Games with Turtle Graphics
In the previous post — Animation with Turtle Graphics — I explained that animation is simply simulation, making stuff appear real. You create the appearance of real and continuous movement by quickly showing a series of slightly-different images. I then introduced the idea of creating animations with Python’s turtle graphics module. In this post, I’ll use a simple example to explain how to use animation as well as user interaction and data to create a game with turtle graphics.
Note: Turtle graphics isn’t the best tool for creating great games (use e.g. Unity for that), but it is an excellent tool for learning about how games fundamentally work.
Games are simulations
Video games simply simulate things. They simulate:
- A system that the player can understand and play with, e.g. a character that can jump on platforms;
- Motion graphics, to illustrate that system and its behaviour to the player;
- Control, by having player input affect the state of the system.
It’s possible for a video game to simply be a toy, for undirected play. It would then be called a sandbox-style game, as, just like sand in a sandbox or sandpit, it invites you into an activity, but doesn’t direct you in any way. But most games usually do direct the player towards some goal or outcome. They do this through the gameplay, which is how the player plays and experiences the game as a result of the combination of all the different elements of the game, like the graphics, the story that the game tells, the game mechanics or rules, the interaction that the game allows, the goals to try to achieve, etc.
In this post, I’ll explain how to use turtle to simulate a 2-player Pong style game, where the goal is to keep a bouncing ball from going past you, and to get it to go past the opposing player instead:
In a two-part follow-up post I’ve written the code that implements the design, but it’s important to first understand how to approach the different aspects of such a game, which is what I’ll explain below.
To create the game, we need to simulate the following:
- The system: The game consists of a single ball, and a paddle (or bat) for each player to control. The ball and paddles are limited to an area on the screen, which I’ll call the playing field. The ball constantly bounces around the playing field, and the players move their paddles up and down, to deflect the ball and keep it from going past them horizontally. When the ball ‘hits’ a paddle, or the top or bottom of the playing field, it must ‘bounce off’. If the ball goes past a paddle horizontally to collide with the left or right side of the playing field, a point is given to the other player, and the game continues with a new ball.
- Motion graphics: There is one ball that moves constantly, two paddles that move when the correct keys are pressed, and the score which changes when a point is scored.
- Control: Player 1 has a designated keyboard key that moves their paddle up, and another that moves their paddle down. Player 2 also has two keys for moving their own paddle up and down.
When using turtle graphics to implement this game, it’s easiest to use a number of different turtles for the different elements:
A dedicated turtle to draw the outline of the playing field. As the playing field doesn’t move around, this drawing would never change.
Another turtle to display the score. A variable would be used to keep track of each player’s score. A turtle has a function for drawing text on the screen, and it would be used to draw the score (the values of the score variables). When a point is scored, the previous score drawing is cleared from the screen, before the new score is drawn, much like a very slow animation.
Another turtle represents the ball, and therefore should look like one so that the user can understand the system. The ball starts at the middle of the playing field, and gets animated as moving across the screen in some direction, just like we did with the square in the previous post. When it reaches the top or bottom of the playing field, or the front of a paddle, it ‘bounces off’. This is simulated by changing the direction in which the ball is moving (or more precisely, the direction that the animation makes the ball appear to move in). If the change of direction is done at the correct time (exactly when the ball appears to collide with something), and in such a way that it resembles how a ball might bounce off of a flat surface in the real world (obeying the law of reflection), it creates the illusion that the ball has been deflected:
- Bouncing off the top or bottom of the playing field is simulated by simply flipping the vertical direction of the ball’s motion, so that if it was busy moving left and up for example, it would then continue moving left and down.
- Bouncing off the front of a paddle can be simulated by flipping the horizontal direction of the ball’s motion, so that if it was busy moving left and up for example, it would then continue moving right and up.
If the ball reaches the left or right side of the playing field, the opposing player’s score increases by one point, and the ball instantly continues its movement at the middle of the playing field so that it looks like the game has continued with a new ball.
Each paddle is also represented by a turtle with a rectangular shape. Each is positioned horizontally at either the far right (for player 1) or the far left (for player 2) of the playing field. Player 1 can use the up ↑ and down ↓ arrow keys on the keyboard, and player 2 the w and s keys, to move their respective paddles up and down. If the paddle reaches the top of the playing field, it shouldn’t be able to move up further, and the same goes for moving down at the bottom of the playing field: this can be done by simply ignoring that player’s key-press at the appropriate time.
As the ball must appear to be constantly moving, we repeatedly need to display the screen as a frame many times a second, with the ball having moved a small amount between each frame or time-step — in other words, we’re simply animating the movement of the ball, as explained in the previous post. We can keep track of the direction and speed of the ball’s movement by giving that movement a horizontal and vertical component, which we keep track of with a variable or two. At each time-step, if the ball doesn’t appear to collide with anything, we simply add the horizontal component to the ball’s horizontal position, and add the vertical component to the ball’s vertical position to move the ball to its new position.
If a player pushes a designated key, we also move their paddle a small amount in the up or down direction as appropriate — that is, unless it’s not allowed to move further up or down, and then we simply ignore that key-press by not doing anything about it so that the paddle stays put at the bottom or top of the playing field.
And lastly, to implement all the other logic for the game, at each time-step we simply have to check if the position of the ball makes it appear to be colliding with something, and take appropriate action if it does. At each time step, does the ball appear to be colliding with:
- The top or bottom of the playing field? Then we flip the vertical direction of the ball’s motion, so that in the next frame, the ball will ‘move’ in the opposite vertical direction;
- A paddle? Then we flip the horizontal direction of the ball’s motion, so that in the next frame, the ball will ‘move’ in the opposite horizontal direction;
- The left or right side of the playing field? Then we add one to the other player’s score, write the new score to the screen, and move the ball to the middle of the playing field again on the next frame, to simulate a new ball;
That’s all there is to it: implementing the simple algorithm gives you a Pong-style game.
I hope it has become clear how a game goes about simulating an understandable, interactive system, illustrated to the user through animated graphics. By simply changing the underlying data and corresponding graphics (and sound or whatever else) at the appropriate time, it gives the impression of a real system. In the next post I show exactly how to implement the algorithm above using Python’s turtle graphics, but why not first give it a go yourself?