Python is one of the simplest and straightforward programming languages, that make it easy for the developer to put logic simply, without worrying about the complex syntax of the programing language. And what could be more logical than writing the code for a game in a programming language?
When it comes to development with Python, rather than building the complete project from scratch we as a Python developer uses open source libraries and frameworks to build our projects. With that, we do not have to reinvent the wheel and get through our project easily.
And this is also one of the main features of Python why many developers love to code with Python. The plethora of libraries and frameworks really help the Python developers to get quickly started with the Project. Although Python has many applications, but in the Gaming development industry, developers do not prefer Python to build real-world or complex games, because of its speed.
Still, we have many libraries present in Python, which can be used in Game Development with Python. Amongst all the libraries "PyGame" is the most popular Python Game Development library. And in this tutorial, we will learn what is Pygame in Python, how to get started with PyGame and we will also build a snake game using Python and PyGame library.
What is Pygame?
Writing the Code from scratch for a software or application could be a nightmare for any developer. And for Game development where we have multiple things going on, such as keypress events, graphics, display movement, sound, etc. there we need some tools that can handle all these things, so we can only focus on the logic of the Game, rather than writing multiple lines of code just to load an image or print graphics on the screen. Here comes the Python "Pygame" library, as the name suggests, it is a Python module that is generally used to build games using Python.
It is an open-source third-party library, and it contains many useful functions and modules for game development. With Pygame the developer does not need to worry about drawing graphics, playing sound, key events, or loading images on the screen.
Apart from all the modules and functions provided by the Pygame library, there are many features and functions it misses. It does not support any inbuilt feature for drag and drop, and Physics. A new Python learner who is just getting started with Python intermediate programming can learn and use Pygame to built logic for Games.
Get Started With Pygame
The first step toward building games using Pygame is installing the Pygame for your Python environment. To install Pygame we can use the Python pip install terminal command.
pip install pygame
After installing the Pygame library we can start writing our first game script with Python and Pygame.
How to Make Game with Python: A Snake Game with Python and Pygame
We all have played the simple snake game, where the snake eats an apple or prey which increases its length and speed. And if the snakehead collides with its body or wall the game gets over. To build the game we will create a directory by the name
Snake Game
where we will store our game
main.py
file with other resources such as
snake block
,
game title logo
, and
apple
images. Our Working directory will be in the following order.
Snake Game:.
????main.py
????resources
apple.png
game_icon.png
snake_block.png
[caption id="attachment_12019" align="alignleft" width="110"]
game_icon.png[/caption] [caption id="attachment_12020" align="alignleft" width="96"]
snake_block.png[/caption] [caption id="attachment_12020" align="alignleft" width="96"]
apple.png[/caption]
You can also download these images and store them in the resources directory. Now let's open your favorite Python IDE or text editor and start writing code in
main.py
file. We will start with importing the required modules.
import pygame
import time
import random
Both
random
and
time
are the Python's inbuilt modules, and in the game, we will be using these modules for time delay and generating random coordinates for the apple. The code for the complete game is more than 250 lines so it would be great that we divide the complete code into multiple functions or modules. It will make the code more readable, and reusable. After importing the important modules let's write the snake movement functions that will be responsible for the changing direction of the snake movement. The snake can move in four directions up, down, left, and right so we need to define 4 functions.
# snake movement
def move_left():
global direction
direction="left"
def move_right():
global direction
direction="right"
def move_up():
global direction
direction="up"
def move_down():
global direction
direction="down"
In all the movement functions we are accessing the
direction
identifier with
global
keyword because we are changing the
direction
global variable identifier inside the functions and we want to reflect that changes outside the function too. To know more about how the global and local scope variables work in Python
click here
.
Python is an interpreted programming langauge so it is very important to define the functions in a sequential order before we call them. That's why we are defining the helper functions first so we can call them in the upcoming code section.
When we play the game we also get a scoreboard that keeps updating when some event occurs. So for our snake game let's define a function
player_score
that will display the player's live score on the top right corner of the screen.
# the player score
def player_score():
my_score = pygame.font.SysFont("Calibri",20).render(f"Player Score: {snake_length}", True, (255, 255, 255))
# show player score on the top right corner
screen.blit(my_score, (700, 10))
The
pygame.font.SysFont()
method defines the font of the text and its size. The
render()
method renders the message on the screen, and it accepts the color code in RGB format. In our game, we have provided the white color with
(255, 255, 255)
color code. While playing the game, the player may get out for various reasons, such as when the snake hit the walls or itself or the player try to quit the game by pressing the escape button, there we need a function that gets invoke and show the player its final score and automatically quit the game after 4 seconds. For such functionality let's define a
game_over()
function
# function when the game is over
def game_over():
# change the background color
screen.fill((255, 255, 255))
# the Game over message
my_score = pygame.font.SysFont("Calibri",40).render(f"Game Over Your Score: {snake_length}", True, (0, 0, 0))
screen.blit(my_score, (150, 350))
pygame.display.update()
# wait for 4 seconds and close the game
time.sleep(4)
exit(0)
The
screen.fill()
method will fill the screen with the specified RGB color
(255, 255, 255)
(white in our case).
pygame.font.SysFont()
function will set the font of the text. The
render()
function print the text on the screen. The
blit()
function print the render message on the specified x and y coordinates. The
pygame.display.update()
function will update the screen with the specified
fill()
function color. The
sleep(4)
function will delay the code execution for 4 seconds. The
exit(0)
function will stop the program execution close the program. Let's also define dedicated functions that will draw the snake blocks and apple on the screen, so we do not have to write that code again and again in the program, whenever we need to display the snake and apple on the screen.
# a function to draw the snake on the screen
def draw_snake_block():
screen.fill(BACKGROUND_COLOR)
# print all the snae block on the screen
for i in range(snake_length):
screen.blit(snake_block, (snake_block_x[i], snake_block_y[i]))
# update the screen
pygame.display.update()
# draw the apple on the screen
def draw_apple():
screen.blit(apple, (apple_x, apple_y))
pygame.display.update()
The
draw_snake_block()
and
draw_apple()
functions will draw the snakehead, its body, and apple with every iteration of the game running. The game runs in multiple frames and these two functions will help us to draw the snake and apple in every frame. In the Snake game, the snake gets automatically starts walking in the pressed direction. Now we also need to define a function
snake_walk()
that will specify the snake path walk.
def snake_walk():
# access the global variables
global direction
global snake_block_x
global snake_block_y
global snake_length
"""
when the head direction change
the body the snake will follow its previous
snake block
"""
for i in range(snake_length-1,0,-1):
snake_block_x[i]= snake_block_x[i-1]
snake_block_y[i] = snake_block_y[i-1]
# change the snake head direction
if direction=="up":
snake_block_y[0]-=block_pixel_size
if direction=="down":
snake_block_y[0]+=block_pixel_size
if direction=="right":
snake_block_x[0]+=block_pixel_size
if direction=="left":
snake_block_x[0]-=block_pixel_size
# draw the snake with every iteration of the game running
draw_snake_block()
In the
snake_walk()
function we are changing the head position of the
snake_block_x
and
snake_block_y
coordinates based on the current direction. And inside the for loop, we are just specifying that the body blocks of the snake must follow its previous block. And with each iteration, we are drawing the new coordinates of the snake blocks with
draw_snake_block()
function. With this function, we will get a moving snake on the screen. Let's also define a function that checks if the snake ate the apple or not. This function will return a boolean value that we will use later in the
run()
function.
# function to check if the snake head eat the apple
def did_snake_eat_apple():
if snake_block_x[0]>=apple_x and snake_block_x[0]< apple_x+block_pixel_size:
if snake_block_y[0]>=apple_y and snake_block_y[0]<apple_y+block_pixel_size:
return True
return False
The
did_snake_eat_apple()
check if the head position of the snake block is colliding with the coordinates of the apple coordinates. When the snake eats an apple we also need to increase the length of the snake and the overall speed of the snake's walk. For that, we can define a function
increment_snake_length()
.
# function to increase the snake length
def increment_snake_length():
# access the global snake features
global snake_length
global snake_block_x
global snake_block_y
global SNAKE_SPEED
# increase the snake length by One
snake_length +=1
# add a new random data in the snake x and y coordinates list
snake_block_x.append(-1)
snake_block_y.append(-1)
# increase the snake speed
if SNAKE_SPEED > 0.2:
if snake_length %2 ==0:
SNAKE_SPEED-=0.1
The
append()
method will add -1 as a new element or snake block to the snake x and y coordinate blocks. However, the coordinates will be overwritten by the
snake_walk()
function. Because soon the body blocks update their position with each iteration and they follow the coordinates of the snakehead block. There are two ways the player can lose the game, one is by body collision and the second is the snake collision. The body collision occurs when the snakehead
collides
with its body, and the wall collision occurs when the snakehead collides with the walls. Let's define two functions
snake_collision()
and
wall_collision()
that will over the game when the snake hits the walls or itself.
# function for snake collision
def snake_collision():
''' if the snake head collide with the
snake body
close the game
'''
for i in range(1,snake_length):
if snake_block_x[0]>=snake_block_x[i] and snake_block_x[0]< snake_block_x[i]+20:
if snake_block_y[0]>=snake_block_y[i] and snake_block_y[0]<snake_block_y[i]+20:
game_over()
# function for the snake-wall collision
def wall_collision():
# if snake head hit left wall or right wall
if snake_block_x[0]<0 or snake_block_x[0] >=screen_size[0]:
game_over()
# if the snake head hits the up or down wall
if snake_block_y[0]<0 or snake_block_y[0] >=screen_size[1]:
game_over()
Both
snake_collision()
and
wall_collision()
functions call
game_over
function when the if the condition gets True. Now let's define the run() function that will run our game in multiple frames, and manage all the above-defined functions.
def run():
# access the global apple x and y coordinates
global apple_x
global apple_y
#run the game until the user click on the close button
game_running = True
while game_running:
# loop through all the game events
for event in pygame.event.get():
# check if the user click the close button
if event.type == pygame.QUIT:
game_running=False
# snake control system
if event.type == pygame.KEYDOWN:
# if player press escape the game ends
if event.key == pygame.K_ESCAPE:
game_over()
# to move left
if event.key == pygame.K_LEFT:
if direction in ["up", "down"]:
move_left()
# to move right
if event.key == pygame.K_RIGHT:
if direction in ["up", "down"]:
move_right()
# to move up
if event.key == pygame.K_UP:
if direction in ["left", "right"]:
move_up()
# to move down
if event.key == pygame.K_DOWN:
if direction in ["left", "right"]:
move_down()
snake_walk()
draw_apple()
# check if the snake eat the apple
if (did_snake_eat_apple()):
# set new coordinates for the apple
apple_x = random.randint(1, 29)*block_pixel_size
apple_y = random.randint(1, 29)*block_pixel_size
# draw a new apple
draw_apple()
# increasee the snake length
increment_snake_length()
# check if the snake head collide with its body
snake_collision()
# check if the snake collide with the walls
wall_collision()
# update the palyer score
player_score()
# update the screen
pygame.display.update()
# the speed of the snake movement
time.sleep(SNAKE_SPEED)
Mostly all the
run()
function statements are inside the
while game_running
statement. And each iteration of this while loop defines a single frame. The
pygame.event.get()
function returns an iterator of events which generally represent the keys press by the user. The
event.type
represents the type of the event. The
pygame.QUIT
occur when the user clicks on the window close button. The
event.key
property represents the key pressed by the user. Using this property we called the movement functions of the snake. Now let's define the main section of our program.
if __name__ =="__main__":
#Initialize Pygame
pygame.init()
# width and height of the screen window (w:h)(900:700)
screen_size = width, height = 900, 700
screen = pygame.display.set_mode(screen_size)
# title and icon of the screen window
pygame.display.set_caption("Snake Game")
icon = pygame.image.load("resources/game_icon.png")
pygame.display.set_icon(icon)
#set the color of the screen window (R,G,B)
BACKGROUND_COLOR = (0,0,0) #black
screen.fill(BACKGROUND_COLOR)
# load the snake block on the screen
snake_block = pygame.image.load("resources/snake_block.png").convert()
# convert the snake block to 20X20 pixels
block_pixel_size = 20
snake_block = pygame.transform.scale(snake_block, (block_pixel_size, block_pixel_size))
#load apple on the screen window
apple = pygame.image.load("resources/apple.png").convert()
# set the apple size to 20X20 pixels (similar to the snake block size)
apple=pygame.transform.scale(apple, (block_pixel_size, block_pixel_size))
# initial coordinate of the apple block
apple_x = 200
apple_y = 100
# initial snake head coordinate
snake_block_x=[100,]
snake_block_y=[100,]
# initial length of the snake
snake_length =1
# intial direction of the snake movement
direction ="right"
# initial snake speed
SNAKE_SPEED = 1
# place snake block on the window screen
screen.blit(snake_block, (snake_block_x[0], snake_block_y[0]))
# place apple on the window
screen.blit(apple, (apple_x, apple_y))
# update the window screen to render the snake block
pygame.display.update()
# call the run function
run()
The
pygame.init()
method initialize the pygame object, and it is very necessary to write this statement. The
display.set_mode()
function specifies the screen size of the window. The
display.set_caption()
specify the title of the screen window. The
image.load()
function load the image in this program. The
display.set_icon()
specify the window icon. The
fill()
function fill the background of the window with the specified RGB color. The transform.scale() function scale the image into specified pixel size (width, height).
apple_x,
and
apple_y
identifiers specify the initial coordinates of the apple on the screen.
snake_block_x,
and
snake_block_y
lists represent the coordinates of the snakehead its body. The blit() method renders the images on the screen. The update method is important to print the images on the screen. That's all with the coding, now put all the code together and execute.
Snake Game With Python and Pygame
import pygame
import time
import random
# snake movement
def move_left():
global direction
direction="left"
def move_right():
global direction
direction="right"
def move_up():
global direction
direction="up"
def move_down():
global direction
direction="down"
# the player score
def player_score():
my_score = pygame.font.SysFont("Calibri",20).render(f"Player Score: {snake_length}", True, (255, 255, 255))
# show player score on the top right corner
screen.blit(my_score, (700, 10))
# function when the game is over
def game_over():
# change the background color
screen.fill((255, 255, 255))
# the Game over message
my_score = pygame.font.SysFont("Calibri",40).render(f"Game Over Your Score: {snake_length}", True, (0, 0, 0))
screen.blit(my_score, (150, 350))
pygame.display.update()
# wait for 4 seconds and close the game
time.sleep(4)
exit(0)
# a function to draw the snake on the screen
def draw_snake_block():
screen.fill(BACKGROUND_COLOR)
# print all the snae block on the screen
for i in range(snake_length):
screen.blit(snake_block, (snake_block_x[i], snake_block_y[i]))
# update the screen
pygame.display.update()
# draw the apple on the screen
def draw_apple():
screen.blit(apple, (apple_x, apple_y))
pygame.display.update()
def snake_walk():
# access the global variables
global direction
global snake_block_x
global snake_block_y
global snake_length
"""
when the head direction change
the body the the snake will follow its previous
snake block
"""
for i in range(snake_length-1,0,-1):
snake_block_x[i]= snake_block_x[i-1]
snake_block_y[i] = snake_block_y[i-1]
# change the snake head direction
if direction=="up":
snake_block_y[0]-=block_pixel_size
if direction=="down":
snake_block_y[0]+=block_pixel_size
if direction=="right":
snake_block_x[0]+=block_pixel_size
if direction=="left":
snake_block_x[0]-=block_pixel_size
# draw the snake with every iteration of the game running
draw_snake_block()
# function to check if the snake head eat the apple
def did_snake_eat_apple():
if snake_block_x[0]>=apple_x and snake_block_x[0]< apple_x+block_pixel_size:
if snake_block_y[0]>=apple_y and snake_block_y[0]<apple_y+block_pixel_size:
return True
return False
# function to increase the snake length
def increment_snake_length():
# access the gloabl snake features
global snake_length
global snake_block_x
global snake_block_y
global SNAKE_SPEED
# increase the snake length by One
snake_length +=1
# add a new random data in the snake x and y coordinates list
snake_block_x.append(-1)
snake_block_y.append(-1)
# increase the snake speed
if SNAKE_SPEED > 0.2:
if snake_length %2 ==0:
SNAKE_SPEED-=0.1
# function for snake collision
def snake_collision():
''' if the snake head collide with the
snake body
close the game
'''
for i in range(1,snake_length):
if snake_block_x[0]>=snake_block_x[i] and snake_block_x[0]< snake_block_x[i]+20:
if snake_block_y[0]>=snake_block_y[i] and snake_block_y[0]<snake_block_y[i]+20:
game_over()
# function for the snake-wall collision
def wall_collision():
# if snake head hit left wall or right wall
if snake_block_x[0]<0 or snake_block_x[0] >=screen_size[0]:
game_over()
# if the snake head hits the up or down wall
if snake_block_y[0]<0 or snake_block_y[0] >=screen_size[1]:
game_over()
def run():
# access the global apple x and y coordinates
global apple_x
global apple_y
#run the game until the user click on the close button
game_running = True
while game_running:
# loop through all the game events
for event in pygame.event.get():
# check if the user click the close button
if event.type == pygame.QUIT:
game_running=False
# snake control system
if event.type == pygame.KEYDOWN:
# if player press escape the game ends
if event.key == pygame.K_ESCAPE:
game_over()
# to move left
if event.key == pygame.K_LEFT:
if direction in ["up", "down"]:
move_left()
# to move right
if event.key == pygame.K_RIGHT:
if direction in ["up", "down"]:
move_right()
# to move up
if event.key == pygame.K_UP:
if direction in ["left", "right"]:
move_up()
# to move down
if event.key == pygame.K_DOWN:
if direction in ["left", "right"]:
move_down()
snake_walk()
draw_apple()
# check if the snake eat the apple
if (did_snake_eat_apple()):
# set new coordinates for the apple
apple_x = random.randint(1, 29)*block_pixel_size
apple_y = random.randint(1, 29)*block_pixel_size
# draw a new apple
draw_apple()
# increasee the snake length
increment_snake_length()
# check if the snake head collide with its body
snake_collision()
# check if the snake collide with the walls
wall_collision()
# update the palyer score
player_score()
# update the screen
pygame.display.update()
# the speed of the snake movement
time.sleep(SNAKE_SPEED)
if __name__ =="__main__":
#Initialize Pygame
pygame.init()
# width and height of the screen window (w:h)(900:700)
screen_size = width, height = 900, 700
screen = pygame.display.set_mode(screen_size)
# title and icon of the screen window
pygame.display.set_caption("Snake Game")
icon = pygame.image.load("resources/game_icon.png")
pygame.display.set_icon(icon)
#set the color of the screen window (R,G,B)
BACKGROUND_COLOR = (0,0,0) #black
screen.fill(BACKGROUND_COLOR)
# load the snake block on the screen
snake_block = pygame.image.load("resources/snake_block.png").convert()
# convert the snake block to 20X20 pixels
block_pixel_size = 20
snake_block = pygame.transform.scale(snake_block, (block_pixel_size, block_pixel_size))
#load apple on the screen window
apple = pygame.image.load("resources/apple.png").convert()
# set the apple size to 20X20 pixels (similar to the snake block size)
apple=pygame.transform.scale(apple, (block_pixel_size, block_pixel_size))
# initial coordinate of the apple block
apple_x = 200
apple_y = 100
# initial snake head coordinate
snake_block_x=[100,]
snake_block_y=[100,]
# initial length of the snake
snake_length =1
# intial direction of the snake movement
direction ="right"
# initial snake speed
SNAKE_SPEED = 1
# place snake block on the window screen
screen.blit(snake_block, (snake_block_x[0], snake_block_y[0]))
# place apple on the window
screen.blit(apple, (apple_x, apple_y))
# update the window screen to render the snake block
pygame.display.update()
# call the run function
run()
Output
Wrapping Up!
In this Python tutorial, we learned what is Pygame and how can we use it to build simple games in Python. If you are into Game Development then Python is not an ideal language, although we can run the game build on Pygame and Python on Android devices using pgs4a, it is not suggested to use Python for complex game development. It's fun to know how to use Libraries like Pygame and TKinter to implement graphics and game logic using Python. You can also convert the above snake game main.py file into a window executable exe file. To know how to convert a Python program to executable windows exe file click here .
People are also reading:
Leave a Comment on this Post