I'm making a pygame game. I have 3 surfaces: gameDisplay (where the character and background is directly rendered to), guiSurf and invSurf
I have a clock made in core pyhon which displays the game time with the pygame font. I blit the clock to guiSurf and then in my gameloop I blit guiSurf and invSurf to gameDisplay. My problem is that the clock leaves a mark from where it was. IE when it changes from '07:00' to '07:01', the '01' is ontop of the '00' which shouldn't be there. I would post the code but theres like 400 lines. Does anyone have any idea what I may of done wrong. Link to a picture of the clock
Make sure you 'clear' the area of where the time is being printed by blitting another image over the spot where the text is. When you draw your surfaces to the screen it simply becomes one 'surface' that is always drawn until overwritten by something else. You need to clear this surface before you blit something else to it, otherwise you get the effect you see. By simple calling display_name.fill((0,0,0)) at the beginning of every game tick you will 'clear' the screen and then redraw your text onto it without the spillover effect. Of course you will have to reblit everything to the screen every tick, but this should not be a problem unless you need to blit thousands of items. If you do not wish to redraw everything, then blit a small rectangle over the text and then redraw it, and your issues should be solved.
I hope this helps you with your issue and happy coding!
Visibly, the clock is blitted twice on the guiSurf. And I guess it keeps stacking the previous image of time (7:00, then 7:01, then 7.02 and so on). You need to clear the surface holding the clock before drawing time into it : clock_surf.fill(clearcolor, clock_surf.get_rect()).
Related
I am making a game using python and pygame. I had a problem a few days ago that I needed to give my games a functionality of being resized and maintain the aspect ratio. Also everything on the screen is resized proportionately. And luckily I got a quick solution to create two different pygame surfaces. One is the screen visible to the user and the other is to manage the blitting functionality. Actually, fake screen has everything blitted and then it itself is blitted to the main screen by using
main_screen.blit((pygame.transform.scale(fake_screen, main_screen.get_rect().size), [0, 0]).
The main problem is that now since the MOUSEBUTTONDOWN events are getting triggered on the main screen and not on fake screen, But
the clicks are getting processed according to the fake screen. This means that when I click on a button after resizing, the button appears to be their but actually its at its respective position on the fake screen. This makes all the buttons loose their functionality after the VIDEORESIZE event. Can anyone help me out with this? I hope that I was able to explain.
Easy answer: use the pygame.SCALED display flag.
It resizes the main screen for you and the mouse events too, without your program needing to know anything about it. Documented on this page: https://www.pygame.org/docs/ref/mixer.html
Using this means you wouldn’t need to use a fake screen at all, or do anything at all with scaling on your end.
DIY answer:
If you still want to control the scaling yourself, you just have to scale the mouse events along with the screen. Like scale then the opposite way you scale the fake screen.
In your case it looks like that would involve dividing the mouse event x by the ratio between fakescreen width and screen width, and same with y (with heights ofc).
I got a very easy solution to this myself. I just after getting mouse x and y coordinates, changed them to proportionately corresponding points. With a simple math. I mean, if x coordinate is 15% of main screen width, then convert it to 15% of fake screen width. This way, the fake screen will get properly scaled coordinates. The mathematical equation can be as follows:-
mouse_x = mouse_x/(xd/100)
mouse_x *= 10
mouse_y = mouse_y/(yd/100)
mouse_y *= 6
Here xd and yd are width and height of the resizable main screen respectively. And 10 and 6 are 1% of 1000 and 600 which are the width and height of the fake screen.
This solved my problem and game is now working perfectly.
Thank You.
When using python and pygame: after loading the screen with the background image and blitting new objects (Text, circles, rectangles, etc.), is there a way to save the modified screen so as to be recalled later in the program? Specifically, I am setting the background and blitting new objects and would like to save the screen image with all of the blits in intact so it can be used later in the program as a new background upon which sprites can be manipulated. Any suggestions welcomed!
Blitting works both ways, meaning you can blit something onto the display screen, but you can also blit the screen onto another surface. So simply make a new surface the same size of your display surface and blit the screen onto that surface for later use.
found a solution and it works better than I expected:
after blitted my raw background onto my surface and then adding numerous circles, rectangles and text to make an image with multiple dial, gauges and labels I ran the following:
pygame.display.update()
window = pygame.display.set_mode((800,480),0,32)
pygame.image.save(TFT,"screen_update.jpg")
the new image is saved to disk(XDcard on my RPi2) as "screen_update.jpg"
then I simply change the name to "ANAL_update.jpg" and use that as the background on my next program run. I commented out all of the code used to create the rectangles, circles and labels and it works. I will add an selectable "update" routine to the program and move all of extra drawing and labelling to that routine to be used when I wish to change the layout of he background. I like the fact that the program creates a new updated file that just needs to be renamed for use and for copying the background to other machines.
note: This is working on my RaspberryPi 2B with HDMI output to a 42" HD tv for development, but it is intended to run on an RPi3B with he official RPi 7 inch TFT display. Thanks to all of you that responded and to the others who left pertinent code for previous questions similar to mine.
I made a 2D project with a lot of tile sprites, and one player sprite. I'm trying to get the camera to follow the player, and for the most part it's working. However, there's one problem:
If you go to the edge of the map, it scrolls normally, but instead of the black background, it displays copies of the sprites on the edge of the map instead of the background (black). It has the same problem if I leave some squares empty, when I move it displays a copy of the tile that was previously there.
The camera works like this:
Select sprites that should be visible
Do sprite.visible = 1 for them, and sprite.visible = 0 for all other sprites
Set the position sprite.rect of all sprites to coords - offset
Update the screen (I use flip(), because the camera moves every turn, so the whole screen has to be updated every turn)
All DirtySprites have dirty = 2.
Does anyone know why it's displaying copies of the sprites on the edge instead of the background?
Help would be appreciated!
Unless you manually clear your screen surface, flip will not change its content.
Thus, if you neglect to draw to a certain location, it will remain the same.
If you want to get rid of this effect, usually called "hall of mirrors", you will have to keep track of what portions of the screen have not been drawn to yet and draw over these yourself.
It may be easier to define background sprites around your map's contours and block your camera from going off too far.
Since you use a "dirty/clean" approach to only redrawing what's changed, you won't have the option to just fill the whole screen surface before you draw your frame, because that would draw over anything that's stayed the same since the last frame.
I need help with a program I'm making. It's a version of Conway's Game of Life.
This game is right now made out of 3 files: main.py, cellBoard.py, cell.py
main.py takes care to instance cellboard and make it update its data, give it mouse input, and tell it to draw itself (an instance of the pygame surface is given to it, which handles it to the cells which are the actual ones that draw themselves)
cellboard.py creates a list of cells based off their size and the screen's size, to fill it properly. It's a 2D list. When it creates the cells it sets their state (alive currently) and handles them an instance of its instance of the original surface instance.
cell.py contains all the things a cell can do: die, live, be toggled, be drawn.
In fact, when I need to draw the whole board I just call cellBoard's own draw() and it should take care of calling each cell's draw. And it does.
The execution gets to the point where the cell should be drawn (checked with prints) and the pixel filling function is executed (using a for loop to cover an area). But nothing is actually drawn to the screen, or at least nothing is visible.
I have no idea what is causing this. I checked the code multiple times, I've even rewritten the whole program from scratch to make it more tidy (and I had the same problem as now)
What is causing this? My idea would be that somehow the instance of surface Cell gets is not good anymore to work because something happened to it (it goes through cellboard before getting to each cell, could that be the problem?)
Here's the source code (all 3 files, they are very short and barebones so they should be easy to read) http://dl.dropbox.com/u/2951174/src.zip
Thanks in advance to anyone who feels like helping. I need to complete this project very fast so your help would be greatly appreciated.
First of a quick suggestion:
People are much more likely to help you if they don't have to download a zip file, next time just post the code parts you suspect not to work.
Anyways, problem seems to be in your main loop:
#Keyboard events
events = pygame.event.get()
for event in events:
if event.type == pygame.QUIT:
running = 0
#Mouse events
#todo
#Grid update <------- here you update the grid and the cells are being drawn
cb.draw()
#Graphical output <------------ here you're filling the WHOLE screen with white
screen.fill(THECOLORS["white"])
pygame.display.flip()
You need to move your screen.fill call above cb.draw so you don't paint over the cells.
Also in cell.py your drawing code is A) Broken and B) bad.
Instead of setting every pixel on its own, which is slow and in it's current state doesn't draw the cells correctly, you can just as well draw rectangle:
pygame.draw.rect(self.surface, (100, 10, 10), (self.pos[0], self.pos[1], self.size, self.size))
What I am trying to do is create a viewport to view a small portion of a background. (And later put sprites in).
However the problem I have noticed is there seems to be an issue of the background blurring when it starts moving. I was not sure if this is because blitting is slow or because of a problem in the code. I was looking for examples on how others blit or create scrolling backgrounds and found this article: Scrolling Games
I used their simple example and sure enough the background appears blurry as you scroll (aka blit the background with an offset). I also thought it might be the FPS dropping for whatever reason however it doesn't deviate at all. I can't recall an issue like this with other 2D games. I understand there may be some motion blur due to it constantly shifting. Just wondering if I can do anything to alleviate this. Can someone chime in on anything I may be missing? I would appreciate any feedback or help. Thank you
I couldn't know what caused the problem you faced, but I guess it is related to double buffering.
Did you use at least two surfaces?
# preparing two surfaces in __init__()
screen = pygame.display.set_mode((800,600))
background = pygame.Surface(screen.get_size())
background.fill((250, 250, 250))
# called at every step in main loop
# draw images on the background surface
background.blit(image, position)
....
# blit background to screen
screen.blit(background, (0, 0))
pygame.display.flip()
If images are drawn on the screen surface directly, flicking occurs.
By "blurry" do you mean that the background appears "doubled"? Do you get the same effect when moving a normal-sized (e.g., 64x64) sprite?
If you are seeing double, then it's probably a refresh rate problem. Turning on vsync may help.
What frame rate are you getting?
If you slow down the animation to around 10 FPS, do you have the same problem?