Pygame0
Prerequisites for understanding these articles.
You will need to have Python 2.7 and the most recent version of Pygame installed on your computer to run the game we are making! I am using Python 2.7.7 and Pygame 1.9.1 in this article.Basic knowledge of Python 2.7 is necessary to follow the progress of our game and to implement the various tools of Pygame in your own projects. If you have no prior experience using Python I highly recommend going to these sources to learn the basics.
- Python: Learn Python in One Day and Learn It Well. Python for Beginners with Hands-on Project. (Learn Coding Fast with Hands-On Project Book 1)
- Codecadamy
- MIT 6.00x
- Python-Guide.org
Following the progress.
Every Pygame progress article I post will build upon the previous articles and will include new features, improvements, and updates to the current state of the code up to that point. To download the current state of the code click the link in the 'links relating to this topic' sidebar and then download the folder that corresponds with the number of the article you are currently viewing (e.g. pygame0, pygame2, etc.). For this article the folder you would download would be pygame0. This folder includes the current state of all the .py files (including any additions or modifications made in the current article), and all images and sounds used in the game.We have plenty of work to do!
These articles have a lot of catching up to do! The most recent version of the game includes an inventory for the player (e.g. picking up the coins in the image above), a perspective view system which allows items to appear closer or farther from the screen relative to eachother, a combat system with health and mana, and AI interaction that allows the player to talk to other characters!Let's jump right into it!
The best way to learn Pygame is to just build a project and research as you go! So that is exactly what we are going to do. Don't be afraid to experiment and tinker with the code at any point in the progress of our game! You'll probably have ideas for features of your own games that I don't cover, and in those cases there is plenty of Pygame documentation out there to help you create what you desire!Start up IDLE and open a new document! The first thing we need to do is import our modules. On lines 1 and 2 of your script type the following:
(2 lines) codebit 1
import pygame, sys from pygame.locals import *
Next we need to set all of our color variables! Skip line 3 and then add the following:
(19 lines) codebit 2
#Colors R G B WHITE = (255, 255, 255) GREEN = (0, 255, 0) BLUE = (0, 0, 255) BLACK = (0, 0, 0) FUCHSIA = (255, 0, 255) GRAY = (128, 128, 128) LIME = (0, 128, 0) MAROON = (128, 0, 0) NAVYBLUE = (0, 0, 128) OLIVE = (128, 128, 0) PURPLE = (128, 0, 128) RED = (255, 0, 0) SILVER = (192, 192, 192) TEAL = (0, 128, 128) WHITE = (255, 255, 255) YELLOW = (255, 255, 0) ORANGE = (255, 128, 0) CYAN = (0, 255, 255)
In Pygame colors are handled by a tuple of three integers between 0 and 255. The first integer represents the amount of red, the second represents the amount of green, and the third represents the amount of blue.
Skip a line and add the following:
(7 lines) codebit 3
pygame.init() DISPLAYWIDTH = 1024 DISPLAYHEIGHT = 683 DISPLAYSURF = pygame.display.set_mode((DISPLAYWIDTH, DISPLAYHEIGHT)) FPS = 30 FPSCLOCK = pygame.time.Clock() pygame.display.set_caption("A Great Game!")
In the first line pygame.init() is called. Always call pygame.init(), and always call it before any other Pygame modules are used, it initializes all the pygame modules automatically. Otherwise, you would have to initialize every Pygame module by hand, which can be confusing and cumbersome.
DISPLAYWIDTH and DISPLAYHEIGHT are two variables that represent exactly what you would expect! They are used as the width and height of the display created on the following line. DISPLAYSURF is the variable we set as our display. We do this by setting DISPLAYSURF equal to pygame.display.set_mode((DISPLAYWIDTH, DISPLAYHEIGHT)), which is how we create a new display surface object in Pygame. pygame.display.set_mode is always used to create the window that everything in our game will be presented (blited) on.
Later in the code we need a clock to handle our FPS variable, and to delay the code so it does not exceed the number of Frames Per Second we established. The FPSCLOCK will do this for us. We set FPSCLOCK equal to pygame.time.Clock() which is a Pygame object that can be used to track an amount of time. The Pygame documentation shows all that can be done with the Clock() object, including the .tick() method we will use later to limit the runtime speed of the game to our FPS variable!
Last, and probably least interesting, we have the pygame.display.set_caption() function. This is a simple function of the display module that sets the caption at the top of the window we create to "A Great Game!". Go ahead and change it up to whatever caption you like! I can't think of any good game titles...
Skip a line and then add two comments similar to these:
(2 lines) codebit 4
#Player class------------------------------------- #Put player class here!
Now would probably be a good time to save our game progress! Save this script in a folder all by itself and call it 'MainGame.py'. Once saved, find the folder on you computer and create a folder next to your Python file called 'characters'. In this folder you will save the character images of our level we are about to create! Download the character pictures from the 'characters' folder inside the 'Pygame0' folder here. Be sure to save the images in their correct file!
Next we need to assign the string name of all the images we want to use to a single variable. We do this by adding the following to our script one line after pygame.display.set_caption("A Great Game!"):
(1 line) codebit 5
charImgs = ('characters/guy0.png','characters/guy1.png','characters/guy2.png')
Now for the fun part of our game, THE GAME LOOP!

(4 lines) codebit 6
def level(): moveX,moveY=0,0 #Game Loop level()
Now we can add our game loop! Adjust the level function so it has the components of the loop exactly like this:
(11 lines) codebit 7
def level(): moveX,moveY=0,0 while True:#Game Loop for event in pygame.event.get(): if event.type==pygame.QUIT: pygame.quit() sys.exit() #More events DISPLAYSURF.fill(WHITE)#background color---- FPSCLOCK.tick(FPS) pygame.display.update()
If nothing is happening when you click run module, make sure you call the level function at the bottom of the script, as shown in codebit 6. If you are getting an error when the module is run, make sure your level function definition looks exactly like what is shown in codebit 7, and that you are using a valid color!
Now lets examine the loop line-by-line so we can understand what is happening.
Our loop begins on line 2 of our level function. Anything that we put inside of this will be read with every iteration of the loop and will effect our game, and what is presented on screen. If, elif, and else statements help us control what our game does under certain conditions with every iteration of the while loop. This loop is infinite because it will always be True, luckily we programed our game to shut off using a feature of Pygame called events.
(5 lines) codebit 8
for event in pygame.event.get(): if event.type==pygame.QUIT: pygame.quit() sys.exit() #More events
The event loop should be read like this, for every event happening right now, check if it is this event. If it is this event, do this. pygame.event.get() gets every event happening right now; such as any buttons pressed on the keyboard, mouse movement and clicks, or any adjustments to the game window we are trying to make. For every event we get from pygame.event.get(), we run it through an if statement to check if it is this event. If it is the event we want, we run the code inside the if statement. In this case we are looking for the event pygame.QUIT(Pressing the red X at the top of the game window) and when Pygame sees that this event has occurred we want our window to close! Which is what pygame.quit() and sys.exit() do.
Always call pygame.quit() and sys.exit() in that order to end your game! It is the most decisive and absolute way to shut down your game quickly!
The comment 'More events' at the end of the for loop is a note for us to return back to later in this article, when we are implementing character movement in our game.
We now exit our event loop and return to finish our game loop.
(3 lines) codebit 9
DISPLAYSURF.fill(WHITE)#background color---- FPSCLOCK.tick(FPS) pygame.display.update()
First, we use the .fill() method of our surface object to fill the entire screen with the color WHITE. .fill() takes an argument of any valid RGB color value! Next, we keep track of our time, and slow the game down to the Frames Per Second we set earlier, by using the .tick() method of our FPSCLOCK object we created. .tick computes how many milliseconds have passed since the previous call. The FPS variable we pass as an argument of the .tick method will delay the game to keep the game running slower than the given ticks per second (30).
Finally we reach the end of our first iteration of our game loop! Everything we just did the computer will do hundreds of times per second, or as fast as we allow it (30 FPS). The last line of our game loop updates the display of our game window and shows us everything that has changed since the last time pygame.display.update() was called! Right now not much changes in our game with each iteration, but soon we will add a character we can move around and play with that will demonstrate how seamless the update process is!
Now it's time to put some life into our game...
You know what will take our game to the next level? Gameplay! There are many things I would like to add to our game before it's complete, but for the sake of time we will just focus on adding a character with keyboard controlled movement. This will be the only major feature added in this article.Let's meet our star!

If you havn't already, please download the character images. Save the character images in a file titled 'characters' in the same place you saved your 'MainGame.py' file. Download the character pictures from the 'characters' folder inside the 'Pygame0' folder here. Be sure to save the images in their correct file!
If you have any prior experience with Pygame you would probably know that Pygame has a complex, but extremely helpful, tool for interacting objects. This tool is called a sprite. We will need to use sprites for other features in our game to work properly (e.g. combat, inventory pick-ups) and we will even need our character to be a sprite. However, in order to keep this article from being to long or complicated I am not going to explain the sprite features of our character yet. All you will need to know is how to use classes, objects, methods, and understand that our Player sprite inherits its features from a built in Pygame object called pygame.sprite.Sprite. Just be aware that if you plan on having multiple objects interacting in your game, sprites are the way to go, and we will spend plenty of time discussing them in a later article.
I will give you the class definition, and how to define each method for this object, in the remainder of this article. I will explain what each method does, but I am going to wait until the next article to explain how it does it. Scroll back up your script to where we typed the comments from codebit 4. In place of the comment that says 'Put player class here!' define the Player class and its __init__ method like this:
(15 lines) codebit 10
#Player class------------------------------------- class Player(pygame.sprite.Sprite): def __init__(self,x,y,images): pygame.sprite.Sprite.__init__(self) self.loadImages(images) self.image = self.i0 self.imageNum = 0 self.timeTarget = 7 self.timeNum = 0 self.rect = self.image.get_rect() self.rect.x=x self.rect.y=y self.left = False self.moving = False

(12 lines) codebit 11
def loadImages(self, images): self.i0 = pygame.image.load(images[0]).convert_alpha() self.i1 = pygame.image.load(images[1]).convert_alpha() self.i2 = pygame.image.load(images[2]).convert_alpha() self.images = (self.i0,self.i1,self.i2) def update(self, movex, movey): self.moveSprite(movex, movey) self.render() def draw(self, Surface): Surface.blit(self.image,(self.rect.x,self.rect.y))
The next two methods are the methods we will use to foster interaction between this object and the game loop.
The update method takes in two arguments movex and movey. These arguments are then passed to a method we have not yet defined, called moveSprite, which will move the object on the X and Y axis by the amounts passed in movex and movey respectively. The update method also calls the render method which we will soon define. The render method chooses which image to use when the object's image is displayed (blited) to the screen by the draw method defined next.
Bliting basically means copying an objects image and displaying it on the display surface for the player to view.
The draw method takes in one argument; the surface to which this object will be drawn onto. This method then calls that surface's blit method which takes two arguments. The first, the image to be blited to the surface (The image our render method will choose). The second, the coordinate value of where on screen the image will be blited (our object's X and Y values).
Before we define the other methods our player object needs, let's put together what we have so far!
Let's the player object to a variable and put the finishing touches on our game loop!
On the line following where we assigned the charImgs variable, which should be a few lines after the final method definition in our Player object, add the following:
(1 line) codebit 12
player = Player(700,500,charImgs)#starting(x,y)coords
Next type the following between DISPLAYSURF.fill(GREEN) and FPSCLOCK.tick(FPS) near the end of our game loop:
(2 lines) codebit 13
player.update(moveX,moveY) player.draw(DISPLAYSURF)
However, in order for this update method to work we need to have some way of changing the values moveX and moveY to something other than 0 when the player is ready to move! Try to guess what feature of Pygame we will use to do this...
In our event loop, where we left off with the comment 'More events', add the following:
(18 lines) codebit 14
if event.type==pygame.KEYDOWN: if event.key==pygame.K_a: moveX = -5 if event.key==pygame.K_d: moveX = 5 if event.key==pygame.K_w: moveY = -5 if event.key==pygame.K_s: moveY = 5 if event.type==pygame.KEYUP: if event.key==pygame.K_a: moveX=0 if event.key==pygame.K_d: moveX=0 if event.key==pygame.K_w: moveY=0 if event.key==pygame.K_s: moveY=0
First, we see that if the event.type is equal to KEYDOWN we check to see which key is being pressed with another test. We test the 'w' 'a' 's' and 'd' keys to see if they are being pressed. If so we assign moveX or moveY a new value depending on the condition. Remember that moveX and moveY are then passed to our player objects's update method, which moves the player that many pixels on either the X or Y axis.
Second, we check if the event.type is equal to KEYUP. If you think about it, this makes sense because we want to stop the player from moving in a direction when he takes his finger of the key that corresponds with that direction.
For those interested, a full list of Pygame event keys can be found here.
It's the final stretch! Of the first lap...
All we have left to do is add our final player class methods! Hopefully you have made it this far because we are about to see the fruit of our labor.Don't even wait for me! Add this after the player draw method from codebit 11 and run it to see for yourself what life we have created:
(35 lines) codebit 15
def moveSprite(self, movex, movey): oldX = self.rect.x oldY = self.rect.y self.rect.x += movex self.rect.y += movey self.movementCheck(oldX, oldY) def movementCheck(self, oldx, oldy): if self.rect.x == oldx and self.rect.y == oldy: self.moving = False else: self.moving = True if self.rect.x > oldx: self.left = False elif self.rect.x < oldx: self.left = True def render(self): self.chooseImageNum() if self.left == True: self.image = pygame.transform.flip(self.images[self.imageNum], True, False) else: self.image = self.images[self.imageNum] def chooseImageNum(self): if self.moving == True: self.timeNum += 1 if self.timeNum >= self.timeTarget: if self.imageNum == 1: self.imageNum = 2 else: self.imageNum = 1 self.timeNum = 0 else: self.imageNum = 0
If it did not work as expected, make sure everything is indented correctly and that you did not miss any of the 15 codebits throughout this article.
The moveSprite method simply takes in two arguments, movex and movey, and moves the object by that many pixels on the X or Y axis. It also then calls the next method we defined named movementCheck. This method takes an X and a Y value and compares it to the object's current X and Y position to see if the object is moving, and which direction it is moving.
The final two methods, render and chooseImageNum, work together to get the image ready to be drawn by our draw method.
There you go! The first major feature of our game has been implemented! Take a break and enjoy what you have accomplished so far. I will go more in detail on the Player methods in the next article and expand upon what we have built so far in Pygame.
- If you just can't wait for more Python/Pygame knowledge, check out some of these awesome books!
- Game Development with Python
- Program Arcade Games: With Python and Pygame
- Python: Learn Python in One Day and Learn It Well. Python for Beginners with Hands-on Project. (Learn Coding Fast with Hands-On Project Book 1)
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.