2
votes

Using PyGame, I get flickering things. Boxes, circles, text, it all flickers. I can reduce this by increasing the wait between my loop, but I though maybe I could eliminate it by drawing everything to screen at once, instead of doing everything individually. Here's a simple example of what happens to me:

    import pygame, time
    pygame.init()
    screen = pygame.display.set_mode((400, 300))
    loop = "yes"
    while loop=="yes":
        screen.fill((0, 0, 0), (0, 0, 400, 300))
        font = pygame.font.SysFont("calibri",40)
        text = font.render("TextA", True,(255,255,255))
        screen.blit(text,(0,0))
        pygame.display.update()

        font = pygame.font.SysFont("calibri",20)
        text = font.render("Begin", True,(255,255,255))
        screen.blit(text,(50,50))
        pygame.display.update()
        time.sleep(0.1)

The "Begin" button flickers for me. It could just be my slower computer, but is there a way to reduce or eliminate the flickers? In more complex things I'm working on, it gets really bad. Thanks!

4

4 Answers

4
votes

I think part of the problem is you're calling 'pygame.display.update()' more then once. Try calling it only once during the mainloop.

Some other optimizations:

  • You could take the font creation code out of the main loop to speed things up
  • Do loop = True rather then loop = "yes"
  • To have a more consistent fps, you could use Pygame's clock class

So...

import pygame
pygame.init()

screen = pygame.display.set_mode((400, 300))
loop = True

# No need to re-make these again each loop.
font1 = pygame.font.SysFont("calibri",40)
font2 = pygame.font.SysFont("calibri",20)

fps = 30 
clock = pygame.time.Clock()

while loop:
    screen.fill((0, 0, 0), (0, 0, 400, 300))

    text = font1.render("TextA", True,(255,255,255))
    screen.blit(text,(0,0))

    text = font2.render("Begin", True,(255,255,255))
    screen.blit(text,(50,50))

    pygame.display.update()   # Call this only once per loop
    clock.tick(fps)     # forces the program to run at 30 fps.
3
votes

You're updating your screen 2 times in a loop, one for drawing first text(TextA) and one for second text(Begin).

After your first update, only first text appears, so you can't see begin text between first update and second update. This causes flickering.

Update your screen after drawing everything. In your case, remove first pygame.display.update().

2
votes

You're redrawing the content of your entire screen every 0.1 seconds. It's much more common and faster to keep track of the changes you actual make and only update the rects that actually contain changed content. So draw everything outside of your loop and have your events modify the screen and keep track of the rectangles that actually are changed.

So something like this:

import pygame, time
pygame.init()
screen = pygame.display.set_mode((400, 300))
screen.fill((0, 0, 0), (0, 0, 400, 300))
font = pygame.font.SysFont("calibri",40)
text = font.render("TextA", True,(255,255,255))
screen.blit(text,(0,0))
font = pygame.font.SysFont("calibri",20)
text = font.render("Begin", True,(255,255,255))
screen.blit(text,(50,50))
loop = "yes"
counter = 0
dirty_rects = []
while loop=="yes":
    pygame.display.update()
    time.sleep(0.1)
    # Handle events, checks for changes, etc. Call appropriate functions like:
    counter += 1
    if counter == 50:
        font = pygame.font.SysFont("calibri",20)
        text = font.render("We hit 50!", True,(255,255,255))
        screen.blit(text,(50,100))
        dirty_rects.append(Rect((50,100),text.get_size()))
1
votes

Pygame has a Buffer system to avoid flickering, so you should draw them as you are doing, but update only once at the end:

...
while loop=="yes":
    screen.fill((0, 0, 0), (0, 0, 400, 300))
    font = pygame.font.SysFont("calibri",40)
    text = font.render("TextA", True,(255,255,255))
    screen.blit(text,(0,0))

    font = pygame.font.SysFont("calibri",20)
    text = font.render("Begin", True,(255,255,255))
    screen.blit(text,(50,50))

    pygame.display.update()   # only one update

    time.sleep(0.1)

And Pygame has a Clock Class that is better than time.sleep(0.1) if you wan't to keep a framerate.