PyGame & Python: Writing your first game
Last couple of times when we’ve talked about Game Development with Python or about GameDev for Android Using Python, we’ve received great responce from our and other related communities.
So we begin our small series of articles dedicated to more practical usage of Python in GameDev.
Today we will build a very simple platform game using Python game framework PyGame, and in the next article, we will try to port it to Android!
So what's a "platform game" game exactly? According to Wiki it's a video game which involves guiding an avatar to jump between suspended platforms, over obstacles, or both to advance the game. These challenges are known as jumping puzzles or freerunning. The player controls the jumps to avoid letting the avatar fall from platforms or miss necessary jumps. "
Classical example of platform game is Nintendo’s famous “Mario”, so we wil try to build something similar to it.
Let's start with the basics:
You can find installation instructions on the official PyGame page as well as prebuilt executables for whole variety of Operating Systems.
It wasn't that hard, isn't it?
So now we have PyGame installed, let’s start with importing it into our future project! Simply start your favourite IDE (check out previous article about IDE's for Python) and paste this code into newly created main.py, see details in comment section of the code!
Woah, it’s starting to get hot in here, isn’t it?
Keep in mind: The game will be launched in the cycle (while True), each iteration it is necessary to redraw the background, platforms, monsters, messages, etc. It is important to note that the drawing is a sequence, ie if the first draw of the hero, and then fill the background, the character will not be seen.
Once you will run above code, you will see a window filled with white color
Let's draw a level on existing surface!
How we will do this? We’re choosing the easiest way, we will create a two-dimensional array of m by n. Each cell (m, n) will be a rectangle. Rectangle can contain something or may be empty.
Let's add some more constants:
And a level structure to the 'main' function :
And to the main cycle we're adding a level parser, to convert above drawing into playable level
So what we're doing here is we sorting out the two-dimensional level array, and if there is a symbol "-", then the coordinates
(x * platform_width, y * platform_height), where x, y - is the index in the array of level.
Bold blocks on the background are boring. We need our character that will run and jump on the platforms we’ve just built.
So it's time for some object oriented programming! We will create a class for our hero! For convenience, we will keep our character as a separate file player.py
What so interesting and what to look for in this code?
Let's start with the fact that we create a new class inheriting from another class pygame.sprite.Sprite, thereby we inherit all the characteristics of a sprite. Sprite, according to wiki is a moving the bitmap. It has a number of useful methods and properties.
self.rect = Rect(x, y, width, height) line, we are creating borders of our rectangular character. Using this rectangle we will not only move hero, but also will check(later) it on a collision with other objects.
update(self, left, right)) method is used to describe the behavior of the object. It overrides the parent update(* args) → None. It may be called in groups of sprites.
draw(self, screen) method is used to display the character on the screen. We will lated remove this method to use more convinient way to display the character.
Before defining the level, let's add our hero and variables to move it.
Also, let's add some code to move our charecter at the ‘event' section of our code.
Everything is pretty much self explanatory in this code, if not, please, ask in the comment section
Now, it's time to finally move and draw our charecter! According to drawing rules, you'll need to add this after backgroud and platform drawing
But, if you launch your code, you'll see that our hero moves too quickly, let's add a restriction in the number of frames per second. To do this, after determining the level add a timer
And to make it work, we will add it's parameters to our main cycle
As you may see, if you launch your code, your hero is stuck in the air, to fix this, let's add some gravity and ability to jump! It's kinda boring, but result is totally worth it!
To do so, let's open our old friend player.py and add a little magic there!
What in real life makes jumps possible? Of course it's gravity!. Now converting those values into the code,:
And voi-là, we now have gravity in our game!
Now setting vertical movement speed and a check if we're standing on the floor, cause we can jump only from the floor. All this goes to init method!
Now, right before self.rect.x += self.xvel string, add:
Now, let's forbid our player to fly! After left = right = False line, let's add:
Again, this code is pretty much self explanatory.
To end flying question, let's add some more event checks!
And to ‘update' method, add argument named ‘up'
Final Chapter: Jumping, Movement
How do you know that we are on the ground or other hard surface? The answer is obvious - to check if rectangle(hero) crosses with platforms!
Firstly, we will need to change how platforms are generating ;)
To make our code more readable and clear, let's split each important part of the code to a different files, same as we did with player.py, but now, create platforms.py and move platform creation code there:
Then, create class, that inherits from from pygame.sprite.Sprite
Nothing new here, i think, so let's move on
In addition, we will need to change some parts of main file. Just right befor level array let's add:
We will will use Sprites Group entities to display all the elements of this group. An array of platforms will be used to test for intersection with the platform.
Remember this tricky part?
Now, we will replace it with more readable
What we did is we created an instance of Platform class, and added it to the ‘entities' group of sprites and ‘platforms' array.'entities' part is to ease up blocks display logic, and ‘platforms' part is to check intersection with the player.
Next, move all of the level generation code from the cycle and replace charecter display part
If you'll run the code, you will see that nothing changed, becase we're not checking for intersections with our charecter! Let's fix it!
Getting back to player.py. We can now remove draw method, wohoo! But we will need new method, boo!, let's name it ‘collide'
In this method, we're checking the intersection of the coordinates of the hero and platforms, if any, above described the logic activates.
Well, to make things work, we will need to call this method. Change the number of arguments for update method once again, it now should look like this:
Tip: Do not forget to change method call in the main file.
And some finishing touches:
If the hero moved vertically, we check the intersection of the vertical, moved horizontally and again, checked at the intersection of the horizontal. Let's run our game and see what we've acieved!
That’s all folks, it was a tough one, but it’s your first game!
In the next part of this article, we will try to add android support and maybe some graphics!
Write your questions and feedback in the comment section, and CheckiO team will do the best we can to help you!
Welcome to CheckiO - games for coders where you can improve your codings skills.
The main idea behind these games is to give you the opportunity to learn by exchanging experience with the rest of the community. Every day we are trying to find interesting solutions for you to help you become a better coder.Join the Game