JustToThePoint English Website Version
JustToThePoint en español
JustToThePoint in Thai

Creating games with Python

Pygame is a cross-platform set of Python modules designed for creating video games and multimedia applications. It is intended to be challenging and fun.

We are going to create the snake game. The player controls our snake. The player loses when the snake runs into the screen border, the ghosts, or itself. He should attempt to eat fruits by running into them. Each fruit item makes the snake longer and increases its speed, so avoiding collusion becomes progressively more complicated.

We will create a class Game, so our main function will be quite simple:

if __name__ == '__main__':
    game = Game() # We create an instance of our class Game.
    game.run() # We call its method run() so we can play our game.

Let’s create our class Game, edit pysnake.py:

class Game:
    InitialSpeed = 0.25 # This is the initial speed of the game
    EXIT_VOLUNTARY = "Exit_Voluntary" # The game is used by the user voluntarily
    EXIT_LOSS = "Loss" # The user has lost 
    def __init__(self):
        pygame.init() # It initializes all imported pygame modules
        pygame.display.set_caption("Snake Game") # It sets the current window caption.

        pygame.mixer.init() # pygame.mixer is the pygame module for loading and playing sounds. pygame.mixer.init initializes the mixer module.
        self.play_background_music() # It is self-explanatory, it plays a background music. 

        self.surface = pygame.display.set_mode((1000, 800)) # It initializes a window or screen for display. It returns a display Surface.
        self.snake = Snake(self.surface) # Our class Game has an instance of the Snake class. It represents the snake and we passed the display surface as a parameter.
        self.snake.draw() # We draw the snake.
        self.apple = Apple(self.surface) # Our class Game has an instance of the Apple class, too.
        self.apple.draw()
        self.ghosts = [Ghost(self.surface, self.apple.x, self.apple.y)] # We will also have a list of ghosts and initialize it with one ghost.
        self.ghosts[0].draw()
        self.speed = self.InitialSpeed # It initializes the speed of the game.
        self.font = pygame.font.Font("resources/Halloween Morning.ttf", 30)

The font module allows for rendering TrueType fonts into a new Surface object. It creates a new Font object from a file located in the resources folder. You can get freely downloadable fonts in DaFont.

        self.clock=0 # It initializes the game's clock.
        self.interval=0 # We will use it to increase the game's difficulty.
         
    def add_ghost(self): # Add new ghosts to the game.
        new_ghost = Ghost(self.surface, self.apple.x, self.apple.y) # It creates a new ghost.
        for i in range(0, self.snake.length-1): # It makes sure that the new_ghost is not created where the snake is right now. 
            if self.is_there_collision(self.snake.x[i], self.snake.y[i], new_ghost.x, new_ghost.y):
                new_ghost = Ghost(self.surface, self.apple.x, self.apple.y)
            
        self.ghosts.append(new_ghost) # It adds the new_ghost to our list of ghosts.

    def play_background_music(self): # It plays the background music.
        pygame.mixer.music.load('resources/bg_music.mp3') # pygame.mixer.music is the module for controlling streamed audio. It loads a music file for playback.
        pygame.mixer.music.play(-1, 0) # It starts the playback of the music stream. The music repeats indefinitely if this argument is set to -1.

    def play_sound(self, sound_name): # It plays a sound.
        sound = pygame.mixer.Sound("resources/" + sound_name + ".mp3") # It create a new Sound object from a file.
        pygame.mixer.Sound.play(sound) # It begins sound playback.

    def reset(self): # It resets the game.
        self.snake = Snake(self.surface) # It creates a new snake.
        self.apple = Apple(self.surface) # It creates a new apple.
        self.ghosts = [Ghost(self.surface, self.apple.x, self.apple.y)] # It creates a new list of "nasty" ghosts and initializes it with one ghost.
        self.speed = self.InitialSpeed # It resets the game's speed, the clock and the interval.
        self.clock = 0
        self.interval = 0

    def is_there_collision(self, x1, y1, x2, y2): # It detects if there is a collision or not
        if abs(x1-x2)<SIZE and abs(y1-y2)<SIZE: # SIZE = 40, SIZE is a constant. The apple, snake's parts, and ghost are all 40*40 pixels.
            return True

        return False

    def render_background(self): 
        bg = pygame.image.load("resources/background.jpg") # It loads a new image from a file
        self.surface.blit(bg, (0,0)) # It draws our image (the background) onto the screen. It is positioned on (0, 0) because it is our background image and it will cover the entire surface.

    def play(self): # Let's play.
        self.render_background() # First, we render the background.
        self.snake.slither() # The snake moves or slithers automatically and it draws itself.
        self.apple.draw() # Next, we draw the apple and the ghosts
        for ghost in self.ghosts:
            ghost.draw()
            
        self.display_score() # It displays the score
        pygame.display.flip() # We were drawing on the surface object. This method updates the full display Surface to the screen.

        if self.is_there_collision(self.snake.x[0], self.snake.y[0], self.apple.x, self.apple.y): # If there is a collision between the snake and the apple.
            self.play_sound("yummy") # We play the file yummy.mp3.
            self.snake.growth() # The snake will grow.
            self.apple.move() # The apple will move to another location.
            self.speed -= 0.01

As the snake grows larger, we will increase the game’s speed. The game’s speed is controlled by the line: time.sleep(self.speed) in the game’s run() method. The sleep() function is a handy function. It suspends the execution of the current thread for a given number of seconds.

Next, we will check whether there is a collision or not:

        for i in range(3, self.snake.length): # If the snake collides with itself... 
            if self.is_there_collision(self.snake.x[0], self.snake.y[0], self.snake.x[i], self.snake.y[i]):
                self.play_sound('crash') # ... we play "crash.mp3"
                raise ValueError("Game over! Hit yourself!") # ... and raise an Exception.
        
        for ghost in self.ghosts: # If the snake collides with one of the ghosts ...
            if self.is_there_collision(self.snake.x[0], self.snake.y[0], ghost.x, ghost.y):
                self.play_sound('crash') # we play "crash.mp3"
                raise ValueError("Game over! Ghosts are dangerous!") # and raise an Exception.
        
        if not (0 <= self.snake.x[0] <= 1000 and 0 <= self.snake.y[0] <= 800): # If the snake collides with the wall ...
            self.play_sound('crash') # ... we play "crash.mp3"
            raise ValueError("Game over! Crash against the wall!") # ... and raise an Exception.

    def display_score(self): # It displays the score
        score = self.font.render(f"Score: {self.snake.length}. {self.clock}",True, (0, 0, 0))

Font.render(text, antialias, color, background=None) draws text. The antialias argument is a boolean. If true the characters will have smooth edges. (0, 0, 0) is the color of the text. The score is the snake.length. We display the clock, too.

        self.surface.blit(score, (850,25)) # It draws our score onto the surface.

    def display_game_over(self, mode): # It displays the Game Over screen.
        self.render_background() # First, we draw our background.
        if mode==self.EXIT_VOLUNTARY: # There are two modes. If the mode is EXIT_VOLUNTARY...
            line = self.font.render(f"I am sorry to see you go", True, (0, 0, 0)) # We display a message saying that we are sorry.
            self.surface.blit(line, (200, 300)) # It draws our message onto the surface.
            pygame.display.flip() # We were drawing on the surface object. This method updates the full display Surface to the screen.
            time.sleep(1) # We wait for a second so the user can read the Game Over screen.
            return
            
        d = shelve.open('score.txt') # If the display_game_over is in the mode EXIT_LOSS. We are going to read the best score from the disk using the shelve mode. It implements persistent storage.
        score = 0
        try:
            score = d['score']  # The score is read from disk
            if score < self.snake.length: # If the file already exists and the score saved on the file is lower than our actual result, we save the new record.
            score = self.snake.length
            d['score'] = self.snake.length    
        except KeyError as e: # A KeyError is raised when there is not such a file.
            d['score'] = self.snake.length # We are going to create the file with this game's score.   
            pass   
            
        d.close()
        # We draw three lines, displaying the game's score, the best score, and instructions to play again or exit.       
        line1 = self.font.render(f"Game is over! Your score is {self.snake.length}", True, (0, 0, 0))
        self.surface.blit(line1, (200, 300))
        line2 = self.font.render(f"The best score is {score}", True, (0, 0, 0))
        self.surface.blit(line2, (200, 350))
        line3 = self.font.render("To play again press Enter. To exit press Escape!", True, (0, 0, 0))
        self.surface.blit(line3, (200, 400))
        pygame.mixer.music.pause() # It stops the music playback if it is currently playing.
        pygame.display.flip() # We were drawing on the surface object. This method updates the full display Surface to the screen.

    def display_pause(self): # If the game is paused, we display a message.
        self.render_background() # First, we render the background.
        line = self.font.render("To resume press r. To exit press Escape!", True, (0, 0, 0)) # It display a message.
        self.surface.blit(line, (200, 350)) # It draws our message onto the surface.
        pygame.display.flip() # We were drawing on the surface object. This method updates the full display Surface to the screen.

We are going to show the Game’s run method. This is the game’s core:

def run(self): 
    running = True # Initailly, the game is running and it is not paused.
    pause = False

    while running: # A game loop runs continuously during our game.
        for event in pygame.event.get():

Basically, there are three things to be done. First, we need to handle all events. Pygame handles all its event messaging through an event queue. pygame.event.get() gets events from the queue. Second, we update the game state. Third, we draw the game state to the screen.

            if event.type == KEYDOWN: # A key is physically pressed on.
                if event.key == K_ESCAPE: # The ESC key was pressed.
                    running = False # The attribute running is set to false to indicate that the game is stopping.
                    self.display_game_over(self.EXIT_VOLUNTARY) # We display the Game Over screen.

                if event.key == K_RETURN: # The return key was pressed.
                    pygame.mixer.music.unpause() # It resumes the playback of a music stream after it has been paused.
                    pause = False # It indicates that the game resumes from the suspended state.

                if event.key == K_p: # The p key was pressed.
                    pause = True # The game stops and it will enter the pause mode.
                    pygame.mixer.music.pause() # It temporarily stops playback of the music stream.
                    self.display_pause() # We draw a pause screen.
                
                if event.key == K_r: # The r key was pressed.
                    pause = False  # It indicates that the game resumes from the paused state.
                    pygame.mixer.music.unpause() # It resumes the playback of a music stream after it has been paused.
                                    
                if not pause: # If the game is not paused...

If the game is not paused and the left arrow was pressed (event.key == K_LEFT), we move the snake to the left. It is exactly the same if the right, up, or down arrow was pressed, we will move the snake to the right, upwards, or downwards respectively. Observe that the snake does not move right now, it will do it when we call the play method **

                    if event.key == K_LEFT: 
                        self.snake.move_left()
                    if event.key == K_RIGHT: 
                        self.snake.move_right() 
                    if event.key == K_UP: 
                        self.snake.move_up() 
                    if event.key == K_DOWN: 
                        self.snake.move_down() 

            elif event.type == QUIT: # The user has clicked the windows's X button.
                running = False # The game stops.
                self.display_game_over(self.EXIT_VOLUNTARY) # It displays the Game Over screen.
        try: # If the game is not in the paused stated, we are continuously playing.
            if not pause:
                self.play() #  **

        except ValueError as e: # If an exception was raised, it indicates that the user has lost because the snake has crashed against the wall, a ghost or itself.
            self.display_game_over(self.EXIT_LOSS) # It displays the Game Over screen.
            pause = True # The game entered it paused stated.
            self.reset() # It resets the game.

        time.sleep(self.speed) # It controls the game's speed.
        self.clock+=self.speed # It updates the game's clock.
        self.interval+=self.speed # It updates the game's interval.
        if self.interval > 5: # After five seconds, we add a new ghost, and by doing so, the game becomes more complicated.
            self.interval = 0
            self.add_ghost()

Let’s now focus on the Ghost, Apple, and Snake classes.

Fruits = ["apple", "bananas", "grapes", "lemon", "strawberry", "watermelon"]

class Ghost: # This class represents the ghost.
    def __init__(self, surface, x, y): # We need the Game's surface and the apple's coordinates
        self.surface = surface
        self.image = pygame.image.load("resources/ghost.png").convert_alpha()

pygame.image.load loads a new image from a file. We use the convert_alpha() method after loading so that the image has transparency (png).

Remember that self.surface = pygame.display.set_mode((1000, 800)) sets the window size for display. random.randint (a, b) returns a random integer n in [a, b]. Notice that 1000/SIZE = 25 and 800/SIZE = 20. random.randint(1, 24)*SIZE returns SIZE or 2*SIZE… 24*SIZE and random.randint(1, 19)*SIZE returns SIZE or 2*SIZE… 19*SIZE so we use them to position our ghost randomly while staying in the canvas.

        self.x = random.randint(1,24)*SIZE 
        self.y = random.randint(1,19)*SIZE 
        if x == self.x and y == self.y: # Bad luck! The Ghost is placed in the same location where the apple is.
            self.x = random.randint(1,24)*SIZE # We need to "resettle" him to a new location.
            self.y = random.randint(1,19)*SIZE
    def draw(self): # The Ghost draws itself. That's why we need the Game's surface.
        self.surface.blit(self.image, (self.x, self.y))
        pygame.display.flip()

class Apple: # This class represents the yummy apple.
    def __init__(self, surface): # We need the Game's surface.
        self.surface = surface
        self.image = pygame.image.load("resources/" +Fruits[random.randint(0, len(Fruits)-1)] + ".png").convert_alpha() # We load a random image of the fruit's list.
        self.x = 100
        self.y = 100

    def draw(self): # The Apple draws itself. 
        self.surface.blit(self.image, (self.x, self.y))
        pygame.display.flip()

    def move(self): # If the snake eats the apple, we should move it to a new location.
        self.image = pygame.image.load("resources/" +Fruits[random.randint(0, len(Fruits)-1)] + ".png").convert_alpha() # We load a new image.
        self.x = random.randint(1,24)*SIZE # We find a new location.
        self.y = random.randint(1,19)*SIZE

class Snake: # This class represents the snake.
    HEAD = "Head" # These constants are self-explanatory.
    BODY = "Body" 
    LEFT = "Left"
    UP = "Up"
    RIGHT = "Right"
    DOWN = "Down"
    def __init__(self, surface): # We also need the Game's surface in the Snake's constructor.
        self.surface = surface
        self.head = pygame.image.load("resources/head.png").convert_alpha() # We load two images, one for the head and a second one for the body.
        self.body = pygame.image.load("resources/body.png").convert_alpha()
        self.direction = Snake.DOWN

        self.length = 1 # The snake will start only with its head.
        self.x = [80] # The snake's body are represented by two lists of coordinates (x, y) of its parts.
        self.y = [80]

    def move_left(self): # When the user press the arrows (Game's run() method), we call these methods. They change the self.direction property.
        self.direction = Snake.LEFT

    def move_right(self):
        self.direction = Snake.RIGHT

    def move_up(self):
        self.direction = Snake.UP

    def move_down(self):
        self.direction = Snake.DOWN

    def slither(self): # The snake is constantly moving or slithering. 
        # Note that if a snake has three parts or blocks, the second block will move to where its head was, and the third part will move to where its second part was.
        self.x[1:] = self.x[0:-1] 
        self.y[1:] = self.y[0:-1]
            
        # The top-left corner of a Surface is the coordinate (0, 0). Moving to the right would be (SIZE, 0), and then moving down just as much would be (SIZE, SIZE). 
        if self.direction == Snake.LEFT:
            self.x[0] -= SIZE
        if self.direction == Snake.RIGHT:
            self.x[0] += SIZE
        if self.direction == Snake.UP:
            self.y[0] -= SIZE
        if self.direction == Snake.DOWN:
            self.y[0] += SIZE

        self.draw() # Finally, the snake draws itself.

    def drawPart(self, partBody, x, y): # It draws the head and body (partBody) of the Snake. Depending on the Snake's direction, we need to rotate the head or tail's images. 
        if partBody == self.HEAD:    
            if self.direction == Snake.LEFT:
                self.surface.blit(pygame.transform.rotate(self.head, 90), (x, y))
            if self.direction == Snake.RIGHT:
                self.surface.blit(pygame.transform.rotate(self.head, 270), (x, y))
            if self.direction == Snake.UP:
                self.surface.blit(self.head, (x, y))
            if self.direction == Snake.DOWN:
                self.surface.blit(pygame.transform.rotate(self.head, 180), (x, y))
        else:
            if self.direction == Snake.LEFT:
                self.surface.blit(pygame.transform.rotate(self.body, 90), (x, y))
            if self.direction == Snake.RIGHT:
                self.surface.blit(pygame.transform.rotate(self.body, 270), (x, y))
            if self.direction == Snake.UP:
                self.surface.blit(self.body, (x, y))
            if self.direction == Snake.DOWN:
                self.surface.blit(pygame.transform.rotate(self.body, 180), (x, y))
            
        
    def draw(self): # The snake's draw() method.
        self.drawPart(self.HEAD, self.x[0], self.y[0]) # It is always needed to draw the head. 
        if self.length == 1: # If the snake's length is 1, we are done....
            pass
        else: # .... Otherwise, we need to draw its body. 
            for i in range(1, self.length): 
                self.drawPart(self.BODY, self.x[i], self.y[i])
                
        pygame.display.flip()

    def growth(self): # This is called when the snake eats (or there is a collision) an apple.
        self.length += 1 # We increase the Snake's property length.
        self.x.append(-1) # We add a new item to the lists of x coordinates.
        self.y.append(-1) # We add a new item to the lists of y coordinates.

Programming games in Python

Programming games in Python

Programming games in Python

Programming games in Python

Let’s see the full code without any comments:

import pygame
from pygame.locals import *
import time
import random
import math
import shelve

SIZE = 40
Fruits = ["apple", "bananas", "grapes", "lemon", "strawberry", "watermelon"]

class Ghost:
    def __init__(self, surface, x, y):
        self.surface = surface
        self.image = pygame.image.load("resources/ghost.png").convert_alpha()
        self.x = random.randint(1,24)*SIZE
        self.y = random.randint(1,19)*SIZE
        if x == self.x:
            self.x = random.randint(1,24)*SIZE
            self.y = random.randint(1,19)*SIZE
        elif y == self.y:
            self.x = random.randint(1,24)*SIZE
            self.y = random.randint(1,19)*SIZE
    def draw(self):
        self.surface.blit(self.image, (self.x, self.y))
        pygame.display.flip()

class Apple:
    def __init__(self, surface):
        self.surface = surface
        self.image = pygame.image.load("resources/" +Fruits[random.randint(0, len(Fruits)-1)] + ".png").convert_alpha()
        self.x = 100
        self.y = 100

    def draw(self):
        self.surface.blit(self.image, (self.x, self.y))
        pygame.display.flip()

    def move(self):
        self.image = pygame.image.load("resources/" +Fruits[random.randint(0, len(Fruits)-1)] + ".png").convert_alpha()
        self.x = random.randint(1,24)*SIZE
        self.y = random.randint(1,19)*SIZE

class Snake:
    HEAD = "Head"
    BODY = "Body"
    LEFT = "Left"
    UP = "Up"
    RIGHT = "Right"
    DOWN = "Down"
    def __init__(self, surface):
        self.surface = surface
        self.head = pygame.image.load("resources/head.png").convert_alpha()
        self.body = pygame.image.load("resources/body.png").convert_alpha()
        self.direction = Snake.DOWN

        self.length = 1
        self.x = [40]
        self.y = [40]

    def move_left(self):
        self.direction = Snake.LEFT

    def move_right(self):
        self.direction = Snake.RIGHT

    def move_up(self):
        self.direction = Snake.UP

    def move_down(self):
        self.direction = Snake.DOWN

    def slither(self):
        self.x[1:] = self.x[0:-1]
        self.y[1:] = self.y[0:-1]
            
        if self.direction == Snake.LEFT:
            self.x[0] -= SIZE
        if self.direction == Snake.RIGHT:
            self.x[0] += SIZE
        if self.direction == Snake.UP:
            self.y[0] -= SIZE
        if self.direction == Snake.DOWN:
            self.y[0] += SIZE

        self.draw()

    def drawPart(self, partBody, x, y):
        if partBody == self.HEAD:    
            if self.direction == Snake.LEFT:
                self.surface.blit(pygame.transform.rotate(self.head, 90), (x, y))
            if self.direction == Snake.RIGHT:
                self.surface.blit(pygame.transform.rotate(self.head, 270), (x, y))
            if self.direction == Snake.UP:
                self.surface.blit(self.head, (x, y))
            if self.direction == Snake.DOWN:
                self.surface.blit(pygame.transform.rotate(self.head, 180), (x, y))
        else:
            if self.direction == Snake.LEFT:
                self.surface.blit(pygame.transform.rotate(self.body, 90), (x, y))
            if self.direction == Snake.RIGHT:
                self.surface.blit(pygame.transform.rotate(self.body, 270), (x, y))
            if self.direction == Snake.UP:
                self.surface.blit(self.body, (x, y))
            if self.direction == Snake.DOWN:
                self.surface.blit(pygame.transform.rotate(self.body, 180), (x, y))
            
        
    def draw(self):
        self.drawPart(self.HEAD, self.x[0], self.y[0])
        if self.length == 1:
            pass
        else:        
            for i in range(1, self.length):
                self.drawPart(self.BODY, self.x[i], self.y[i])
                
        pygame.display.flip()

    def growth(self):
        self.length += 1
        self.x.append(-1)
        self.y.append(-1)

class Game:
    InitialSpeed = 0.25
    EXIT_VOLUNTARY = "Exit_Voluntary"
    EXIT_LOSS = "Loss"
    def __init__(self):
        pygame.init()
        pygame.display.set_caption("Snake Game")

        pygame.mixer.init()
        self.play_background_music()

        self.surface = pygame.display.set_mode((1000, 800))
        self.snake = Snake(self.surface)
        self.snake.draw()
        self.apple = Apple(self.surface)
        self.apple.draw()
        self.ghosts = [Ghost(self.surface, self.apple.x, self.apple.y)]
        self.ghosts[0].draw()
        self.speed = self.InitialSpeed
        self.font = pygame.font.Font("resources/Halloween Morning.ttf", 30)
        self.clock=0
        self.interval=0
        
    def add_ghost(self):
        new_ghost = Ghost(self.surface, self.apple.x, self.apple.y)
        for i in range(0, self.snake.length-1):
            if self.is_there_collision(self.snake.x[i], self.snake.y[i], new_ghost.x, new_ghost.y):
                new_ghost = Ghost(self.surface, self.apple.x, self.apple.y)
            
        self.ghosts.append(new_ghost)

    def play_background_music(self):
        pygame.mixer.music.load('resources/bg_music.mp3')
        pygame.mixer.music.play(-1, 0)

    def play_sound(self, sound_name):
        sound = pygame.mixer.Sound("resources/" + sound_name + ".mp3")
        pygame.mixer.Sound.play(sound)

    def reset(self):
        self.snake = Snake(self.surface)
        self.apple = Apple(self.surface)
        self.ghosts = [Ghost(self.surface, self.apple.x, self.apple.y)]
        self.speed = self.InitialSpeed
        self.clock = 0
        self.interval = 0

    def is_there_collision(self, x1, y1, x2, y2):
        if abs(x1-x2)<SIZE and abs(y1-y2)<SIZE:
            return True

        return False

    def render_background(self):
        bg = pygame.image.load("resources/background.jpg")
        self.surface.blit(bg, (0,0))

    def play(self):
        self.render_background()
        self.snake.slither()
        self.apple.draw()
        for ghost in self.ghosts:
            ghost.draw()
            
        self.display_score()
        pygame.display.flip()

        if self.is_there_collision(self.snake.x[0], self.snake.y[0], self.apple.x, self.apple.y):
            self.play_sound("yummy")
            self.snake.growth()
            self.apple.move()
            self.speed -= 0.01

        for i in range(3, self.snake.length):
            if self.is_there_collision(self.snake.x[0], self.snake.y[0], self.snake.x[i], self.snake.y[i]):
                self.play_sound('crash')
                raise ValueError("Game over! Hit yourself!")
        
        for ghost in self.ghosts:
            if self.is_there_collision(self.snake.x[0], self.snake.y[0], ghost.x, ghost.y):
                self.play_sound('crash')
                raise ValueError("Game over! Ghosts are dangerous!")
        
        if not (0 <= self.snake.x[0] <= 1000 and 0 <= self.snake.y[0] <= 800):
            self.play_sound('crash')
            raise ValueError("Game over! Crash against the wall!")

    def display_score(self):
        score = self.font.render(f"Score: {self.snake.length}. {self.clock}",True, (0, 0, 0))
        self.surface.blit(score,(850,25))

    def display_game_over(self, mode):
        self.render_background()
        if mode==self.EXIT_VOLUNTARY:
            line1 = self.font.render(f"I am sorry to see you go", True, (0, 0, 0))
            self.surface.blit(line1, (200, 300))
            pygame.display.flip()
            time.sleep(1)
            return
            
        d = shelve.open('score.txt')
        score = 0
        try:
            score = d['score']  # the score is read from disk
        except KeyError as e:
            d['score'] = self.snake.length    
            pass    
        if score < self.snake.length:
            score = self.snake.length
            d['score'] = self.snake.length    
            
        d.close()
        print(score)
       
        line1 = self.font.render(f"Game is over! Your score is {self.snake.length}", True, (0, 0, 0))
        self.surface.blit(line1, (200, 300))
        line2 = self.font.render(f"The best score is {score}", True, (0, 0, 0))
        self.surface.blit(line2, (200, 350))
        line3 = self.font.render("To play again press Enter. To exit press Escape!", True, (0, 0, 0))
        self.surface.blit(line3, (200, 400))
        pygame.mixer.music.pause()
        pygame.display.flip()

    def display_pause(self):
        self.render_background()
        line = self.font.render("To resume press r. To exit press Escape!", True, (0, 0, 0))
        self.surface.blit(line, (200, 350))
        pygame.display.flip()        

    def run(self):
        running = True
        pause = False

        while running:
            for event in pygame.event.get():
                if event.type == KEYDOWN:
                    if event.key == K_ESCAPE:
                        running = False
                        self.display_game_over(self.EXIT_VOLUNTARY)

                    if event.key == K_RETURN:
                        pygame.mixer.music.unpause()
                        pause = False

                    if event.key == K_p:
                        pause = True
                        pygame.mixer.music.pause()
                        self.display_pause()
                    
                    if event.key == K_r:
                        pause = False
                        pygame.mixer.music.unpause()
                                        
                    if not pause:
                        if event.key == K_LEFT:
                            self.snake.move_left()

                        if event.key == K_RIGHT:
                            self.snake.move_right()

                        if event.key == K_UP:
                            self.snake.move_up()

                        if event.key == K_DOWN:
                            self.snake.move_down()

                elif event.type == QUIT:
                    running = False
                    self.display_game_over(self.EXIT_VOLUNTARY)
            try:
                if not pause:
                    self.play()

            except ValueError as e:
                self.display_game_over(self.EXIT_LOSS)
                pause = True
                self.reset()

            time.sleep(self.speed)
            self.clock+=self.speed
            self.interval+=self.speed
            if self.interval > 5:
                self.interval = 0
                self.add_ghost()
                

if __name__ == '__main__':
    game = Game()
    game.run()
Bitcoin donation

JustToThePoint Copyright © 2011 - 2024 Anawim. ALL RIGHTS RESERVED. Bilingual e-books, articles, and videos to help your child and your entire family succeed, develop a healthy lifestyle, and have a lot of fun. Social Issues, Join us.

This website uses cookies to improve your navigation experience.
By continuing, you are consenting to our use of cookies, in accordance with our Cookies Policy and Website Terms and Conditions of use.