In this tutorial you will learn how to build the game snake. The game is an arcade game and it has very simple logic, which is why it is an ideal example to demonstrate how to build games with Pygame.
The player is represented as snake, which grows if it eats an apple. The goal of the game is to eat as many apples as possible without colliding into yourself. This is very easy in the early phase of the game but is increasingly more difficult as the length of the snake grows.
Getting started: Basic structure and event handling. We define a class Player which holds the players position on the screen and the speed by which it moves. In addition we define the actions a Player instance can do (movements):
classPlayer: x = 10 y = 10 speed = 1
defmoveRight(self): self.x = self.x + self.speed
defmoveLeft(self): self.x = self.x - self.speed
defmoveUp(self): self.y = self.y - self.speed
defmoveDown(self): self.y = self.y + self.speed
A player object can be created and variables can be modified using the movement methods. We link those methods to the events. In Pygame we can get non-blocking keyboard input using this code:
pygame.event.pump() keys = pygame.key.get_pressed() if (keys[K_RIGHT]): print"Right arrow pressed."
The complete code gives us the ability to move the player across the screen:
Building the player (snake) The player controls a snake which has an initial length. This snake is always moving and changes the direction it moves when pressing an arrow key. To do so, update the player class:
classPlayer: x = 0 y = 0 speed = 32 direction = 0
defupdate(self): if self.direction == 0: self.x = self.x + self.speed if self.direction == 1: self.x = self.x - self.speed if self.direction == 2: self.y = self.y - self.speed if self.direction == 3: self.y = self.y + self.speed
defmoveRight(self): self.direction = 0
defmoveLeft(self): self.direction = 1
defmoveUp(self): self.direction = 2
defmoveDown(self): self.direction = 3
and don’t forget to add a delay to the game loop.
import time ... time.sleep (100.0 / 1000.0);
This starts to act more as a snake, but it does not have a base length yet. We keep track of the snakes old positions and move the head of the snake. We also moved the drawing method into the snake. Copy the code and you will have a moving snake:
from pygame.localsimport * import pygame import time
classPlayer: x = [] y = [] step = 44 direction = 0 length = 3 updateCountMax = 2 updateCount = 0
def__init__(self, length): self.length = length for i inrange(0,length): self.x.append(0) self.y.append(0)
defupdate(self):
self.updateCount = self.updateCount + 1 if self.updateCount > self.updateCountMax:
For simplicity sake, we display the apples as green cubes. We have this basic code, but it does not do a lot more than moving the snake and showing the apple:
from pygame.localsimport * import pygame import time
classApple: x = 0 y = 0 step = 44
def__init__(self,x,y): self.x = x * self.step self.y = y * self.step
We have thus to add the game logic. To know if the snakes position matches the apples position, we have to do collision detection. This simply means veryfing that the cordinate of the snake are intersecting with the coordinates of the apple. We create a new method to do that:
defisCollision(self,x1,y1,x2,y2,bsize): if x1 >= x2 and x1 <= x2 + bsize: if y1 >= y2 and y1 <= y2 + bsize: returnTrue returnFalse
It will return True if the coordinates (x1,y1) are intersection with (x2,y2) given its block size bsize. We call this method to determine if the snake collides with the apple. We need to check this for the entire snake and not only for the head, because we do not want the new position of the apple to be somewhere on the snake. We use the same isCollision method to determine if the snake collides with itself (= lose game).
Full source:
from pygame.localsimport * from random import randint import pygame import time classApple: x = 0 y = 0 step = 44 def__init__(self,x,y): self.x = x * self.step self.y = y * self.step defdraw(self, surface, image): surface.blit(image,(self.x, self.y)) classPlayer: x = [0] y = [0] step = 44 direction = 0 length = 3 updateCountMax = 2 updateCount = 0 def__init__(self, length): self.length = length for i inrange(0,2000): self.x.append(-100) self.y.append(-100) # initial positions, no collision. self.x[1] = 1*44 self.x[2] = 2*44 defupdate(self): self.updateCount = self.updateCount + 1 if self.updateCount > self.updateCountMax: # update previous positions for i inrange(self.length-1,0,-1): self.x[i] = self.x[i-1] self.y[i] = self.y[i-1] # update position of head of snake if self.direction == 0: self.x[0] = self.x[0] + self.step if self.direction == 1: self.x[0] = self.x[0] - self.step if self.direction == 2: self.y[0] = self.y[0] - self.step if self.direction == 3: self.y[0] = self.y[0] + self.step self.updateCount = 0 defmoveRight(self): self.direction = 0 defmoveLeft(self): self.direction = 1 defmoveUp(self): self.direction = 2 defmoveDown(self): self.direction = 3 defdraw(self, surface, image): for i inrange(0,self.length): surface.blit(image,(self.x[i],self.y[i])) classGame: defisCollision(self,x1,y1,x2,y2,bsize): if x1 >= x2 and x1 <= x2 + bsize: if y1 >= y2 and y1 <= y2 + bsize: returnTrue returnFalse classApp: windowWidth = 800 windowHeight = 600 player = 0 apple = 0 def__init__(self): self._running = True self._display_surf = None self._image_surf = None self._apple_surf = None self.game = Game() self.player = Player(3) self.apple = Apple(5,5) defon_init(self): pygame.init() self._display_surf = pygame.display.set_mode((self.windowWidth,self.windowHeight), pygame.HWSURFACE) pygame.display.set_caption('Pygame pythonspot.com example') self._running = True self._image_surf = pygame.image.load("block.jpg").convert() self._apple_surf = pygame.image.load("block.jpg").convert() defon_event(self, event): if event.type == QUIT: self._running = False defon_loop(self): self.player.update() # does snake eat apple? for i inrange(0,self.player.length): if self.game.isCollision(self.apple.x,self.apple.y,self.player.x[i], self.player.y[i],44): self.apple.x = randint(2,9) * 44 self.apple.y = randint(2,9) * 44 self.player.length = self.player.length + 1 # does snake collide with itself? for i inrange(2,self.player.length): if self.game.isCollision(self.player.x[0],self.player.y[0],self.player.x[i], self.player.y[i],40): print("You lose! Collision: ") print("x[0] (" + str(self.player.x[0]) + "," + str(self.player.y[0]) + ")") print("x[" + str(i) + "] (" + str(self.player.x[i]) + "," + str(self.player.y[i]) + ")") exit(0) pass defon_render(self): self._display_surf.fill((0,0,0)) self.player.draw(self._display_surf, self._image_surf) self.apple.draw(self._display_surf, self._apple_surf) pygame.display.flip() defon_cleanup(self): pygame.quit() defon_execute(self): if self.on_init() == False: self._running = False while( self._running ): pygame.event.pump() keys = pygame.key.get_pressed() if (keys[K_RIGHT]): self.player.moveRight() if (keys[K_LEFT]): self.player.moveLeft() if (keys[K_UP]): self.player.moveUp() if (keys[K_DOWN]): self.player.moveDown() if (keys[K_ESCAPE]): self._running = False self.on_loop() self.on_render() time.sleep (50.0 / 1000.0); self.on_cleanup() if __name__ == "__main__" : theApp = App() theApp.on_execute()
You learned how to create the game snake in Python along with concepts such as collision detection, image loading and event handling. Many things could be added to this little toy game but this serves as a very simple example. :-)
Thank you for this simple tutorial. I plan program this tutorial, and then learn to further program more complex games. Thank you.
Jacky•Sun, 13 Dec 2015
pygame.error: Couldn't open pygame.png How can i get pygame.png and apple.png?
Frank•Sun, 13 Dec 2015
Hi Jacky, simply take any two images from the web
Jacky•Mon, 14 Dec 2015
Yes,i get it done,thanks a lot!
Trung Le•Mon, 21 Mar 2016
[python] print "x[" + str(i) + "] (" + str(self.player.x[i]) + "," + str(self.player.y[i]) + ")" ^ SyntaxError: invalid syntax [/python] Can you check it? Frank
Frank•Mon, 21 Mar 2016
Chance are you use Python 3.x. I updated the code, it was made for Python 2.7, should work on all Python versions now. Be sure to have the images image_surf and apple_surf, simply 32x32 images in the same directory.
You also need Pygame.
If you are on Ubuntu Linux (Py 2.7), you can simply: [python] sudo pip install pygame [/python]
For Ubuntu Linux (Py 3.x): [python] sudo apt-get install mercurial sudo pip3 install hg+http://bitbucket.org/pygame... [/python]
Hi! Can you explain to me what updateCount and updateCountMax are? I'm having trouble understanding this line of code: if self.updateCount > self.updateCountMax. Why must updateCount be greater than updateCountMax in order for the positions to be updated?
Thanks!
Frank•Wed, 28 Dec 2016
updateCount is a counter. Its simply the update interval, it will update once updateCount is greater than updateCountMax.
Kanav Mahajan•Sun, 07 May 2017
When code compiles a dialog box appears and gets closed straight away. How can I solve this problem? You have suggested another person to download images from net. Those images should be of jpg or png format? And where to put these images?
Frank•Sun, 07 May 2017
Put the image the same directory as your program. Add an if statement to test if the image has been opened. Depending on the platform, but it could be both.
Handuo Wang•2021-11-25T16:19:35.136Z
Thank you for this tutorial. I picked two images and rename each pygame.png and apple.png. But when the program is started, it appears two big image in the area, overlapping, incomplete. What is the error?
Frank•2021-11-25T16:19:36.136Z
Modify the images to be the same size, or change the code to use bigger images.
Leave a Reply:
Thank you for this simple tutorial. I plan program this tutorial, and then learn to further program more complex games. Thank you.
pygame.error: Couldn't open pygame.png
How can i get pygame.png and apple.png?
Hi Jacky, simply take any two images from the web
Yes,i get it done,thanks a lot!
[python]
print "x[" + str(i) + "] (" + str(self.player.x[i]) + "," + str(self.player.y[i]) + ")"
^
SyntaxError: invalid syntax
[/python]
Can you check it? Frank
Chance are you use Python 3.x. I updated the code, it was made for Python 2.7, should work on all Python versions now.
Be sure to have the images image_surf and apple_surf, simply 32x32 images in the same directory.
You also need Pygame.
If you are on Ubuntu Linux (Py 2.7), you can simply:
[python] sudo pip install pygame [/python]
For Ubuntu Linux (Py 3.x):
[python]
sudo apt-get install mercurial
sudo pip3 install hg+http://bitbucket.org/pygame...
[/python]
For other platforms: www.pygame.org
Hi!
Can you explain to me what updateCount and updateCountMax are? I'm having trouble understanding this line of code: if self.updateCount > self.updateCountMax. Why must updateCount be greater than updateCountMax in order for the positions to be updated?
Thanks!
updateCount is a counter. Its simply the update interval, it will update once updateCount is greater than updateCountMax.
When code compiles a dialog box appears and gets closed straight away.
How can I solve this problem?
You have suggested another person to download images from net.
Those images should be of jpg or png format?
And where to put these images?
Put the image the same directory as your program. Add an if statement to test if the image has been opened. Depending on the platform, but it could be both.
Thank you for this tutorial.
I picked two images and rename each pygame.png and apple.png.
But when the program is started, it appears two big image in the area, overlapping, incomplete.
What is the error?
Modify the images to be the same size, or change the code to use bigger images.