Open In App

Car Race Game In PyGame

Last Updated : 20 Mar, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

In this article, we will see how to create a racing car game in Python using Pygame. In this game, we will have functionality like driving, obstacle crashing, speed increment when levels are passed, pause, countdown, scoreboard, and Instruction manual screen. 

Required Modules:

Before going any further Install necessary packages by running the following lines in the command prompt and import them to your game.py file: 

pip install pygame
pip install time
pip install random

Project Structure:

Racing Car Game using Python Pygame

Repository 

Step 1: Import all the modules

Python3




# code for developing car racing game in python
import pygame
import time
import random


Step 2: Setting the Screen

Initialize all the Pygame modules with the help of pygame.init(). Now set the color values. Now set the captions for different texts

pygame.image.load() is used for loading image resources

Python3




# Initialize pygame and set the colors with captions
pygame.init()
  
# Define color codes
gray = (119, 118, 110)
black = (0, 0, 0)
red = (255, 0, 0)
green = (0, 200, 0)
blue = (0, 0, 200)
bright_red = (255, 0, 0)
bright_green = (0, 255, 0)
bright_blue = (0, 0, 255)
  
# Define display dimensions
display_width = 800
display_height = 600
  
# Set up game display
gamedisplays = pygame.display.set_mode((display_width, 
                                        display_height))
pygame.display.set_caption("car game")
clock = pygame.time.Clock()
  
# Load car image and background images
carimg = pygame.image.load('car1.jpg')
backgroundpic = pygame.image.load("download12.jpg")
yellow_strip = pygame.image.load("yellow strip.jpg")
strip = pygame.image.load("strip.jpg")
intro_background = pygame.image.load("background.jpg")
instruction_background = pygame.image.load("background2.jpg")
  
# Set car width and initialize pause state
car_width = 56
pause = False


Step 3: Working with Start screen

In the intro screen, there will be three buttons named START, QUIT, and INSTRUCTION. The START button will initialize the game, the QUIT button will exit the window, INSTRUCTION button will show the player controls

Now if the current screen is the intro screen then a boolean named intro will be set to True.

Draw rectangles using .rect(). Pass length, breadth, width & height to make the rectangle. 
blit() will take that rectangular Surface and put it on top of the screen.

Python3




# Intro screen
def intro_loop():
    intro = True
    while intro:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
                sys.exit()
  
        # Display background image
        gamedisplays.blit(intro_background, 
                          (0, 0))
  
        # Render and display "CAR GAME" text
        largetext = pygame.font.Font
                    ('freesansbold.ttf', 115)
        TextSurf, TextRect = text_objects
                        ("CAR GAME", largetext)
        TextRect.center = (400, 100)
        gamedisplays.blit(TextSurf, TextRect)
  
        # Render and display "START" button
        button("START", 150, 520, 100, 50, green,
                                   bright_green, "play")
  
        # Render and display "QUIT" button
        button("QUIT", 550, 520, 100, 50, red,
                                   bright_red, "quit")
  
        # Render and display "INSTRUCTION" button
        button("INSTRUCTION", 300, 520, 200,
                       50, blue, bright_blue, "intro")
  
        pygame.display.update()
        clock.tick(50)


Step 4:  Add Functionality for Buttons

Now let’s make those fancy-looking buttons into reactive buttons. Think of scenarios like what should be  the ability of the button that you have created i.e The PLAY button should trigger the main game loop with a counter which counts the number of seconds a player has played game The QUIT button should exit the window INTRO button should give an instruction manual of the game(Details discussed as you move downwards)The PAUSE button should freeze the current flow of the game and show a new screen with CONTINUE, RESTART, and MAIN MENU buttons (Details discussed as you move downwards).

Python3




# Function to create a button with specified parameters
# msg: The text to be displayed on the button
# x, y: The coordinates of the top-left corner of the button
# w, h: The width and height of the button
# ic: The color of the button when inactive
# ac: The color of the button when active (hovered over)
# action: The action to be performed when the button is clicked
  
def button(msg, x, y, w, h, ic, ac, action=None):
    # Get the current mouse position
    mouse = pygame.mouse.get_pos()
    # Get the current state of mouse buttons
    click = pygame.mouse.get_pressed()
  
    # Check if mouse is within the button's boundaries
    if x+w > mouse[0] > x and y+h > mouse[1] > y:
        # Draw button with active color
        pygame.draw.rect(gamedisplays, ac, (x, y, w, h))
        # Check if left mouse button is clicked
        # and action is specified
        if click[0] == 1 and action != None:
             # If action is "play", call the countdown()
            if action == "play":
                countdown()
             # If action is "quit", quit the game
            elif action == "quit":
                pygame.quit()
                quit()
                sys.exit()
  
            elif action == "intro":
                introduction()
            # If action is "menu", call the intro_loop() function
            elif action == "menu":
                intro_loop()
            # If action is "pause", call the paused() function
            elif action == "pause":
                paused()
             # If action is "unpause", call the unpaused() function
                unpaused()
            elif action == "unpause":
  
    else:
        # Draw button with inactive color
        pygame.draw.rect(gamedisplays, ic, (x, y, w, h))
    smalltext = pygame.font.Font("freesansbold.ttf", 20)
    textsurf, textrect = text_objects(msg, smalltext)
    textrect.center = ((x+(w/2)), (y+(h/2)))
    gamedisplays.blit(textsurf, textrect)


Step 5: Implementing Introduction Screen

Since the current screen is the instruction screen we will set the instruction boolean to true. Now in an Instruction manual, the most important things are the controls of the player and what the game is about. So we will organize those details in the instructions screen.

pygame.font.Font('fontname.ttf', fontsize) => This will display the font woth its given font size

Python3




# Function to display the introduction screen
def introduction():
    introduction = True
    while introduction:
         # Get events from the event queue
        for event in pygame.event.get():
            # If the 'QUIT' event is triggered 
            # (e.g., window closed)
            if event.type == pygame.QUIT:
                pygame.quit()  # Quit pygame
                quit()  # Quit the game
                sys.exit()  # Exit the system
        # Draw the instruction background
        gamedisplays.blit(instruction_background, (0, 0))
        # Set font for large text
        largetext = pygame.font.Font('freesansbold.ttf', 80)
        # Set font for small text
        smalltext = pygame.font.Font('freesansbold.ttf', 20)
        # Set font for medium text
        mediumtext = pygame.font.Font('freesansbold.ttf', 40)
  
        # Render and draw the instruction text
        textSurf, textRect = text_objects("This is an car game" +
               "in which you need dodge the coming cars", smalltext)
        textRect.center = ((350), (200))
        TextSurf, TextRect = text_objects("INSTRUCTION", largetext)
        TextRect.center = ((400), (100))
        gamedisplays.blit(TextSurf, TextRect)
        gamedisplays.blit(textSurf, textRect)
  
        # Render and draw the control instructions
        stextSurf, stextRect = text_objects(
            "ARROW LEFT : LEFT TURN", smalltext)
        stextRect.center = ((150), (400))
        hTextSurf, hTextRect = text_objects(
            "ARROW RIGHT : RIGHT TURN", smalltext)
        hTextRect.center = ((150), (450))
        atextSurf, atextRect = text_objects
                    ("A : ACCELERATOR", smalltext)
        atextRect.center = ((150), (500))
        rtextSurf, rtextRect = text_objects
                        ("B : BRAKE ", smalltext)
        rtextRect.center = ((150), (550))
        ptextSurf, ptextRect = text_objects
                        ("P : PAUSE  ", smalltext)
        ptextRect.center = ((150), (350))
        sTextSurf, sTextRect = text_objects
                            ("CONTROLS", mediumtext)
        sTextRect.center = ((350), (300))
        gamedisplays.blit(sTextSurf, sTextRect)
        gamedisplays.blit(stextSurf, stextRect)
        gamedisplays.blit(hTextSurf, hTextRect)
        gamedisplays.blit(atextSurf, atextRect)
        gamedisplays.blit(rtextSurf, rtextRect)
        gamedisplays.blit(ptextSurf, ptextRect)
  
        # Render and draw the 'BACK' button
        button("BACK", 600, 450, 100, 50, blue, 
                               bright_blue, "menu")
  
        pygame.display.update()  # Update the display
        clock.tick(30# Limit frame rate to 30 FPS


Step 6:  Implementing the Pause Function

Since the pause function will be there when you are playing the game it should have the capability to freeze every global action except its own function. So to make sure this happens we use a global declaration in the Pause button with the value set as True. When Pause is pressed it shows a new screen with CONTINUE, RESTART, and MAIN MENU buttons. When unpaused we simply reset the global boolean pause to False.

Python3




def paused():
    global pause
  
    # Loop for handling events during pause state
    while pause:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
                sys.exit()
        gamedisplays.blit(instruction_background, 
                          (0, 0))
        largetext = pygame.font.Font('freesansbold.ttf'
                              115)
        TextSurf, TextRect = text_objects("PAUSED"
                            largetext)
        TextRect.center = (
          (display_width/2), 
          (display_height/2))
        gamedisplays.blit(TextSurf, TextRect)
        # Create buttons for continue, restart, and main menu
        button("CONTINUE", 150
               450, 150, 50
               green, bright_green, "unpause")
        button("RESTART", 350
               450, 150, 50
               blue, bright_blue, "play")
        button("MAIN MENU", 550
               450, 200, 50
               red, bright_red, "menu")
        pygame.display.update()
        clock.tick(30)
  
  
def unpaused():
    global pause
    pause = False


Step 7: Countdown System of the Game

Let us make a scoreboard where the score and dodged cars will be accounted for. Apart from this let us also put the pause button in the countdown_background().

Python3




def countdown_background():
    # Import the necessary modules and set up the game display
    # Initialize the font for displaying text
    font = pygame.font.SysFont(None, 25)
    # Set the initial positions for the game objects
    # (background, strips, car, and text)
    x = (display_width*0.45)
    y = (display_height*0.8)
    # Draw the background images on the game display
    gamedisplays.blit(backgroundpic, (0, 0))
    gamedisplays.blit(backgroundpic, (0, 200))
    gamedisplays.blit(backgroundpic, (0, 400))
    gamedisplays.blit(backgroundpic, (700, 0))
    gamedisplays.blit(backgroundpic, (700, 200))
    gamedisplays.blit(backgroundpic, (700, 400))
    # Draw the yellow strips on the game display
    gamedisplays.blit(yellow_strip, (400, 100))
    gamedisplays.blit(yellow_strip, (400, 200))
    gamedisplays.blit(yellow_strip, (400, 300))
    gamedisplays.blit(yellow_strip, (400, 400))
    gamedisplays.blit(yellow_strip, (400, 100))
    gamedisplays.blit(yellow_strip, (400, 500))
    gamedisplays.blit(yellow_strip, (400, 0))
    gamedisplays.blit(yellow_strip, (400, 600))
    # Draw the side strips on the game display
    gamedisplays.blit(strip, (120, 200))
    gamedisplays.blit(strip, (120, 0))
    gamedisplays.blit(strip, (120, 100))
    gamedisplays.blit(strip, (680, 100))
    gamedisplays.blit(strip, (680, 0))
    gamedisplays.blit(strip, (680, 200))
    # Draw the car on the game display
    gamedisplays.blit(carimg, (x, y))
    # Draw the text for the score and number of dodged cars
    text = font.render("DODGED: 0", True, black)
    score = font.render("SCORE: 0", True, red)
    gamedisplays.blit(text, (0, 50))
    gamedisplays.blit(score, (0, 30))
    # Draw the "PAUSE" button on the game display
    button("PAUSE", 650, 0, 150, 50, blue, bright_blue, "pause")


Step 8:  Implementing the Countdown function

Whenever the game is on our countdown will be on so let’s set the boolean countdown as true. Now loop until the countdown is true and in the loop call countdown_background. Also during the countdown, the clock should be ticking every 1sec so set the clock. tick(1). After every second we will update the display. This loop continues till the countdown boolean becomes false.

gamedisplay.fill(color) => This will file the gamedisplay woth the given color
pygame.display.update() => This updates the entire game GUI every time it is called

Python3




def countdown():
    # Initialize a boolean variable to indicate if countdown is i
        # n progress
    countdown = True
    # Continue looping until countdown is complete
    while countdown:
        # Check for events in the pygame event queue
        for event in pygame.event.get():
            # If user closes the game window
            if event.type == pygame.QUIT:
                pygame.quit()  # Quit pygame
                quit()  # Quit the game
                sys.exit()  # Exit the program
        # Fill the game display with a gray color
        gamedisplays.fill(gray)
        # Call a function to display the countdown background
        countdown_background()
  
        # Display "3" in large font at the center of the screen
        largetext = pygame.font.Font('freesansbold.ttf', 115)
        TextSurf, TextRect = text_objects("3", largetext)
        TextRect.center = ((display_width/2), (display_height/2))
        gamedisplays.blit(TextSurf, TextRect)
        pygame.display.update()
        clock.tick(1# Delay for 1 second
  
        gamedisplays.fill(gray)
        countdown_background()
  
        # Display "2" in large font at the center of the screen
        largetext = pygame.font.Font('freesansbold.ttf', 115)
        TextSurf, TextRect = text_objects("2", largetext)
        TextRect.center = ((display_width/2), (display_height/2))
        gamedisplays.blit(TextSurf, TextRect)
        pygame.display.update()
        clock.tick(1# Delay for 1 second
  
        gamedisplays.fill(gray)
        countdown_background()
  
        # Display "1" in large font at the center of the screen
        largetext = pygame.font.Font('freesansbold.ttf', 115)
        TextSurf, TextRect = text_objects("1", largetext)
        TextRect.center = ((display_width/2), (display_height/2))
        gamedisplays.blit(TextSurf, TextRect)
        pygame.display.update()
        clock.tick(1# Delay for 1 second
  
        gamedisplays.fill(gray)
        countdown_background()
  
        # Display "GO!!!" in large font at the center of the screen
        largetext = pygame.font.Font('freesansbold.ttf', 115)
        TextSurf, TextRect = text_objects("GO!!!", largetext)
        TextRect.center = ((display_width/2), (display_height/2))
        gamedisplays.blit(TextSurf, TextRect)
        pygame.display.update()
        clock.tick(1# Delay for 1 second
        # Call the game loop function after the countdown is complete
        game_loop()


Step 9: Defining Obstacles in Game

In a car race there will be some obstacles like opponent cars so let us define those obstacles. For obstacles to be made, we need their x,y, and obs id. Once we get this we can easily load those obstacles in the game window.

Python3




# Loading the obstacles
def obstacle(obs_startx, obs_starty, obs):
    if obs == 0:
        obs_pic = pygame.image.load("car.jpg")
    elif obs == 1:
        obs_pic = pygame.image.load("car1.jpg")
    elif obs == 2:
        obs_pic = pygame.image.load("car2.jpg")
    elif obs == 3:
        obs_pic = pygame.image.load("car4.jpg")
    elif obs == 4:
        obs_pic = pygame.image.load("car5.jpg")
    elif obs == 5:
        obs_pic = pygame.image.load("car6.jpg")
    elif obs == 6:
        obs_pic = pygame.image.load("car7.jpg")
    gamedisplays.blit(obs_pic, (obs_startx, obs_starty))


Step 10: Implementing Score System 

The score_system() function is used for showing the score and is used in the game_loop function which will be discussed below.text_objects() function is used for text rendering on screen.message_display() is used for displaying text we just need to pass the text that we want to show on the game screen.

Python3




def score_system(passed, score):
    # Create a font object with size 25
    font = pygame.font.SysFont(None, 25)
    # Render the "Passed" text with passed parameter
    # and color black
    text = font.render("Passed"+str(passed), True, black)
    # Render the "Score" text with score parameter and color red
    score = font.render("Score"+str(score), True, red)
    # Draw the "Passed" text on the game display at (0, 50)
    # coordinates
    gamedisplays.blit(text, (0, 50))
    # Draw the "Score" text on the game display at (0, 30)
    # coordinates
    gamedisplays.blit(score, (0, 30))
  
  
def text_objects(text, font):
    # Render the given text with the given font and color black
    textsurface = font.render(text, True, black)
    return textsurface, textsurface.get_rect()
  
  
def message_display(text):
    # Create a font object with size 80
    largetext = pygame.font.Font("freesansbold.ttf", 80)
    # Render the given text with the created font
    textsurf, textrect = text_objects(text, largetext)
    textrect.center = ((display_width/2), (display_height/2))
    # Draw the rendered text on the game display at the center of the
    # screen
    gamedisplays.blit(textsurf, textrect)
    pygame.display.update()
    time.sleep(3)
    game_loop()


Step 11: Fallback Logic

Whatever a developer builds the developer should always think about some fallback mechanism i.e if something goes wrong and the program does not work then the user should know what has happened. In this case, we will be displaying the message “YOU CRASHED” on the main screen. 

Python3




def crash():
    message_display("YOU CRASHED")


Step 12: Onscreen Game UI

For a racing game, we will need a road image and some background scenery terrain. We make this UI in the background function. Yellow strips are the vertical strip in the road that are usually placed in the middle of the road. 

Python3




# on Screen UI
def background():
    gamedisplays.blit(backgroundpic, (0, 0))
    gamedisplays.blit(backgroundpic, (0, 200))
    gamedisplays.blit(backgroundpic, (0, 400))
    gamedisplays.blit(backgroundpic, (700, 0))
    gamedisplays.blit(backgroundpic, (700, 200))
    gamedisplays.blit(backgroundpic, (700, 400))
    gamedisplays.blit(yellow_strip, (400, 0))
    gamedisplays.blit(yellow_strip, (400, 100))
    gamedisplays.blit(yellow_strip, (400, 200))
    gamedisplays.blit(yellow_strip, (400, 300))
    gamedisplays.blit(yellow_strip, (400, 400))
    gamedisplays.blit(yellow_strip, (400, 500))
    gamedisplays.blit(strip, (120, 0))
    gamedisplays.blit(strip, (120, 100))
    gamedisplays.blit(strip, (120, 200))
    gamedisplays.blit(strip, (680, 0))
    gamedisplays.blit(strip, (680, 100))
    gamedisplays.blit(strip, (680, 200))
  
  
def car(x, y):
    gamedisplays.blit(carimg, (x, y))


Step 13:  Working on the Game

As soon as game_loop() is initialized we check whether the boolean pause if it’s false then we go further. We will set the obstacle_speed to 9 you can change the speed according to your convenience. Now we need to pop obstacles in random co-ords of the road so for that use random.randrange() for setting random x-coord.To check if the player has bumped into a car we will set initially a boolean bumped to false. Apart from this, In the game_loop function, we will configure controls for a player, a speed increase of obstacles after every level, and Incrementing scoreboard.

Python3




#!/usr/bin/python
# -*- coding: utf-8 -*-
  
def game_loop():
    global pause
    x = display_width * 0.45
    y = display_height * 0.8
    x_change = 0
    obstacle_speed = 9
    obs = 0
    y_change = 0
    obs_startx = random.randrange(200, display_width - 200)
    obs_starty = -750
    obs_width = 56
    obs_height = 125
    passed = 0
    level = 0
    score = 0
    y2 = 7
    fps = 120
  
    # flag to indicate that the player has been crashed
  
    bumped = False
  
    while not bumped:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
  
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    x_change = -5
                if event.key == pygame.K_RIGHT:
                    x_change = 5
                if event.key == pygame.K_a:
                    obstacle_speed += 2
                if event.key == pygame.K_b:
                    obstacle_speed -= 2
            if event.type == pygame.KEYUP:
                if event.key == pygame.K_LEFT:
                    x_change = 0
                if event.key == pygame.K_RIGHT:
                    x_change = 0
  
        # Update player's car position
  
    x += x_change
  
    # Set pause flag to True
  
    pause = True
  
    # Fill the game display with gray color
  
    gamedisplays.fill(gray)
  
    # Update background position
  
    rel_y = y2 % backgroundpic.get_rect().width
    gamedisplays.blit(backgroundpic, (0, rel_y
                                      - backgroundpic.get_rect().width))
    gamedisplays.blit(backgroundpic, (700, rel_y
                                      - backgroundpic.get_rect().width))
  
    # Draw background strips
  
    if rel_y < 800:
  
        # Draw background strips
  
        gamedisplays.blit(backgroundpic, (0, rel_y))
        gamedisplays.blit(backgroundpic, (700, rel_y))
        gamedisplays.blit(yellow_strip, (400, rel_y))
        gamedisplays.blit(yellow_strip, (400, rel_y + 100))
  
    # Update obstacle positions and display them
  
    y2 += obstacle_speed
    obs_starty -= obstacle_speed / 4
    obstacle(obs_startx, obs_starty, obs)
    obs_starty += obstacle_speed
  
    # Update player's car position and display it
  
    car(x, y)
  
    # Update score system and display score
  
    score_system(passed, score)
  
    # Check for collision with screen edges and call crash()
    # function if collision occurs
  
    if x > 690 - car_width or x < 110:
        crash()
    if x > display_width - (car_width + 110):
        crash()
    if x < 110:
        crash()
  
    # Update obstacle positions and display them
  
    if obs_starty > display_height:
        obs_starty = 0 - obs_height
        obs_startx = random.randrange(170, display_width - 170)
        obs = random.randrange(0, 7)
        passed = passed + 1
        score = passed * 10
  
        # Check for level up and update obstacle speed, display
        # level text, and pause for 3 seconds
  
        if int(passed) % 10 == 0:
            level = level + 1
            obstacle_speed += 2
            largetext = pygame.font.Font('freesansbold.ttf', 80)
            (textsurf, textrect) = text_objects('LEVEL' + str(level),
                                                largetext)
            textrect.center = (display_width / 2, display_height / 2)
            gamedisplays.blit(textsurf, textrect)
            pygame.display.update()
            time.sleep(3)
  
    # Check for collision with obstacles and call crash()
    # function if collision occurs
  
    if y < obs_starty + obs_height:
        if x > obs_startx and x < obs_startx + obs_width or x \
            + car_width > obs_startx and x + car_width < obs_startx \
                + obs_width:
            crash()
  
    # Draw pause button
  
    button(
        'Pause',
        650,
        0,
        150,
        50,
        blue,
        bright_blue,
        'pause',
    )
  
    # Update game display and set frames per second to 60
  
    pygame.display.update()
    clock.tick(60)


Step 14:  Calling the functions

Now let’s initiate the game by calling important functions i.e. 

  • intro_loop(): PLAY, QUIT, and INSTRUCTION button screen.
  • game_loop() : Logic of the game.quit(): For exiting the game window

Python3




intro_loop()
game_loop()
pygame.quit()
quit()


Step 15:  Window.py file

Now all these programs require a window tab to run. So let’s create a new file window.py in the same directory as the current one(A snapshot is attached below) and copy the following code, Now run the code & you should be able to play the game.

Python3




# Importing the Pygame library for game development
import pygame
  
# Importing the Time module for handling 
# time-related operations
import time
  
# Initializing Pygame
pygame.init()
  
# Width of the game window
display_width = 800
  
# Height of the game window
display_height = 600
  
# Setting the display mode with specified width and height
display = pygame.display.set_mode((display_width, 
                                   display_height))
  
# Updating the display
pygame.display.update()
  
# Setting the caption/title of the game window
pygame.display.set_caption("Car Game")
  
# Creating a Clock object to control game frame rate
clock = pygame.time.Clock()
  
# Flag to indicate if the car is bumped or not
bumped = False
  
# Looping until the car is bumped
while not bumped:
    # Checking for events (e.g. key presses, mouse clicks)
    for event in pygame.event.get():
        # If the QUIT event is triggered (user closes the game window)
        if event.type == pygame.QUIT:
            # Set the bumped flag to True to exit the game loop
            bumped = True
            # Quitting the game and closing the game window
            quit()


Complete Code Snippet:

Python3




# code for developing car racing game in python
import pygame
import time
import random
  
# initialize pygame and set the colors
pygame.init()
gray = (119, 118, 110)
black = (0, 0, 0)
red = (255, 0, 0)
green = (0, 200, 0)
blue = (0, 0, 200)
bright_red = (255, 0, 0)
bright_green = (0, 255, 0)
bright_blue = (0, 0, 255)
display_width = 800
display_height = 600
  
gamedisplays = pygame.display.set_mode(
    (display_width, display_height))
pygame.display.set_caption("car game")
clock = pygame.time.Clock()
carimg = pygame.image.load('car1.jpg')
backgroundpic = pygame.image.load("download12.jpg")
yellow_strip = pygame.image.load("yellow strip.jpg")
strip = pygame.image.load("strip.jpg")
intro_background = pygame.image.load("background.jpg")
instruction_background = pygame.image.load("background2.jpg")
car_width = 56
pause = False
  
# Intro screen
  
  
def intro_loop():
    intro = True
    while intro:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
                sys.exit()
        gamedisplays.blit(intro_background, (0, 0))
        largetext = pygame.font.Font('freesansbold.ttf', 115)
        TextSurf, TextRect = text_objects("CAR GAME", largetext)
        TextRect.center = (400, 100)
        gamedisplays.blit(TextSurf, TextRect)
        button("START", 150, 520, 100, 50, green,
               bright_green, "play")
        button("QUIT", 550, 520, 100,
               50,
               red,
               bright_red,
               "quit")
        button("INSTRUCTION", 300, 520, 200,
               50, blue, bright_blue,
               "intro")
        pygame.display.update()
        clock.tick(50)
  
  
def button(msg, x, y, w, h, ic, ac, action=None):
    mouse = pygame.mouse.get_pos()
    click = pygame.mouse.get_pressed()
    if x+w > mouse[0] > x and y+h > mouse[1] > y:
        pygame.draw.rect(gamedisplays,
                         ac, (x, y, w, h))
        if click[0] == 1 and action != None:
            if action == "play":
                countdown()
            elif action == "quit":
                pygame.quit()
                quit()
                sys.exit()
            elif action == "intro":
                introduction()
            elif action == "menu":
                intro_loop()
            elif action == "pause":
                paused()
            elif action == "unpause":
                unpaused()
  
    else:
        pygame.draw.rect(gamedisplays,
                         ic,
                         (x, y, w, h))
    smalltext = pygame.font.Font("freesansbold.ttf", 20)
    textsurf, textrect = text_objects(msg, smalltext)
    textrect.center = ((x+(w/2)), (y+(h/2)))
    gamedisplays.blit(textsurf, textrect)
  
  
def introduction():
    introduction = True
    while introduction:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
                sys.exit()
        gamedisplays.blit(instruction_background, (0, 0))
        largetext = pygame.font.Font('freesansbold.ttf', 80)
        smalltext = pygame.font.Font('freesansbold.ttf', 20)
        mediumtext = pygame.font.Font('freesansbold.ttf', 40)
        textSurf, textRect = text_objects(
            "This is an car game in which you" +
            "need dodge the coming cars", smalltext)
        textRect.center = ((350), (200))
        TextSurf, TextRect = text_objects("INSTRUCTION", largetext)
        TextRect.center = ((400), (100))
        gamedisplays.blit(TextSurf, TextRect)
        gamedisplays.blit(textSurf, textRect)
        stextSurf, stextRect = text_objects(
            "ARROW LEFT : LEFT TURN", smalltext)
        stextRect.center = ((150), (400))
        hTextSurf, hTextRect = text_objects(
            "ARROW RIGHT : RIGHT TURN", smalltext)
        hTextRect.center = ((150), (450))
        atextSurf, atextRect = text_objects("A : ACCELERATOR", smalltext)
        atextRect.center = ((150), (500))
        rtextSurf, rtextRect = text_objects("B : BRAKE ", smalltext)
        rtextRect.center = ((150), (550))
        ptextSurf, ptextRect = text_objects("P : PAUSE  ", smalltext)
        ptextRect.center = ((150), (350))
        sTextSurf, sTextRect = text_objects("CONTROLS", mediumtext)
        sTextRect.center = ((350), (300))
        gamedisplays.blit(sTextSurf, sTextRect)
        gamedisplays.blit(stextSurf, stextRect)
        gamedisplays.blit(hTextSurf, hTextRect)
        gamedisplays.blit(atextSurf, atextRect)
        gamedisplays.blit(rtextSurf, rtextRect)
        gamedisplays.blit(ptextSurf, ptextRect)
        button("BACK", 600, 450, 100, 50, blue,
               bright_blue, "menu")
        pygame.display.update()
        clock.tick(30)
  
  
def paused():
    global pause
  
    while pause:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
                sys.exit()
        gamedisplays.blit(instruction_background, (0, 0))
        largetext = pygame.font.Font('freesansbold.ttf', 115)
        TextSurf, TextRect = text_objects("PAUSED", largetext)
        TextRect.center = (
            (display_width/2),
            (display_height/2)
        )
        gamedisplays.blit(TextSurf, TextRect)
        button("CONTINUE", 150, 450,
               150, 50, green,
               bright_green, "unpause")
        button("RESTART", 350, 450, 150,
               50, blue, bright_blue,
               "play")
        button("MAIN MENU", 550, 450,
               200, 50, red, bright_red,
               "menu")
        pygame.display.update()
        clock.tick(30)
  
  
def unpaused():
    global pause
    pause = False
  
  
def countdown_background():
    font = pygame.font.SysFont(None, 25)
    x = (display_width*0.45)
    y = (display_height*0.8)
    gamedisplays.blit(backgroundpic, (0, 0))
    gamedisplays.blit(backgroundpic, (0, 200))
    gamedisplays.blit(backgroundpic, (0, 400))
    gamedisplays.blit(backgroundpic, (700, 0))
    gamedisplays.blit(backgroundpic, (700, 200))
    gamedisplays.blit(backgroundpic, (700, 400))
    gamedisplays.blit(yellow_strip, (400, 100))
    gamedisplays.blit(yellow_strip, (400, 200))
    gamedisplays.blit(yellow_strip, (400, 300))
    gamedisplays.blit(yellow_strip, (400, 400))
    gamedisplays.blit(yellow_strip, (400, 100))
    gamedisplays.blit(yellow_strip, (400, 500))
    gamedisplays.blit(yellow_strip, (400, 0))
    gamedisplays.blit(yellow_strip, (400, 600))
    gamedisplays.blit(strip, (120, 200))
    gamedisplays.blit(strip, (120, 0))
    gamedisplays.blit(strip, (120, 100))
    gamedisplays.blit(strip, (680, 100))
    gamedisplays.blit(strip, (680, 0))
    gamedisplays.blit(strip, (680, 200))
    gamedisplays.blit(carimg, (x, y))
    text = font.render("DODGED: 0", True, black)
    score = font.render("SCORE: 0", True, red)
    gamedisplays.blit(text, (0, 50))
    gamedisplays.blit(score, (0, 30))
    button("PAUSE", 650, 0, 150, 50, blue, bright_blue, "pause")
  
  
def countdown():
    countdown = True
  
    while countdown:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
                sys.exit()
        gamedisplays.fill(gray)
        countdown_background()
        largetext = pygame.font.Font('freesansbold.ttf', 115)
        TextSurf, TextRect = text_objects("3", largetext)
        TextRect.center = (
            (display_width/2),
            (display_height/2))
        gamedisplays.blit(TextSurf, TextRect)
        pygame.display.update()
        clock.tick(1)
        gamedisplays.fill(gray)
        countdown_background()
        largetext = pygame.font.Font('freesansbold.ttf', 115)
        TextSurf, TextRect = text_objects("2", largetext)
        TextRect.center = (
            (display_width/2),
            (display_height/2))
        gamedisplays.blit(TextSurf, TextRect)
        pygame.display.update()
        clock.tick(1)
        gamedisplays.fill(gray)
        countdown_background()
        largetext = pygame.font.Font('freesansbold.ttf', 115)
        TextSurf, TextRect = text_objects("1", largetext)
        TextRect.center = (
            (display_width/2),
            (display_height/2))
        gamedisplays.blit(TextSurf, TextRect)
        pygame.display.update()
        clock.tick(1)
        gamedisplays.fill(gray)
        countdown_background()
        largetext = pygame.font.Font('freesansbold.ttf', 115)
        TextSurf, TextRect = text_objects("GO!!!", largetext)
        TextRect.center = (
            (display_width/2),
            (display_height/2))
        gamedisplays.blit(TextSurf, TextRect)
        pygame.display.update()
        clock.tick(1)
        game_loop()
  
  
def obstacle(obs_startx, obs_starty, obs):
    if obs == 0:
        obs_pic = pygame.image.load("car.jpg")
    elif obs == 1:
        obs_pic = pygame.image.load("car1.jpg")
    elif obs == 2:
        obs_pic = pygame.image.load("car2.jpg")
    elif obs == 3:
        obs_pic = pygame.image.load("car4.jpg")
    elif obs == 4:
        obs_pic = pygame.image.load("car5.jpg")
    elif obs == 5:
        obs_pic = pygame.image.load("car6.jpg")
    elif obs == 6:
        obs_pic = pygame.image.load("car7.jpg")
    gamedisplays.blit(obs_pic,
                      (obs_startx,
                       obs_starty))
  
  
def score_system(passed, score):
    font = pygame.font.SysFont(None, 25)
    text = font.render("Passed"+str(passed), True, black)
    score = font.render("Score"+str(score), True, red)
    gamedisplays.blit(text, (0, 50))
    gamedisplays.blit(score, (0, 30))
  
  
def text_objects(text, font):
    textsurface = font.render(text, True, black)
    return textsurface, textsurface.get_rect()
  
  
def message_display(text):
    largetext = pygame.font.Font("freesansbold.ttf", 80)
    textsurf, textrect = text_objects(text, largetext)
    textrect.center = (
        (display_width/2),
        (display_height/2))
    gamedisplays.blit(textsurf, textrect)
    pygame.display.update()
    time.sleep(3)
    game_loop()
  
  
def crash():
    message_display("YOU CRASHED")
  
  
def background():
    gamedisplays.blit(backgroundpic, (0, 0))
    gamedisplays.blit(backgroundpic, (0, 200))
    gamedisplays.blit(backgroundpic, (0, 400))
    gamedisplays.blit(backgroundpic, (700, 0))
    gamedisplays.blit(backgroundpic, (700, 200))
    gamedisplays.blit(backgroundpic, (700, 400))
    gamedisplays.blit(yellow_strip, (400, 0))
    gamedisplays.blit(yellow_strip, (400, 100))
    gamedisplays.blit(yellow_strip, (400, 200))
    gamedisplays.blit(yellow_strip, (400, 300))
    gamedisplays.blit(yellow_strip, (400, 400))
    gamedisplays.blit(yellow_strip, (400, 500))
    gamedisplays.blit(strip, (120, 0))
    gamedisplays.blit(strip, (120, 100))
    gamedisplays.blit(strip, (120, 200))
    gamedisplays.blit(strip, (680, 0))
    gamedisplays.blit(strip, (680, 100))
    gamedisplays.blit(strip, (680, 200))
  
  
def car(x, y):
    gamedisplays.blit(carimg, (x, y))
  
  
def game_loop():
    global pause
    x = (display_width*0.45)
    y = (display_height*0.8)
    x_change = 0
    obstacle_speed = 9
    obs = 0
    y_change = 0
    obs_startx = random.randrange(200,
                                  (display_width-200))
    obs_starty = -750
    obs_width = 56
    obs_height = 125
    passed = 0
    level = 0
    score = 0
    y2 = 7
    fps = 120
  
    bumped = False
    while not bumped:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
  
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    x_change = -5
                if event.key == pygame.K_RIGHT:
                    x_change = 5
                if event.key == pygame.K_a:
                    obstacle_speed += 2
                if event.key == pygame.K_b:
                    obstacle_speed -= 2
            if event.type == pygame.KEYUP:
                if event.key == pygame.K_LEFT:
                    x_change = 0
                if event.key == pygame.K_RIGHT:
                    x_change = 0
  
        x += x_change
        pause = True
        gamedisplays.fill(gray)
  
        rel_y = y2 % backgroundpic.get_rect().width
        gamedisplays.blit(
            backgroundpic, (0,
                            rel_y-backgroundpic.get_rect().width))
        gamedisplays.blit(backgroundpic,
                          (700, rel_y -
                           backgroundpic.get_rect().width))
        if rel_y < 800:
            gamedisplays.blit(backgroundpic, (0, rel_y))
            gamedisplays.blit(backgroundpic, (700, rel_y))
            gamedisplays.blit(yellow_strip, (400, rel_y))
            gamedisplays.blit(yellow_strip, (400, rel_y+100))
            gamedisplays.blit(yellow_strip, (400, rel_y+200))
            gamedisplays.blit(yellow_strip, (400, rel_y+300))
            gamedisplays.blit(yellow_strip, (400, rel_y+400))
            gamedisplays.blit(yellow_strip, (400, rel_y+500))
            gamedisplays.blit(yellow_strip, (400, rel_y-100))
            gamedisplays.blit(strip, (120, rel_y-200))
            gamedisplays.blit(strip, (120, rel_y+20))
            gamedisplays.blit(strip, (120, rel_y+30))
            gamedisplays.blit(strip, (680, rel_y-100))
            gamedisplays.blit(strip, (680, rel_y+20))
            gamedisplays.blit(strip, (680, rel_y+30))
  
        y2 += obstacle_speed
  
        obs_starty -= (obstacle_speed/4)
        obstacle(obs_startx, obs_starty, obs)
        obs_starty += obstacle_speed
        car(x, y)
        score_system(passed, score)
        if x > 690-car_width or x < 110:
            crash()
        if x > display_width-(car_width+110) or x < 110:
            crash()
        if obs_starty > display_height:
            obs_starty = 0-obs_height
            obs_startx = random.randrange(170,
                                          (display_width-170))
            obs = random.randrange(0, 7)
            passed = passed+1
            score = passed*10
            if int(passed) % 10 == 0:
                level = level+1
                obstacle_speed+2
                largetext = pygame.font.Font("freesansbold.ttf", 80)
                textsurf, textrect = text_objects(
                    "LEVEL"+str(level), largetext)
                textrect.center = (
                    (display_width/2), (display_height/2))
                gamedisplays.blit(textsurf, textrect)
                pygame.display.update()
                time.sleep(3)
  
        if y < obs_starty+obs_height:
            if x > obs_startx and x < \
                    obs_startx + obs_width or x+car_width > \
                    (obs_startx and x+car_width < obs_startx+obs_width):
                crash()
        button("Pause", 650, 0, 150, 50, blue, bright_blue, "pause")
        pygame.display.update()
        clock.tick(60)
  
  
intro_loop()
game_loop()
pygame.quit()
quit()


Output :

Racing Car Game using Python Pygame

Output GIF



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads