Introduction
Pong is one of the first video games ever published. According to Wikipedia, the game was released in 1972 and very quickly had become successful. It’s really interesting, though, that the game was originally created only for training purposes. And yet, in 2018, this game is still being implemented over and over! Yes, Forty-six years later. I think this fact alone already qualifies to be a legend.
Why is this game being continuously re-implemented? It’s relatively easy and not too time-consuming to implement such a game — but it’s not a 10 liner coding challenge either. Programming this game gives enough room to practice whatever you want, let it be the basics of the programming language you’re learning or a new graphics module to test. And… of course, this is the Pong game! A classic, legendary game, that must be fun to implement it.
I wanted to play a little bit and get familiar with pygame. It was no question for me that Pong is the perfect candidate to grasp the fundamentals of pygame.
PyGame Overview
Pygame is a graphics library for Python that’s leveraging Simple Direct Media (SDL) under the hood. SDL is a low-level, high-performance graphics library written in C. We can also think of Pygame as a wrapper of SDL. It hides the complexity of SDL and provides a simple way to write graphics applications.
How do we install Pygame? Like for any other module, use the utility pip to install it:
$ pip install pygame
Collecting pygame
...
Successfully installed pygame-1.9.4
$
The Source Code of the Game
I published the code to github, you can clone the repository:
$ git clone https://github.com/roberttorok/python-games.git
And start it:
$ cd python-games
$ python pong.py
Deep Dive in the Code
Let's take a look at the code!
Most of the parameters like the screen width and height, the size of the paddles, etc. are extracted as constants since they are referenced at multiple places and are easy to change if needed.
I used two classes to describe the entities in the game:
- Ball
- Paddle
The properties and the functions of the Ball class seem to be fairly easy, however, here is some explanation: The properties directionx and directiony specify the direction of the ball horizontally and vertically. 1 refers to the movement from the left to the right horizontally and from the top to the bottom vertically. -1 is the opposite: From the right to the left horizontally, and from the bottom to the top vertically.
The method flip_direction_x
and flip_direction_y
utilize a little trick: Multiplying the current direction by minus one will result in the opposite direction.
The method throw_in
basically just does what it says; throws in the ball to the screen.
The method move
moves the ball horizontally and vertically with the given speed.
The keep_on_screen
and leaves_screen
methods handle the cases when the ball is leaving the screen. In case the ball tries to escape the field vertically, make it jump back. This is basically equals to flipping the y direction. Leaving the screen horizontally implies that either the player or the computer scores. In this case, we don’t want to have it jump back, we want to throw in the ball again.
The Paddle class has two very important methods to check collision with the ball involving some math. These methods were not really necessary if we had implemented this class by subclassing the Pygame’s sprite class. If that was the case, we would have an out-of-the-box solution to check the collision. However, in order to practice some math too, I decided to perform the collision detection by hand.
Okay, we have well described the entities of the game at this point. But there are still some utility methods before the game loop starts: methods ai_move
and computer_predict
are responsible for performing the computer’s step. It’s very basic, but very accurate: If the constant COMPUTER_MOVEMENT_UNITS
is set too high, it’s basically almost impossible to defeat the CPU. No real machine learning method is used here, though. That would be a very nice challenge! We’ll get back to his game later and try to implement some real AI and Machine Learning solution.
The method display_text
displays the given parameters.
And then the main game loop starts. That could be interpreted as follows:
- Wait 10 ms
- Clear the screen
- Move the ball
- Check if the ball is not leaving the field
- If yes, flip its y direction
- Check if the ball crosses the player's or the computer's goal line
- If yes, check if the paddle is colliding with the ball (which eventually means defending)
- If yes, flip the ball back
- If no, the enemy scores
- If yes, check if the paddle is colliding with the ball (which eventually means defending)
- Increase the ball speed
- Process the user input for moving the paddle accordingly
- Jump to #1
And we've arrived at the end of the source code. I hope that it helped you find and learn something new.