The Mainloop


Let's talk real quick about how a graphics and animations work. When we see animation on-screen, what we're really seeing is the screen being refreshed many, many times a second with a new image. A screen being updated with an image slightly different from the previous can have the illusion of motion.

This means that, for us to have an interactive graphics user interface, all the following must happen in a split second:\

  1. Recieve any inputs, possibly from the user or external sources.
  2. Calculate anything and everything that needs to be calculated, store/update information, etc.
  3. Draw on the display surface with the updated information.

Any graphics interface has the same procedure, as in tkinter and Pygame.

In tkinter, we could call root.mainloop(), give it a timerDelay, and call timerFired after every timerDelay. There wasn't a real, pythonic while loop that was visible.

This is not the case with Pygame. With Pygame, we need to give it a real while loop, and go through the three steps mentioned above. This can get ugly real fast if we're not careful, but with some carefully chosen helper functions in our framework, it can be really clean. Take a look at the following code:

import pygame

pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode((width, height))

running = True
while running:
    time = clock.tick(fps) #similar to timerDelay

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

pygame.quit()

This is the bare-bones of any pygame app. We first set up out display in the first three lines. After our setup, we need to create the loop we've talked about. Generally, we want the loop to run forever, or at least until you tell it to stop. You wouldn't want your graphics window to stop running randomly, right?

So, we create an infinite loop. Instead of doing while True, however, we set a variable, 'running', equal to True, and condition our loop on that. This lets us set 'running' to False anywhere in our code, which will let us break out of the loop.

Inside our loop, we call clock.tick(fps, or frames per second). This sets an upper bound on our frame rate. That is, if we set our fps to be 24, the game will never run faster than 24 frames per second. It also returns the time since the last frame, so you can use the 'time' variable if you need it.

IMPORTANT: clock.tick isn't accurate. While it says our fps can't be any higher than whatever fps we specified, it doesn't mean that our fps will be exactly that. This is especially important if you're making an app that relies on accurate timing, such as an app that needs the screen and music to play in sync.

The next chunk of code gives us the user input. Calling pygame.event.get() gives us a list of all the events that are currently active. Then, inside the loop, we can condition on any event we're interested in. In the example above, we check for pygame.QUIT, which is the exit button on the Pygame window. If the exit button is pressed, running is set to False, we exit the loop, and we quit out of pygame by calling pygame.quit() outside of the loop.

Anywhere else in the loop, we can add code to do things for us.

results matching ""

    No results matching ""