Controlling Your Game's Display Rate
00:00
In the previous lesson, I introduced the idea of using Python objects to represent the things in your game. In this lesson, I’ll talk about controlling the display rate of your game and how that interacts with the perception of speed. Up until now, you’ve been using an uncontrolled game loop that in each iteration calls display.flip()
to push the screen buffer surface to the display.
00:24 Each iteration of the loop will run as fast as your computer will allow. This can be a problem. It means your game will run at different speeds on different computers. That asteroid moving from left to right? If you’re not careful, it will move too fast for the player to react to, and the difficulty of your game will be based on the machine that is running it.
00:44
This problem is solved by using Pygame’s Clock
object, which will put an upper limit on the FPS of your program. To better demonstrate how FPS limits work, let’s step away from the game for a moment.
00:58
This is a standalone script named zoomzoom
. The first few lines here are no different than anything you’ve seen before: setting up Pygame and getting a screen surface to work with.
01:10 What this script will do is show a little red dot that moves from left to right and back again on the screen. You’ll be able to control the speed, represented by how many pixels it moves at a time, and the frame rate.
01:24
The variables here will be used to track where the dot is, which direction it is moving—1
for right, -1
for left—the number of pixels to advance each time, and the frames per second limiter. Line 14 instantiates a Pygame Clock
object.
01:41 This object is the key to controlling the frame rate. Here, I’m just creating it and storing it. It is used further down inside the game loop. Let me just scroll down here.
01:55
Line 21 shows a new way of interacting with user input. You’ve seen the QUIT
event before, but now I’m adding the KEYDOWN
event.
02:04
This event gets fired each time a key is pressed, but only once per press. Holding a key only triggers a single event. If there is a KEYDOWN
event, the next step is to check which key was pushed. For the right arrow, the speed will increase. For the left arrow, the speed will decrease, but never go below zero. For the up arrow, the frame rate will increase. And for the down arrow, the frame rate will decrease, never going below one frame per second.
02:37
With all those events taken care of, the next step is the game logic. Here, I’m calculating the little red dot’s new position based on the old position, the direction, and its speed. Next, so that the dot stays on the screen, I check if the newly-calculated position would be less than 0
. If it is, that would be off the left side of the screen, so I set the new position to 0
and change the direction so the dot is moving to the right. Similarly, I next check if the dot has gone off the right-hand side of the screen. If so, I set its position to the right side of the screen and change the direction to the left. Scrolling the code down some more, and here you see the typical circle drawing code.
03:26
And finally, this is where the FPS restrictor comes into play. The .tick()
method on the Clock
object ensures a maximum frame rate.
03:35
In most games, you’d just hard-code this value to 25
or 30
. Because this is a frame rate demo, I’m passing in the current value of the FPS variable. Note that this is a maximum of the FPS. Setting the FPS to 10,000 won’t make that many frames happen.
03:52
You’re always limited by how fast each iteration of your game loop runs. What the .tick()
method does is slow things down if your game loop executes very quickly, enforcing a maximum frame rate.
04:07
Let’s play around with zoomzoom
a little bit. The little red dot is moving one pixel per iteration, and the frame rate is limited to 30
frames per second.
04:17 Let’s start by increasing the frame rate.
04:27 I’ve hit the up arrow many times now. It’s moving a tiny bit faster, but not by much. I’ve hit the upper limit on what my computer can do in each iteration.
04:37
Having a frame rate of 50
frames per second really is no different than 40
in this case. Let’s slow it down again.
04:52
At 20
frames per second, the dot is starting to move more slowly.
05:02
At 5
frames per second, you’re really starting to feel the pain. Okay, back up to 30
frames.
05:16 And let’s crank the speed up a bit.
05:21
At a speed of 5
, each loop iteration moves the dot forward by five pixels. The motion isn’t great, but it is still almost fluid.
05:32 Now let me slow the frame rate down.
05:41
At 10
FPS, you can really see the stutter. This lower frame rate exposes how the movie is made. You no longer feel like there is fluid motion. The dot is skipping steps.
05:52 Remember, this is the same pixel speed as before, but the illusion of animation is breaking down.
06:11
Cranking the frame rate up to 60
and you get some nice clean motion. Even if I increase the speed to 20
,
06:23 this still looks like it is moving rather than stuttering.
06:30 It isn’t perfect, but our eyes expect a bit of blur on things moving quickly, so our brain compensates.
06:39 A quick note here: You’re watching a video. Don’t act surprised, I can see you doing it. The video itself has a frame rate. Although I’ve cranked the frame rate of the game up to 60, the video’s own frame rate will limit what you can see.
06:53 This is why in older movies you would sometimes see strange patterns when they recorded CRT computer monitors or the spokes on a wheel. The frame rate of the movie recording interacts with the refresh rate of the monitor or the rotation rate of the wheel and creates odd visual effects.
07:11
Hopefully, that provides some clarity on how the frame rate affects the animation of your game. Let me quickly show you how to use the clock within SpaceRocks
.
07:23
Nothing earth-shattering here. Modify the .__init__()
method to create and store a Pygame Clock
. Scrolling all the way down. Then use the .tick()
method on the clock
object at the bottom of your ._draw()
method.
07:39 This will be the last thing to run in your game loop before the next iteration. I won’t bother demoing this at this point, there’s nothing new to see on the screen, but now your game will behave the same on computers of different speeds.
07:53 You’re steadily progressing forwards towards the game part of writing your game. In the next lesson, I’ll add some movement controls for the spaceship.
Become a Member to join the conversation.