To kick off the year 2024 on SSaurel’s Blog, what better way than to code the classic game of Pong in Python?

That’s what I suggest you do in this step-by-step tutorial, using the Tkinter library for the user interface. This will show you how to program a simple game in Python and manage user interaction.

Let’s start by designing the Ball

To design our ball, we need to define its position and velocity. We’ll then need to define a method for modifying the position of the rectangle representing this ball as its coordinates change.

When the ball touches one of the two horizontal edges, we’ll need to restart the ball from the center of the screen. This will be done in a restart method, and we’ll use the random method in Python’s Random library to randomly choose an x and y direction.

Finally, the bulk of the work remains to be done in the ball’s move method.

We’ll have to deal with several scenarios. The first is when the ball touches the outer edges at height. In this case, we’ll need to reverse the direction of the ball in ordinate. This is done by multiplying the current y velocity of the ball by -1.

The second is when the ball comes into contact with the right or left paddles. In this case, you need to invert the current velocity on the x-axis. This is done by multiplying the velocity at x by -1.

In the third and fourth cases, points are scored for the player on the left and the player on the right. If the ball touches the edge on the left, the player on the right scores 1 point. If the ball touches the edge on the right, the player on the left scores 1 point.

Finally, we play the x and y positions of the ball, adding the current velocity.

This gives us the following for the Ball object:

Let’s move on to designing the Paddle

This Paddle object will have x and y coordinates, as well as a width and height. Each paddle is assigned a score initialized to 0. We also initially create the rectangle representing the paddle and store its id returned by the Tkinter library’s create_rectangle method. This id will then be used to modify the paddle’s coordinates.

The draw method is used to modify the paddle’s coordinates using this id.

The top and down methods move the paddle up and down respectively. The VELOCITY constant is used for displacement. This constant will also be used whenever ball positions are modified.

Finally, we use the collideright and collideleft methods to test whether the paddle and ball collide to the right and left respectively. In the event of a collision, we return True, which will then be used in the Pong class we’ll define for the Pong game.

This gives us the following code for our Paddle object:

Time to design the Pong Game using Ball and Paddle objects

With our two objects modeled above, we can move on to modeling the Pong object.

The Pong object will store the scores of the two Paddles, as well as the objects drawn on the canvas to represent these scores. These will be deleted before each rewrite when the scores are updated. This avoids having to delete the entire canvas each time the scores are updated.

A Boolean is set to True when the game is rendering.

Four Booleans are used to define whether the up/down keys chosen for each player are pressed or not. If they are pressed, the paddles are activated. The Paddle and Ball objects are created in the Pong object constructor. We call the canvas’s pack method and then call the drawmiddlelines, drawbord, and move methods respectively to start the game.

The drawmiddlelines method draws the mid-screen line vertically.

The drawboard method draws all game elements. Note the small workaround used with the _exit method of the os library to ensure that the application stops when the Tkinter game window is closed.

The drawpoints method is used to draw the scores of two players on the screen.

The move method will be called every X milliseconds to update the state of our Pong game. We’ll use a Timer object from Python’s Threading library to handle this repetitive call. In the method, we check whether it’s necessary to move the paddles. If so, we act accordingly.

After calling the ball’s move method, we retrieve the returned state. If the state is True, this means that the ball must be restarted from the center of the board. To do this, we call the restart method of the Pong object, within which we call only the restart method of the Ball object. So why a separate method? To improve the game in the future and add more behaviors to restart. You could choose to emit a sound at this point…

As for the keypress and keyrelease methods, they are associated with the keyboard events <KeyPress> and <KeyRelease>. This makes it possible to manage several keyboard keys at the same time. We choose the z / s keys for the left paddle and the o / l keys for the right paddle.

Finally, the killtimer method will be used to end the rendering phase and cancel the timer if it’s running.

This gives us the following code for the Pong object:

Assembling objects for the Pong Game

The final part of the program simply consists of creating the root of the UI by calling the TK method of the tk object. The instance of the Pong game is created by passing the board size and margin as parameters. These are defined as constants at the start of the program.

We then bind the <KeyPress> and <KeyRelease> events to the UI root and call the keypress and keyrelease methods of our Pong object instance respectively. Finally, don’t forget to listen for the WM_DELETE_WINDOW event to react to the click on the cross in our Tkinter window. This ensures that the timer is properly killed and that the process associated with our Pong game is stopped.

This gives us the following complete code for our Pong game in Python with a Tkinter UI:

You can see the result of our Pong Game below:

You can also watch this tutorial on YouTube on the SSaurel channel here:

At the end of the program code on Github, I’ve also suggested some ideas for improvements, such as defining a limit at which the game is over. You can also define an AI for the second paddle. Finally, there’s inevitably some work to be done to improve the dependencies between each of the objects. This will allow you to code your own Python Pong game.

It’s up to you to code.