This tutorial is the fourth tutorial in a series of five Pygame tutorials:

For our car racing game we will add a few more cars.

Each car is an object that will be instantiated from the Car Class.

Looking at the code from our previous tutorial we are adding a few properties and methods to our Car class. This is to allow for the coming cars to have different sizes (width and height), colors and different speed. See the changes on the car.py file.

Then, in our main program, we are going to create four extra cars and we will add these to a list called “all_comming_cars”. Each car will be given a different color, a speed and a different starting position (x & y coordinates). This is what the code on the main.py file does on lines 34 to 62.

The four cars will be moving down (starting at the top of the screen). When they reach the bottom of the screen they will be given a new color, speed and starting position towards the top of the screen. This is what the code on the main.py file does on lines 89 to 94.

The overall speed of the game will be stored in a variable called speed initialised on line 15 of the main.py file. New event handlers will detect when the user presses the UP or DOWN keys on the keyboard. These will increment or decrement the speed variable by 0.05. See lines 82 to 85 of the main.py file.

Here is the code for our latest Car class and for our main program:

Car.py main.py import pygame WHITE = (255, 255, 255) class Car(pygame.sprite.Sprite): #This class represents a car. It derives from the "Sprite" class in Pygame. def __init__(self, color, width, height, speed): # Call the parent class (Sprite) constructor super().__init__() # Pass in the color of the car, and its x and y position, width and height. # Set the background color and set it to be transparent self.image = pygame.Surface([width, height]) self.image.fill(WHITE) self.image.set_colorkey(WHITE) #Initialise attributes of the car. self.width=width self.height=height self.color = color self.speed = speed # Draw the car (a rectangle!) pygame.draw.rect(self.image, self.color, [0, 0, self.width, self.height]) # Instead we could load a proper picture of a car... # self.image = pygame.image.load("car.png").convert_alpha() # Fetch the rectangle object that has the dimensions of the image. self.rect = self.image.get_rect() def moveRight(self, pixels): self.rect.x += pixels def moveLeft(self, pixels): self.rect.x -= pixels def moveForward(self, speed): self.rect.y += self.speed * speed / 20 def moveBackward(self, speed): self.rect.y -= self.speed * speed / 20 def changeSpeed(self, speed): self.speed = speed def repaint(self, color): self.color = color pygame.draw.rect(self.image, self.color, [0, 0, self.width, self.height]) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 import pygame WHITE = ( 255 , 255 , 255 ) class Car ( pygame . sprite . Sprite ) : #This class represents a car. It derives from the "Sprite" class in Pygame. def __init__ ( self , color , width , height , speed ) : # Call the parent class (Sprite) constructor super ( ) . __init__ ( ) # Pass in the color of the car, and its x and y position, width and height. # Set the background color and set it to be transparent self . image = pygame . Surface ( [ width , height ] ) self . image . fill ( WHITE ) self . image . set_colorkey ( WHITE ) #Initialise attributes of the car. self . width = width self . height = height self . color = color self . speed = speed # Draw the car (a rectangle!) pygame . draw . rect ( self . image , self . color , [ 0 , 0 , self . width , self . height ] ) # Instead we could load a proper picture of a car... # self.image = pygame.image.load("car.png").convert_alpha() # Fetch the rectangle object that has the dimensions of the image. self . rect = self . image . get_rect ( ) def moveRight ( self , pixels ) : self . rect . x += pixels def moveLeft ( self , pixels ) : self . rect . x -= pixels def moveForward ( self , speed ) : self . rect . y += self . speed * speed / 20 def moveBackward ( self , speed ) : self . rect . y -= self . speed * speed / 20 def changeSpeed ( self , speed ) : self . speed = speed def repaint ( self , color ) : self . color = color pygame . draw . rect ( self . image , self . color , [ 0 , 0 , self . width , self . height ] ) import pygame, random #Let's import the Car Class from car import Car pygame.init() GREEN = (20, 255, 140) GREY = (210, 210 ,210) WHITE = (255, 255, 255) RED = (255, 0, 0) PURPLE = (255, 0, 255) YELLOW = (255, 255, 0) CYAN = (0, 255, 255) BLUE = (100, 100, 255) speed = 1 colorList = (RED, GREEN, PURPLE, YELLOW, CYAN, BLUE) SCREENWIDTH=800 SCREENHEIGHT=600 size = (SCREENWIDTH, SCREENHEIGHT) screen = pygame.display.set_mode(size) pygame.display.set_caption("Car Racing") #This will be a list that will contain all the sprites we intend to use in our game. all_sprites_list = pygame.sprite.Group() playerCar = Car(RED, 60, 80, 70) playerCar.rect.x = 160 playerCar.rect.y = SCREENHEIGHT - 100 car1 = Car(PURPLE, 60, 80, random.randint(50,100)) car1.rect.x = 60 car1.rect.y = -100 car2 = Car(YELLOW, 60, 80, random.randint(50,100)) car2.rect.x = 160 car2.rect.y = -600 car3 = Car(CYAN, 60, 80, random.randint(50,100)) car3.rect.x = 260 car3.rect.y = -300 car4 = Car(BLUE, 60, 80, random.randint(50,100)) car4.rect.x = 360 car4.rect.y = -900 # Add the car to the list of objects all_sprites_list.add(playerCar) all_sprites_list.add(car1) all_sprites_list.add(car2) all_sprites_list.add(car3) all_sprites_list.add(car4) all_coming_cars = pygame.sprite.Group() all_coming_cars.add(car1) all_coming_cars.add(car2) all_coming_cars.add(car3) all_coming_cars.add(car4) #Allowing the user to close the window... carryOn = True clock=pygame.time.Clock() while carryOn: for event in pygame.event.get(): if event.type==pygame.QUIT: carryOn=False elif event.type==pygame.KEYDOWN: if event.key==pygame.K_x: playerCar.moveRight(10) keys = pygame.key.get_pressed() if keys[pygame.K_LEFT]: playerCar.moveLeft(5) if keys[pygame.K_RIGHT]: playerCar.moveRight(5) if keys[pygame.K_UP]: speed += 0.05 if keys[pygame.K_DOWN]: speed -= 0.05 #Game Logic for car in all_coming_cars: car.moveForward(speed) if car.rect.y > SCREENHEIGHT: car.changeSpeed(random.randint(50,100)) car.repaint(random.choice(colorList)) car.rect.y = -200 all_sprites_list.update() #Drawing on Screen screen.fill(GREEN) #Draw The Road pygame.draw.rect(screen, GREY, [40,0, 400,SCREENHEIGHT]) #Draw Line painting on the road pygame.draw.line(screen, WHITE, [140,0],[140,SCREENHEIGHT],5) #Draw Line painting on the road pygame.draw.line(screen, WHITE, [240,0],[240,SCREENHEIGHT],5) #Draw Line painting on the road pygame.draw.line(screen, WHITE, [340,0],[340,SCREENHEIGHT],5) #Now let's draw all the sprites in one go. (For now we only have 1 sprite!) all_sprites_list.draw(screen) #Refresh Screen pygame.display.flip() #Number of frames per secong e.g. 60 clock.tick(60) pygame.quit() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 import pygame , random #Let's import the Car Class from car import Car pygame . init ( ) GREEN = ( 20 , 255 , 140 ) GREY = ( 210 , 210 , 210 ) WHITE = ( 255 , 255 , 255 ) RED = ( 255 , 0 , 0 ) PURPLE = ( 255 , 0 , 255 ) YELLOW = ( 255 , 255 , 0 ) CYAN = ( 0 , 255 , 255 ) BLUE = ( 100 , 100 , 255 ) speed = 1 colorList = ( RED , GREEN , PURPLE , YELLOW , CYAN , BLUE ) SCREENWIDTH = 800 SCREENHEIGHT = 600 size = ( SCREENWIDTH , SCREENHEIGHT ) screen = pygame . display . set_mode ( size ) pygame . display . set_caption ( "Car Racing" ) #This will be a list that will contain all the sprites we intend to use in our game. all_sprites_list = pygame . sprite . Group ( ) playerCar = Car ( RED , 60 , 80 , 70 ) playerCar . rect . x = 160 playerCar . rect . y = SCREENHEIGHT - 100 car1 = Car ( PURPLE , 60 , 80 , random . randint ( 50 , 100 ) ) car1 . rect . x = 60 car1 . rect . y = - 100 car2 = Car ( YELLOW , 60 , 80 , random . randint ( 50 , 100 ) ) car2 . rect . x = 160 car2 . rect . y = - 600 car3 = Car ( CYAN , 60 , 80 , random . randint ( 50 , 100 ) ) car3 . rect . x = 260 car3 . rect . y = - 300 car4 = Car ( BLUE , 60 , 80 , random . randint ( 50 , 100 ) ) car4 . rect . x = 360 car4 . rect . y = - 900 # Add the car to the list of objects all_sprites_list . add ( playerCar ) all_sprites_list . add ( car1 ) all_sprites_list . add ( car2 ) all_sprites_list . add ( car3 ) all_sprites_list . add ( car4 ) all_coming_cars = pygame . sprite . Group ( ) all_coming_cars . add ( car1 ) all_coming_cars . add ( car2 ) all_coming_cars . add ( car3 ) all_coming_cars . add ( car4 ) #Allowing the user to close the window... carryOn = True clock = pygame . time . Clock ( ) while carryOn : for event in pygame . event . get ( ) : if event . type == pygame . QUIT : carryOn = False elif event . type == pygame . KEYDOWN : if event . key == pygame . K_x : playerCar . moveRight ( 10 ) keys = pygame . key . get_pressed ( ) if keys [ pygame . K_LEFT ] : playerCar . moveLeft ( 5 ) if keys [ pygame . K_RIGHT ] : playerCar . moveRight ( 5 ) if keys [ pygame . K_UP ] : speed += 0.05 if keys [ pygame . K_DOWN ] : speed -= 0.05 #Game Logic for car in all_coming_cars : car . moveForward ( speed ) if car . rect . y > SCREENHEIGHT : car . changeSpeed ( random . randint ( 50 , 100 ) ) car . repaint ( random . choice ( colorList ) ) car . rect . y = - 200 all_sprites_list . update ( ) #Drawing on Screen screen . fill ( GREEN ) #Draw The Road pygame . draw . rect ( screen , GREY , [ 40 , 0 , 400 , SCREENHEIGHT ] ) #Draw Line painting on the road pygame . draw . line ( screen , WHITE , [ 140 , 0 ] , [ 140 , SCREENHEIGHT ] , 5 ) #Draw Line painting on the road pygame . draw . line ( screen , WHITE , [ 240 , 0 ] , [ 240 , SCREENHEIGHT ] , 5 ) #Draw Line painting on the road pygame . draw . line ( screen , WHITE , [ 340 , 0 ] , [ 340 , SCREENHEIGHT ] , 5 ) #Now let's draw all the sprites in one go. (For now we only have 1 sprite!) all_sprites_list . draw ( screen ) #Refresh Screen pygame . display . flip ( ) #Number of frames per secong e.g. 60 clock . tick ( 60 ) pygame . quit ( )

Detecting Collision

The next addition to our game is used on most 2D arcarde games: The aim is to check when a sprite (e.g. playerCar) is colliding with other sprites (in this case cars stored in the all_coming_cars list).

You would need to add these lines of code in the “game logic” section of your main program loop. For instance you could add these lines on line 95 of the code provided above (main.py).