Creating Dino Game in Python

Dino Game in Python

Who has not played Google’s famous Dino Game whenever we are not connected to the internet? Probably everyone might have played this game once. Today, in this article, we will help you develop a Dino Game in Python. This tutorial will include an in-depth explanation of each line of code along with reference materials. We will try our level best to make our readers understand this project in detail and thoroughly. The task record for the Python version of the Dino Game includes picture documents and Python material. GUI makes use of the pygame library.

We will use one of the most famous Python libraries that is PyGame. Apart from that, we will also use random, os, and sys libraries for the development of this Dino Game in Python. Before moving on to the actual coding let us take a brief overview of What Dino Game is all about? How does it work? etc. After that, we will take a look at the list of features that we need to add to this game. So let us initialize this article without any further ado.

Basic Idea of the Dino Game in Python

The main objective of this simplified game is to score an increasing amount of points without becoming distracted by any obstacles. The same playing techniques are used in all games. As stated the core of this mini-game is to accumulate points without coming into contact with any obstacles. The user must use two keyboard keys to play this straightforward game. Jump with the spacebar, and cover with the down arrow. The gaming environment has been modified in this copy compared to the original.

Having a basic idea of what exactly this game is all about. Let us talk about the mandatory features that need to be there in this project of Dino Game in Python

Features of this game

The set of features for Dino Game includes the following:

  • Display previous high score and current score
  • Keyboard support
  • Sound for jump and when dinosaurs die
  • Checkpoint sound
  • Option to replay the game

Now let us move on to the actual coding of this project.

Coding Dino Game in Python

Basic library import

import os
import sys
import pygame
import random
from pygame import *

pygame.init()

Explanation:

Here we imported all the libraries that we are going to use in the development of this project. The last line pygame. init() is used to initialize all the imported pygame modules.

Setting up the display window and title

screenDisplay = (width_screen, height_screen) = (600, 400)
FPS = 60
gravity = 0.6

black_color = (0,0,0)
white_color = (255,255,255)
backgroundColor = (235, 235, 235)

highest_scores = 0

screenDisplay = pygame.display.set_mode(screenDisplay)
timerClock = pygame.time.Clock()
pygame.display.set_caption("Dino Run - CopyAssignment ")

Explanation:

In this section of code in Dino Game in Python, we have used the various functions of PyGame in order to set the window size, title, etc. We used to display.set_mode will initialize a window or screen for display. In order to set the title of the window we used set_caption

Basic resources addition

soundOnJump = pygame.mixer.Sound('resources/jump.wav')
soundOnDie = pygame.mixer.Sound('resources/die.wav')
soundOnCheckpoint = pygame.mixer.Sound('resources/checkPoint.wav')

Explanation:

Here w declared three variables that are basically to add various sounds in the game. We made a folder named resources and in that, we have our three .wav files. In order to send sound to our game, we made use of a mixer.Sound(). We will use these three sounds in the other parts of the code.

Functions to load the images

def load_image(
    name,
    sx=-1,
    sy=-1,
    colorkey=None,
    ):

    fullname = os.path.join('resources', name)
    img = pygame.image.load(fullname)
    img = img.convert()
    if colorkey is not None:
        if colorkey == -1:
            colorkey = img.get_at((0, 0))
        img.set_colorkey(colorkey, RLEACCEL)

    if sx != -1 or sy != -1:
        img = pygame.transform.scale(img, (sx, sy))

    return (img, img.get_rect())

def load_sprite_sheet(
        s_name,
        namex,
        namey,
        scx = -1,
        scy = -1,
        c_key = None,
        ):
    fullname = os.path.join('resources', s_name)
    sh = pygame.image.load(fullname)
    sh = sh.convert()

    sh_rect = sh.get_rect()

    sprites = []

    sx = sh_rect.width/ namex
    sy = sh_rect.height/ namey

    for i in range(0, namey):
        for j in range(0, namex):
            rect = pygame.Rect((j*sx,i*sy,sx,sy))
            img = pygame.Surface(rect.size)
            img = img.convert()
            img.blit(sh,(0,0),rect)

            if c_key is not None:
                if c_key == -1:
                    c_key = img.get_at((0, 0))
                img.set_colorkey(c_key, RLEACCEL)

            if scx != -1 or scy != -1:
                img = pygame.transform.scale(img, (scx, scy))

            sprites.append(img)

    sprite_rect = sprites[0].get_rect()

    return sprites,sprite_rect

Explanation:

Onto the other block of code in Dino Game in Python, this section is mainly responsible for loading images on the game window of Dino Game. Here we used Python’s os. path.join() function that intelligently joins one or more path components. With the exception of the last path component, this approach concatenates different path components by placing exactly one directory separator (‘/’) after each non-empty portion. A directory separator (‘/’) is added at the end of the final path component to be linked is empty.

pygame. image.load() this helps us to load the image and then in the for loop, we used the set_colorkey() that will basically set the transparent color key. In the same way, we used the above functions in another user-defined function named load_sprite_sheet

To display the game over the message

def gameover_display_message(rbtn_image, gmo_image):
    rbtn_rect = rbtn_image.get_rect()
    rbtn_rect.centerx = width_screen / 2
    rbtn_rect.top = height_screen * 0.52

    gmo_rect = gmo_image.get_rect()
    gmo_rect.centerx = width_screen / 2
    gmo_rect.centery = height_screen * 0.35

    screenDisplay.blit(rbtn_image, rbtn_rect)
    screenDisplay.blit(gmo_image, gmo_rect)

def extractDigits(num):
    if num > -1:
        d = []
        i = 0
        while(num / 10 != 0):
            d.append(num % 10)
            num = int(num / 10)

        d.append(num % 10)
        for i in range(len(d),5):
            d.append(0)
        d.reverse()
        return d

Explanation:

Here in this function, we made use of two rectangles in order to display the two images: One of the “Game Over” image and another of the “Replay Image”. We used blit() which means Block Transfer which refers to the process of copying material from one surface to another Surface. The screen you made and the new Surface are the two surfaces in concern. So, this Surface will be taken and placed on top of the screen by the blit() function. The approach requires two arguments. Another function that we defined is extractDigits() – this function is responsible for keeping the track of user’s score.

Defining the Dino class

class Dino():
    def __init__(self, sx=-1, sy=-1):
        self.imgs, self.rect = load_sprite_sheet('dino.png', 5, 1, sx, sy, -1)
        self.imgs1, self.rect1 = load_sprite_sheet('dino_ducking.png', 2, 1, 59, sy, -1)
        self.rect.bottom = int(0.98 * height_screen)
        self.rect.left = width_screen / 15
        self.image = self.imgs[0]
        self.index = 0
        self.counter = 0
        self.score = 0
        self.jumping = False
        self.dead = False
        self.ducking = False
        self.blinking = False
        self.movement = [0,0]
        self.jumpSpeed = 11.5

        self.stand_position_width = self.rect.width
        self.duck_position_width = self.rect1.width

    def draw(self):
        screenDisplay.blit(self.image, self.rect)

    def checkbounds(self):
        if self.rect.bottom > int(0.98 * height_screen):
            self.rect.bottom = int(0.98 * height_screen)
            self.jumping = False

    def update(self):
        if self.jumping:
            self.movement[1] = self.movement[1] + gravity

        if self.jumping:
            self.index = 0
        elif self.blinking:
            if self.index == 0:
                if self.counter % 400 == 399:
                    self.index = (self.index + 1)%2
            else:
                if self.counter % 20 == 19:
                    self.index = (self.index + 1)%2

        elif self.ducking:
            if self.counter % 5 == 0:
                self.index = (self.index + 1)%2
        else:
            if self.counter % 5 == 0:
                self.index = (self.index + 1)%2 + 2

        if self.dead:
           self.index = 4

        if not self.ducking:
            self.image = self.imgs[self.index]
            self.rect.width = self.stand_position_width
        else:
            self.image = self.imgs1[(self.index) % 2]
            self.rect.width = self.duck_position_width

        self.rect = self.rect.move(self.movement)
        self.checkbounds()

        if not self.dead and self.counter % 7 == 6 and self.blinking == False:
            self.score += 1
            if self.score % 100 == 0 and self.score != 0:
                if pygame.mixer.get_init() != None:
                    soundOnCheckpoint.play()

        self.counter = (self.counter + 1)

Explanation:

This class can be considered the heart of Dino Game in Python. It is mainly responsible for handling all the functions of the dinosaur. Initially, we hard-coded all the different variables of the dino like its speed, jump movements, etc. Apart from that in order to show its movement, we used the function update() that will keep track of all the movements like ducking, jumping, death, etc of the dino.

Defining the Cactus class

class Ground():
    def __init__(self,speed=-5):
        self.image,self.rect = load_image('ground.png',-1,-1,-1)
        self.image1,self.rect1 = load_image('ground.png',-1,-1,-1)
        self.rect.bottom = height_screen
        self.rect1.bottom = height_screen
        self.rect1.left = self.rect.right
        self.speed = speed

    def draw(self):
        screenDisplay.blit(self.image, self.rect)
        screenDisplay.blit(self.image1, self.rect1)

    def update(self):
        self.rect.left += self.speed
        self.rect1.left += self.speed

        if self.rect.right < 0:
            self.rect.left = self.rect1.right

        if self.rect1.right < 0:
            self.rect1.left = self.rect.right

Explanation:

This class is responsible for handling the placement of cacti in this Dino Game in Python. At first, we load the cactus image from our resources folder and set its place, movement, etc. To remove the cactus that are passed from the screen, we made use of an update(). Inside that, we set and if block with the condition that self. rect.right < 0 then we will call the self.kill()

Defining the Birds class

class birds(pygame.sprite.Sprite):
    def __init__(self, speed=5, sx=-1, sy=-1):
        pygame.sprite.Sprite.__init__(self,self.containers)
        self.imgs, self.rect = load_sprite_sheet('birds.png', 2, 1, sx, sy, -1)
        self.birds_height = [height_screen * 0.82, height_screen * 0.75, height_screen * 0.60]
        self.rect.centery = self.birds_height[random.randrange(0, 3)]
        self.rect.left = width_screen + self.rect.width
        self.image = self.imgs[0]
        self.movement = [-1*speed,0]
        self.index = 0
        self.counter = 0

    def draw(self):
        screenDisplay.blit(self.image, self.rect)

    def update(self):
        if self.counter % 10 == 0:
            self.index = (self.index+1)%2
        self.image = self.imgs[self.index]
        self.rect = self.rect.move(self.movement)
        self.counter = (self.counter + 1)
        if self.rect.right < 0:
            self.kill()

Explanation:

This class is responsible for handling the placement of cacti in this Dino Game in Python. At first, we load the cactus image from our resources folder and set its place, movement, etc. To remove the cactus that are passed from the screen, we made use of an update(). Inside that, we set and if block with the condition that self.rect.right < 0 then we will call the self.kill(). It is used to remove the widget from the screen and so we use kill().

Defining the Ground class

class Ground():
    def __init__(self,speed=-5):
        self.image,self.rect = load_image('ground.png',-1,-1,-1)
        self.image1,self.rect1 = load_image('ground.png',-1,-1,-1)
        self.rect.bottom = height_screen
        self.rect1.bottom = height_screen
        self.rect1.left = self.rect.right
        self.speed = speed

    def draw(self):
        screenDisplay.blit(self.image, self.rect)
        screenDisplay.blit(self.image1, self.rect1)

    def update(self):
        self.rect.left += self.speed
        self.rect1.left += self.speed

        if self.rect.right < 0:
            self.rect.left = self.rect1.right

        if self.rect1.right < 0:
            self.rect1.left = self.rect.right

Explanation

In the same way, as we defined the birds class, we defined the ground class and for the movement of the ground, we used the same functions as we did in birds.

Defining the Cloud class

class Cloud(pygame.sprite.Sprite):
    def __init__(self,x,y):
        pygame.sprite.Sprite.__init__(self,self.containers)
        self.image,self.rect = load_image('cloud.png',int(90*30/42),30,-1)
        self.speed = 1
        self.rect.left = x
        self.rect.top = y
        self.movement = [-1*self.speed,0]

    def draw(self):
        screenDisplay.blit(self.image, self.rect)

    def update(self):
        self.rect = self.rect.move(self.movement)
        if self.rect.right < 0:
            self.kill()

Explanation:

Moving on to another class in Dino Game in Python. Clouds are also one of the components of this game. Its function and movement are totally the same as the ground. The functions in this class will be the same as those we used in the ground class.

Handling the scores

class Scoreboard():
    def __init__(self,x=-1,y=-1):
        self.score = 0
        self.scre_img, self.screrect = load_sprite_sheet('numbers.png', 12, 1, 11, int(11 * 6 / 5), -1)
        self.image = pygame.Surface((55,int(11*6/5)))
        self.rect = self.image.get_rect()
        if x == -1:
            self.rect.left = width_screen * 0.89
        else:
            self.rect.left = x
        if y == -1:
            self.rect.top = height_screen * 0.1
        else:
            self.rect.top = y

    def draw(self):
        screenDisplay.blit(self.image, self.rect)

    def update(self,score):
        score_digits = extractDigits(score)
        self.image.fill(backgroundColor)
        for s in score_digits:
            self.image.blit(self.scre_img[s], self.screrect)
            self.screrect.left += self.screrect.width
        self.screrect.left = 0

Explanation:

Now we have to work on handling the scoreboard in Dino Game. We did this by tracking the movement of the screen. We used our “numbers.png” images to update the scores. On top of that, we called our extractDigits() function that we declared previously to extract single- single digits from the image and then display it based on the movement of the components on the window.

Introduction screen

def introduction_screen():
    ado_dino = Dino(44,47)
    ado_dino.blinking = True
    starting_game = False

    t_ground,t_ground_rect = load_sprite_sheet('ground.png',15,1,-1,-1,-1)
    t_ground_rect.left = width_screen / 20
    t_ground_rect.bottom = height_screen

    logo,l_rect = load_image('logo.png',300,140,-1)
    l_rect.centerx = width_screen * 0.6
    l_rect.centery = height_screen * 0.6
    while not starting_game:
        if pygame.display.get_surface() == None:
            print("Couldn't load display surface")
            return True
        else:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    return True
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_SPACE or event.key == pygame.K_UP:
                        ado_dino.jumping = True
                        ado_dino.blinking = False
                        ado_dino.movement[1] = -1*ado_dino.jumpSpeed

        ado_dino.update()

        if pygame.display.get_surface() != None:
            screenDisplay.fill(backgroundColor)
            screenDisplay.blit(t_ground[0], t_ground_rect)
            if ado_dino.blinking:
                screenDisplay.blit(logo, l_rect)
            ado_dino.draw()

            pygame.display.update()

        timerClock.tick(FPS)
        if ado_dino.jumping == False and ado_dino.blinking == False:
            starting_game = True

Explanation:

This screen will be displayed t first whenever the user will run this program of Dino Game in Python. This screen will initially load some of the components of the game like the ground and the logo image only. We used if-else to display a message that “Couldn’t load display surface” just in case our image does not load up. Apart from that, we used the three keys that are Upward and Downward arrow keys and Spacebar to start the game. The game will only start if the user presses any of these keys. The handling of key presses is done using the event.

Handling the overall gameplay

def gameplay():
    global highest_scores
    gp = 4
    s_Menu = False
    g_Over = False
    g_exit = False
    gamer_Dino = Dino(44,47)
    new_grnd = Ground(-1*gp)
    score_boards = Scoreboard()
    highScore = Scoreboard(width_screen * 0.78)
    counter = 0

    cactusan = pygame.sprite.Group()
    smallBird = pygame.sprite.Group()
    skyClouds = pygame.sprite.Group()
    last_end_obs = pygame.sprite.Group()

    Cactus.containers = cactusan
    birds.containers = smallBird
    Cloud.containers = skyClouds

    rbtn_image,rbtn_rect = load_image('replay_button.png',35,31,-1)
    gmo_image,gmo_rect = load_image('game_over.png',190,11,-1)

    t_images,t_rect = load_sprite_sheet('numbers.png',12,1,11,int(11*6/5),-1)
    ado_image = pygame.Surface((22,int(11*6/5)))
    ado_rect = ado_image.get_rect()
    ado_image.fill(backgroundColor)
    ado_image.blit(t_images[10],t_rect)
    t_rect.left += t_rect.width
    ado_image.blit(t_images[11],t_rect)
    ado_rect.top = height_screen * 0.1
    ado_rect.left = width_screen * 0.73

    while not g_exit:
        while s_Menu:
            pass
        while not g_Over:
            if pygame.display.get_surface() == None:
                print("Couldn't load display surface")
                g_exit = True
                g_Over = True
            else:
                for event in pygame.event.get():
                    if event.type == pygame.QUIT:
                        g_exit = True
                        g_Over = True

                    if event.type == pygame.KEYDOWN:
                        if event.key == pygame.K_SPACE:
                            if gamer_Dino.rect.bottom == int(0.98 * height_screen):
                                gamer_Dino.jumping = True
                                if pygame.mixer.get_init() != None:
                                    soundOnJump.play()
                                gamer_Dino.movement[1] = -1*gamer_Dino.jumpSpeed

                        if event.key == pygame.K_DOWN:
                            if not (gamer_Dino.jumping and gamer_Dino.dead):
                                gamer_Dino.ducking = True

                    if event.type == pygame.KEYUP:
                        if event.key == pygame.K_DOWN:
                            gamer_Dino.ducking = False
            for c in cactusan:
                c.movement[0] = -1*gp
                if pygame.sprite.collide_mask(gamer_Dino,c):
                    gamer_Dino.dead = True
                    if pygame.mixer.get_init() != None:
                        soundOnDie.play()

            for p in smallBird:
                p.movement[0] = -1*gp
                if pygame.sprite.collide_mask(gamer_Dino,p):
                    gamer_Dino.dead = True
                    if pygame.mixer.get_init() != None:
                        soundOnDie.play()

            if len(cactusan) < 2:
                if len(cactusan) == 0:
                    last_end_obs.empty()
                    last_end_obs.add(Cactus(gp,40,40))
                else:
                    for l in last_end_obs:
                        if l.rect.right < width_screen*0.7 and random.randrange(0, 50) == 10:
                            last_end_obs.empty()
                            last_end_obs.add(Cactus(gp, 40, 40))

            if len(smallBird) == 0 and random.randrange(0,200) == 10 and counter > 500:
                for l in last_end_obs:
                    if l.rect.right < width_screen*0.8:
                        last_end_obs.empty()
                        last_end_obs.add(birds(gp, 46, 40))

            if len(skyClouds) < 5 and random.randrange(0,300) == 10:
                Cloud(width_screen, random.randrange(height_screen / 5, height_screen / 2))

            gamer_Dino.update()
            cactusan.update()
            smallBird.update()
            skyClouds.update()
            new_grnd.update()
            score_boards.update(gamer_Dino.score)
            highScore.update(highest_scores)

            if pygame.display.get_surface() != None:
                screenDisplay.fill(backgroundColor)
                new_grnd.draw()
                skyClouds.draw(screenDisplay)
                score_boards.draw()
                if highest_scores != 0:
                    highScore.draw()
                    screenDisplay.blit(ado_image, ado_rect)
                cactusan.draw(screenDisplay)
                smallBird.draw(screenDisplay)
                gamer_Dino.draw()

                pygame.display.update()
            timerClock.tick(FPS)

            if gamer_Dino.dead:
                g_Over = True
                if gamer_Dino.score > highest_scores:
                    highest_scores = gamer_Dino.score

            if counter%700 == 699:
                new_grnd.speed -= 1
                gp += 1

            counter = (counter + 1)

        if g_exit:
            break

        while g_Over:
            if pygame.display.get_surface() == None:
                print("Couldn't load display surface")
                g_exit = True
                g_Over = False
            else:
                for event in pygame.event.get():
                    if event.type == pygame.QUIT:
                        g_exit = True
                        g_Over = False
                    if event.type == pygame.KEYDOWN:
                        if event.key == pygame.K_ESCAPE:
                            g_exit = True
                            g_Over = False

                        if event.key == pygame.K_RETURN or event.key == pygame.K_SPACE:
                            g_Over = False
                            gameplay()
            highScore.update(highest_scores)
            if pygame.display.get_surface() != None:
                gameover_display_message(rbtn_image, gmo_image)
                if highest_scores != 0:
                    highScore.draw()
                    screenDisplay.blit(ado_image, ado_rect)
                pygame.display.update()
            timerClock.tick(FPS)

    pygame.quit()
    quit()

Explanation:

The gameplay function comes into action whenever the user presses the three keys that we described above to start the game. Once the game starts, it is the responsibility of the gameplay() function to control the movement of each and every component in the game. Besides that, the key presses for various types of movement of the dino are also controlled in this function. The constant display of birds, cacti, clouds, etc. In the end, if the player loses then the game automatically gets into the quit() state. This will help us to take the game into the quit state and display the two images of replay and game over.

main function

def main():
    isGameQuit = introduction_screen()
    if not isGameQuit:
        gameplay()

main()

Explanation:

This function will call the introduction_screen() if the user quits the game. If that is not the case then the gameplay() function will be called. That simply means that the game will again be in a state wherein the user will be able to play.

Output:

Image output:

Dino Game in Python - Output
Start Game window
Game over window
Game Over window

Video output:

Complete Code for Dino Game in Python

import os
import sys
import pygame
import random
from pygame import *

pygame.init()

screenDisplay = (width_screen, height_screen) = (600, 400)
FPS = 60
gravity = 0.6

black_color = (0,0,0)
white_color = (255,255,255)
backgroundColor = (235, 235, 235)

highest_scores = 0

screenDisplay = pygame.display.set_mode(screenDisplay)
timerClock = pygame.time.Clock()
pygame.display.set_caption("Dino Run - CopyAssignment ")

soundOnJump = pygame.mixer.Sound('resources/jump.wav')
soundOnDie = pygame.mixer.Sound('resources/die.wav')
soundOnCheckpoint = pygame.mixer.Sound('resources/checkPoint.wav')

def load_image(
    name,
    sx=-1,
    sy=-1,
    colorkey=None,
    ):

    fullname = os.path.join('resources', name)
    img = pygame.image.load(fullname)
    img = img.convert()
    if colorkey is not None:
        if colorkey == -1:
            colorkey = img.get_at((0, 0))
        img.set_colorkey(colorkey, RLEACCEL)

    if sx != -1 or sy != -1:
        img = pygame.transform.scale(img, (sx, sy))

    return (img, img.get_rect())

def load_sprite_sheet(
        s_name,
        namex,
        namey,
        scx = -1,
        scy = -1,
        c_key = None,
        ):
    fullname = os.path.join('resources', s_name)
    sh = pygame.image.load(fullname)
    sh = sh.convert()

    sh_rect = sh.get_rect()

    sprites = []

    sx = sh_rect.width/ namex
    sy = sh_rect.height/ namey

    for i in range(0, namey):
        for j in range(0, namex):
            rect = pygame.Rect((j*sx,i*sy,sx,sy))
            img = pygame.Surface(rect.size)
            img = img.convert()
            img.blit(sh,(0,0),rect)

            if c_key is not None:
                if c_key == -1:
                    c_key = img.get_at((0, 0))
                img.set_colorkey(c_key, RLEACCEL)

            if scx != -1 or scy != -1:
                img = pygame.transform.scale(img, (scx, scy))

            sprites.append(img)

    sprite_rect = sprites[0].get_rect()

    return sprites,sprite_rect

def gameover_display_message(rbtn_image, gmo_image):
    rbtn_rect = rbtn_image.get_rect()
    rbtn_rect.centerx = width_screen / 2
    rbtn_rect.top = height_screen * 0.52

    gmo_rect = gmo_image.get_rect()
    gmo_rect.centerx = width_screen / 2
    gmo_rect.centery = height_screen * 0.35

    screenDisplay.blit(rbtn_image, rbtn_rect)
    screenDisplay.blit(gmo_image, gmo_rect)

def extractDigits(num):
    if num > -1:
        d = []
        i = 0
        while(num / 10 != 0):
            d.append(num % 10)
            num = int(num / 10)

        d.append(num % 10)
        for i in range(len(d),5):
            d.append(0)
        d.reverse()
        return d

class Dino():
    def __init__(self, sx=-1, sy=-1):
        self.imgs, self.rect = load_sprite_sheet('dino.png', 5, 1, sx, sy, -1)
        self.imgs1, self.rect1 = load_sprite_sheet('dino_ducking.png', 2, 1, 59, sy, -1)
        self.rect.bottom = int(0.98 * height_screen)
        self.rect.left = width_screen / 15
        self.image = self.imgs[0]
        self.index = 0
        self.counter = 0
        self.score = 0
        self.jumping = False
        self.dead = False
        self.ducking = False
        self.blinking = False
        self.movement = [0,0]
        self.jumpSpeed = 11.5

        self.stand_position_width = self.rect.width
        self.duck_position_width = self.rect1.width

    def draw(self):
        screenDisplay.blit(self.image, self.rect)

    def checkbounds(self):
        if self.rect.bottom > int(0.98 * height_screen):
            self.rect.bottom = int(0.98 * height_screen)
            self.jumping = False

    def update(self):
        if self.jumping:
            self.movement[1] = self.movement[1] + gravity

        if self.jumping:
            self.index = 0
        elif self.blinking:
            if self.index == 0:
                if self.counter % 400 == 399:
                    self.index = (self.index + 1)%2
            else:
                if self.counter % 20 == 19:
                    self.index = (self.index + 1)%2

        elif self.ducking:
            if self.counter % 5 == 0:
                self.index = (self.index + 1)%2
        else:
            if self.counter % 5 == 0:
                self.index = (self.index + 1)%2 + 2

        if self.dead:
           self.index = 4

        if not self.ducking:
            self.image = self.imgs[self.index]
            self.rect.width = self.stand_position_width
        else:
            self.image = self.imgs1[(self.index) % 2]
            self.rect.width = self.duck_position_width

        self.rect = self.rect.move(self.movement)
        self.checkbounds()

        if not self.dead and self.counter % 7 == 6 and self.blinking == False:
            self.score += 1
            if self.score % 100 == 0 and self.score != 0:
                if pygame.mixer.get_init() != None:
                    soundOnCheckpoint.play()

        self.counter = (self.counter + 1)

class Cactus(pygame.sprite.Sprite):
    def __init__(self, speed=5, sx=-1, sy=-1):
        pygame.sprite.Sprite.__init__(self,self.containers)
        self.imgs, self.rect = load_sprite_sheet('cactus-small.png', 3, 1, sx, sy, -1)
        self.rect.bottom = int(0.98 * height_screen)
        self.rect.left = width_screen + self.rect.width
        self.image = self.imgs[random.randrange(0, 3)]
        self.movement = [-1*speed,0]

    def draw(self):
        screenDisplay.blit(self.image, self.rect)

    def update(self):
        self.rect = self.rect.move(self.movement)

        if self.rect.right < 0:
            self.kill()

class birds(pygame.sprite.Sprite):
    def __init__(self, speed=5, sx=-1, sy=-1):
        pygame.sprite.Sprite.__init__(self,self.containers)
        self.imgs, self.rect = load_sprite_sheet('birds.png', 2, 1, sx, sy, -1)
        self.birds_height = [height_screen * 0.82, height_screen * 0.75, height_screen * 0.60]
        self.rect.centery = self.birds_height[random.randrange(0, 3)]
        self.rect.left = width_screen + self.rect.width
        self.image = self.imgs[0]
        self.movement = [-1*speed,0]
        self.index = 0
        self.counter = 0

    def draw(self):
        screenDisplay.blit(self.image, self.rect)

    def update(self):
        if self.counter % 10 == 0:
            self.index = (self.index+1)%2
        self.image = self.imgs[self.index]
        self.rect = self.rect.move(self.movement)
        self.counter = (self.counter + 1)
        if self.rect.right < 0:
            self.kill()


class Ground():
    def __init__(self,speed=-5):
        self.image,self.rect = load_image('ground.png',-1,-1,-1)
        self.image1,self.rect1 = load_image('ground.png',-1,-1,-1)
        self.rect.bottom = height_screen
        self.rect1.bottom = height_screen
        self.rect1.left = self.rect.right
        self.speed = speed

    def draw(self):
        screenDisplay.blit(self.image, self.rect)
        screenDisplay.blit(self.image1, self.rect1)

    def update(self):
        self.rect.left += self.speed
        self.rect1.left += self.speed

        if self.rect.right < 0:
            self.rect.left = self.rect1.right

        if self.rect1.right < 0:
            self.rect1.left = self.rect.right

class Cloud(pygame.sprite.Sprite):
    def __init__(self,x,y):
        pygame.sprite.Sprite.__init__(self,self.containers)
        self.image,self.rect = load_image('cloud.png',int(90*30/42),30,-1)
        self.speed = 1
        self.rect.left = x
        self.rect.top = y
        self.movement = [-1*self.speed,0]

    def draw(self):
        screenDisplay.blit(self.image, self.rect)

    def update(self):
        self.rect = self.rect.move(self.movement)
        if self.rect.right < 0:
            self.kill()

class Scoreboard():
    def __init__(self,x=-1,y=-1):
        self.score = 0
        self.scre_img, self.screrect = load_sprite_sheet('numbers.png', 12, 1, 11, int(11 * 6 / 5), -1)
        self.image = pygame.Surface((55,int(11*6/5)))
        self.rect = self.image.get_rect()
        if x == -1:
            self.rect.left = width_screen * 0.89
        else:
            self.rect.left = x
        if y == -1:
            self.rect.top = height_screen * 0.1
        else:
            self.rect.top = y

    def draw(self):
        screenDisplay.blit(self.image, self.rect)

    def update(self,score):
        score_digits = extractDigits(score)
        self.image.fill(backgroundColor)
        for s in score_digits:
            self.image.blit(self.scre_img[s], self.screrect)
            self.screrect.left += self.screrect.width
        self.screrect.left = 0


def introduction_screen():
    ado_dino = Dino(44,47)
    ado_dino.blinking = True
    starting_game = False

    t_ground,t_ground_rect = load_sprite_sheet('ground.png',15,1,-1,-1,-1)
    t_ground_rect.left = width_screen / 20
    t_ground_rect.bottom = height_screen

    logo,l_rect = load_image('logo.png',300,140,-1)
    l_rect.centerx = width_screen * 0.6
    l_rect.centery = height_screen * 0.6
    while not starting_game:
        if pygame.display.get_surface() == None:
            print("Couldn't load display surface")
            return True
        else:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    return True
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_SPACE or event.key == pygame.K_UP:
                        ado_dino.jumping = True
                        ado_dino.blinking = False
                        ado_dino.movement[1] = -1*ado_dino.jumpSpeed

        ado_dino.update()

        if pygame.display.get_surface() != None:
            screenDisplay.fill(backgroundColor)
            screenDisplay.blit(t_ground[0], t_ground_rect)
            if ado_dino.blinking:
                screenDisplay.blit(logo, l_rect)
            ado_dino.draw()

            pygame.display.update()

        timerClock.tick(FPS)
        if ado_dino.jumping == False and ado_dino.blinking == False:
            starting_game = True

def gameplay():
    global highest_scores
    gp = 4
    s_Menu = False
    g_Over = False
    g_exit = False
    gamer_Dino = Dino(44,47)
    new_grnd = Ground(-1*gp)
    score_boards = Scoreboard()
    highScore = Scoreboard(width_screen * 0.78)
    counter = 0

    cactusan = pygame.sprite.Group()
    smallBird = pygame.sprite.Group()
    skyClouds = pygame.sprite.Group()
    last_end_obs = pygame.sprite.Group()

    Cactus.containers = cactusan
    birds.containers = smallBird
    Cloud.containers = skyClouds

    rbtn_image,rbtn_rect = load_image('replay_button.png',35,31,-1)
    gmo_image,gmo_rect = load_image('game_over.png',190,11,-1)

    t_images,t_rect = load_sprite_sheet('numbers.png',12,1,11,int(11*6/5),-1)
    ado_image = pygame.Surface((22,int(11*6/5)))
    ado_rect = ado_image.get_rect()
    ado_image.fill(backgroundColor)
    ado_image.blit(t_images[10],t_rect)
    t_rect.left += t_rect.width
    ado_image.blit(t_images[11],t_rect)
    ado_rect.top = height_screen * 0.1
    ado_rect.left = width_screen * 0.73

    while not g_exit:
        while s_Menu:
            pass
        while not g_Over:
            if pygame.display.get_surface() == None:
                print("Couldn't load display surface")
                g_exit = True
                g_Over = True
            else:
                for event in pygame.event.get():
                    if event.type == pygame.QUIT:
                        g_exit = True
                        g_Over = True

                    if event.type == pygame.KEYDOWN:
                        if event.key == pygame.K_SPACE:
                            if gamer_Dino.rect.bottom == int(0.98 * height_screen):
                                gamer_Dino.jumping = True
                                if pygame.mixer.get_init() != None:
                                    soundOnJump.play()
                                gamer_Dino.movement[1] = -1*gamer_Dino.jumpSpeed

                        if event.key == pygame.K_DOWN:
                            if not (gamer_Dino.jumping and gamer_Dino.dead):
                                gamer_Dino.ducking = True

                    if event.type == pygame.KEYUP:
                        if event.key == pygame.K_DOWN:
                            gamer_Dino.ducking = False
            for c in cactusan:
                c.movement[0] = -1*gp
                if pygame.sprite.collide_mask(gamer_Dino,c):
                    gamer_Dino.dead = True
                    if pygame.mixer.get_init() != None:
                        soundOnDie.play()

            for p in smallBird:
                p.movement[0] = -1*gp
                if pygame.sprite.collide_mask(gamer_Dino,p):
                    gamer_Dino.dead = True
                    if pygame.mixer.get_init() != None:
                        soundOnDie.play()

            if len(cactusan) < 2:
                if len(cactusan) == 0:
                    last_end_obs.empty()
                    last_end_obs.add(Cactus(gp,40,40))
                else:
                    for l in last_end_obs:
                        if l.rect.right < width_screen*0.7 and random.randrange(0, 50) == 10:
                            last_end_obs.empty()
                            last_end_obs.add(Cactus(gp, 40, 40))

            if len(smallBird) == 0 and random.randrange(0,200) == 10 and counter > 500:
                for l in last_end_obs:
                    if l.rect.right < width_screen*0.8:
                        last_end_obs.empty()
                        last_end_obs.add(birds(gp, 46, 40))

            if len(skyClouds) < 5 and random.randrange(0,300) == 10:
                Cloud(width_screen, random.randrange(height_screen / 5, height_screen / 2))

            gamer_Dino.update()
            cactusan.update()
            smallBird.update()
            skyClouds.update()
            new_grnd.update()
            score_boards.update(gamer_Dino.score)
            highScore.update(highest_scores)

            if pygame.display.get_surface() != None:
                screenDisplay.fill(backgroundColor)
                new_grnd.draw()
                skyClouds.draw(screenDisplay)
                score_boards.draw()
                if highest_scores != 0:
                    highScore.draw()
                    screenDisplay.blit(ado_image, ado_rect)
                cactusan.draw(screenDisplay)
                smallBird.draw(screenDisplay)
                gamer_Dino.draw()

                pygame.display.update()
            timerClock.tick(FPS)

            if gamer_Dino.dead:
                g_Over = True
                if gamer_Dino.score > highest_scores:
                    highest_scores = gamer_Dino.score

            if counter%700 == 699:
                new_grnd.speed -= 1
                gp += 1

            counter = (counter + 1)

        if g_exit:
            break

        while g_Over:
            if pygame.display.get_surface() == None:
                print("Couldn't load display surface")
                g_exit = True
                g_Over = False
            else:
                for event in pygame.event.get():
                    if event.type == pygame.QUIT:
                        g_exit = True
                        g_Over = False
                    if event.type == pygame.KEYDOWN:
                        if event.key == pygame.K_ESCAPE:
                            g_exit = True
                            g_Over = False

                        if event.key == pygame.K_RETURN or event.key == pygame.K_SPACE:
                            g_Over = False
                            gameplay()
            highScore.update(highest_scores)
            if pygame.display.get_surface() != None:
                gameover_display_message(rbtn_image, gmo_image)
                if highest_scores != 0:
                    highScore.draw()
                    screenDisplay.blit(ado_image, ado_rect)
                pygame.display.update()
            timerClock.tick(FPS)

    pygame.quit()
    quit()

def main():
    isGameQuit = introduction_screen()
    if not isGameQuit:
        gameplay()

main()

Reference Material and Link

Images

Sound Files

NOTE: Add all the above files under the “resource” folder:

Links

Endnote

This concludes our tutorial. Dino Game in Python has reached its conclusion. We have tried our level best to explain each and every concept of Dino Game in Python. We at CopyAssignments strongly believe that only by creating projects in Python, can get a strong grip on the various concept and libraries of Python. It is now up to our readers to change the look and add various other functionalities in order to make this project suitable for your resume. We have already utilized a range of libraries and developed a number of fundamental to intermediate-level functions. We really hope that the structure of this article was easy to understand. Keep learning, doing, and growing until we return with another lesson. We appreciate you visiting our website.


Also Read:

Share:

Author: Ayush Purawr