This question already has answers here:
Making the background move sideways in pygame
(2 answers)
How to scroll the background surface in PyGame?
(1 answer)
How to move the background image with keys in pygame?
(1 answer)
Pygame : Two layered scrolling background, can you help me?
(1 answer)
Closed 2 years ago.
I'm trying to convert a simple game written in pygame in pyglet.
I almost figure out everything, but now I'm facing this situation,
I have a background sprite like this example:
In my pygame code I use to write this to let it scrolls smoothly in the background:
base_shift = self.graphic.IMAGES['base'].get_width() - self.COMMON_CONST['screenWidth']
while True:
base_x = -((-base_x + 3) % base_shift)
self.screen.blit(self.graphic.IMAGES['base'], (base_x, y))
Basically the image is longer than the actual screen and once it passes the delta value between image X and screen X, the image is set to 0 again.
I'm trying to do the same in pyglet inside the def update(self, dt): function but I have no idea exactly how to do it. I mean I understand the meaning of dt but still.. To move the image now I do something like this:
def update(self, dt):
self.base.x -= 15 * dt
Of course this will continue to move and it does not reset his position.
How can I replicate the behavior that I have done in pygame?
thanks
UPDATE
I try this code:
def update(dt):
self.base.x = -((-(self.base.x - 15 * dt)) % base_shift)
It seems to work but it's not smooth when is back to 0 is not perfect aligned.
UPDATE/2 TEMPORARY SOLUTION
I finally went to another completely different solution. I split the image in a single pattern something like this:
and then I repeat it many times to fill the screen width plus 2. Then I move all of them and when the first goes completely out of the screen size, I remove from the array and add a new one.
I don't know if there is a better solution so far is ok.
Related
This question already has answers here:
Why is nothing drawn in PyGame at all?
(2 answers)
Closed 7 months ago.
I was trying to create a small ping-pong game with python and pygame, but I run into a huge problem: it doesnt work.
My code opens a window, but doesn't fill it. I've tried different variants of solving, but nothing seems to help. And I tried to compile this code in online compiler (Replit), but it doesn'tseem to work there neither.
import pygame
#screen initializing
WIDTH, HEIGHT = 900, 500
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('Ping-Pong')
for i in range(1000):
screen.fill((200, 200, 200))
this code just opens a black window, no matter what number I write in. What can cause fill() function to not work?
Add pygame.display.update() at the end to update the screen
This question already has answers here:
How can I crop an image with Pygame?
(4 answers)
How to blit from the x and y coordinates of an image in Pygame?
(1 answer)
Closed 2 years ago.
Pixel-perfect collisions from multi-sprite image
I want to do pixel-perfect collision checks. I have a sprite with 6 frames in PNG format with a transparent background, but they're all on a single spritesheet. (The 'enemy' sprites have 2 frames each.) I can animate them and move them fine.
How can I make a pygame surface object from only part of a loaded image? I suppose I could load each sprite frame individually, but this is laborious and doesn't seem like good coding.
More Info
I can turn the whole spritesheet into a mask easy enough as follows (originally in a spritesheet class but simplified here):
# Load image
sheet = pygame.image.load("spritesheet.png")
# Create mask
sheet_mask = pygame.mask.from_surface(sheet)
I could simply use the rect of the current frame to detect collisions, but this will be very unsatisfying because collisions would seem to happen without contact sometimes. An pygame has this wonderful mask object for this sort of thing.
In each loop of the main game loop I want to check the appropriate frame of one sprite against the appropriate frame of the other. I have been trying to create a mask for each frame then store them in a list.
Use the subsurface() method to get a rectangular subsurface from a pygame.Surface:
sheet = pygame.image.load("spritesheet.png")
rect_area = pygame.Rect(left, top, width, heigth)
sprite_from_sheet = sheet.subsurface(rect_area)
This question already has answers here:
How can I create a text input box with Pygame?
(5 answers)
Closed 3 years ago.
All I need right now is basic text fields and buttons for input in pygames. A text field as some simple structure that I can read into variables, and a button to call a function.
First, I browsed around and found it was not a straight-forward process to create a text field in pygames. Eventually, by cobbling together this wall of code, I became the proud father of one, somewhat broken text field. Then I looked into buttons, and found to some horror that implementing them is even more complicated.
Surely PyGame has some sort of buttons module built in right? No.
Excuse me? I'm not trying to write a whole program just for one button, I just need the interface for a deeper simulation. That's all.
So then I looked into Tkinter, which has very easy-to-understand commands for GUI input. But no, that was also not meant to be.
I don't believe you can embed tkinter in to pygame.
So then I tried PGU, but found a stunning lack of any straight-forward examples of how to actually use it for what I need (simple text fields and buttons). When I tried looking for one, I found this piece of wisdom.
Are there any good, modern widget toolkits for Pygame? No. Every year someone makes a new Pygame UI library and then abandons it after a few versions
So if that was true, how is anyone supposed to get anything done with this language? What exactly is the best practice for a simple textfield and simple button in a pygame environment?
yes - pygame is barebones "we control the pixels" - and has been around a lot of time, and itself looked like abandoned for a lot of time (it was just in late 2016 that it would install clean on Python 3, for example). So, in the meantime pygame looked abandoned people moved away.
For the time being, you have to try your luck mining a usable toolkit from here:
https://www.pygame.org/wiki/gui
The PGU toolkit listed there, as you noted, seems quite complete - bar examples on how to build simple widgets to interact with an existing Pygame codebase. All the examples assume one wants to just have an stand alne gui application for form filling, which, I agree, is quite inapropriate: if one wants this kind of application, just use Tkiner, Qt or create a web app.
It turns out, however, that using a standalone widget in an existing pygame window is quite simple. Despite all the library examples calling the .run method, which is the spoiler part, since nce you call run the PGU app takes over and there is no way to run your code back, save for callbacks. However, the run method itself consist of a very simple infinite loop, calling the app's loop method. You just have to put a call to app.loop in all frames of your own pygame loop and have the widgets working.
It will swallow pygame events, however - if you want to treat event while you are displaying widgets, you should dispatch all events to app.event and call app.update instead of calling app.loop. It is trivial once you look at the source code for the app class at https://github.com/parogers/pgu/blob/master/pgu/gui/app.py
So, a complete example for using a text-input can be:
import pygame
from pgu import gui
SIZE = W, H = 800, 600
def bouncing_rect(screen):
surf = pygame.Surface((50, 50))
rect = surf.get_rect()
surf.fill((255, 0, 0))
vx, vy = 10, 10
while True:
screen.blit(surf, rect)
new_surface = yield rect
if new_surface:
surf = new_surface
rect.width = surf.get_width()
rect.height = surf.get_height()
rect.x += vx
rect.y += vy
if rect.right > W or rect.left < 0:
vx = -vx
rect.x += vx * 2
if rect.bottom > H or rect.top < 0:
vy = -vy
rect.y += vy * 2
def main():
screen = pygame.display.set_mode((SIZE))
app = gui.Desktop()
txt = gui.Input()
app.init(widget=txt, screen=screen, area=pygame.Rect(50, 50, 200,25))
bouncing = bouncing_rect(screen)
previous_value = ""
font = pygame.font.SysFont(name="Sans", size=30)
while True:
screen.fill((0,0,0))
rect = next(bouncing)
app.loop()
if txt.value != previous_value:
previous_value = txt.value
rect = bouncing.send(font.render(txt.value, True, (255, 255, 0)))
pygame.display.update([rect])
app.repaint()
pygame.display.flip()
pygame.time.delay(30)
try:
main()
finally:
pygame.quit()
(I just made the bouncing object as generator function using the "send" method, since there are very few examples of this pattern, but it could be a class just the same - if it were a common pygame.Sprite child class, I'd just call "update" instead of using next/send. )
It's extremely painful to redraw each image everytime the screen is cleared.
import pygame
from pygame.locals import *
T = pygame.display.set_mode((500,500))
M = pygame.image.load("test.jpg")
X = 0
Y = 0
while True:
X += 1
Y += 1
# Other sprites are here which are also redrawn every time loop runs.
# Other code is here too, this is just a little part of it to help explain my problem
T.fill((0,0,0))
T.blit(M,(X,Y))
pygame.display.flip()
In the above code, I am loading the background image in M Variable, everytime I clear the screen to update the position of my sprites, I also have to redraw the background image which is causing severe FPS drops.
Anyway I can prevent the Background image from being cleared whenever I am using T.fill((0,0,0)) ?
First, try to convert the background image. Images should usually be converted with convert or convert_alpha to improve the performance.
M = pygame.image.load("test.jpg").convert()
Second, if the background image has the size of the screen you can omit the line T.fill((0,0,0)), since the background fills the screen anyway.
Third, if the background isn't scrolling and you only need to update some portions of the screen every frame, you can try to use pygame.display.update() instead of pygame.display.flip(). Pass a single rect or a list of rects to pygame.display.update to tell it which parts of the screen should be updated.
I'm not sure if these measures will improve the performance drastically. Pygame is rather slow because it still relies on software rendering.
Sidenote, use descriptive variable names instead of T, M, etc..
I am using python 2.7, and im using pygame to make a basic game.
(code can be found here: http://github.com/ProgrammerKid/snake)
(snake.py is my main file)
My game was initially supposed to mock the snake game, but it turned out to be more like pacman... so my problem is that since in pygame, the position of an image is always set to the top left corner of the image.... is there was i can make it the center of the image...
because the position of the killer/alien is at the top left, and same with the pacman/snake... so the two objects would literally have to be overlapping for the alien to kill the pacman.... i want it so that they only overlap a little....:
check out this picture:
http://i.stack.imgur.com/N88GX.png
see: Pygame Rect Reference
you probably already know:
imageObject = pygame.image.load(filename)
rect = imageObject.get_rect()
Now try:
rect.center = (newX, newY)
Or, better:
rect.move(xDistance, yDistance)
Good Luck!