1

I have been working on a two player racing car game in Pygame. When the cars cross the finish line the correct way, I have made it reset to the start position as to 'jump' the finish, rather than cross it smoothly (which is how I want it). If I were to remove this reset feature, my cars wouldn't be able to cross, as I have placed a barrier at the other side of the finish to prevent the line being crossed in the wrong direction. So, how can I make it so that the line can't be crossed in the wrong direction, but it can be crossed over from the other side smoothly? Note: I know my lap system is not exactly functional

Here is my code:

import pygame
import time
import math
from utils import scale_image, blit_rotate_center

GRASS = scale_image(pygame.image.load("imgs/grass.jpg"), 1.94)
TRACK = scale_image(pygame.image.load("imgs/track.png"), 0.7)

TRACK_BORDER = scale_image(pygame.image.load("imgs/track-border.png"), 0.7)
TRACK_BORDER_MASK = pygame.mask.from_surface(TRACK_BORDER)
FINISH = scale_image(pygame.image.load("imgs/finish.png"), 0.7)
FINISH_MASK = pygame.mask.from_surface(FINISH)
FINISH_POSITION = (101,194.44)

RED_CAR = scale_image(pygame.image.load("imgs/red-car.png"), 0.428)
GREEN_CAR = scale_image(pygame.image.load("imgs/green-car.png"), 0.428)

WIDTH, HEIGHT = TRACK.get_width(), TRACK.get_height()
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Racing Game!")

FPS = 60

class GameInfo:
    LAPS = 5

    def __init__(self, lap=1):
        self.lap = lap
        self.started = False
        self.lap_start_time = 0

    def next_lap(self):
        self.lap += 1
        self.started = False

    def game_finished(self):
        return self.lap > self.LAPS

    def start_lap(self):
        self.started = True
        self.lap_start_time = time.time()

    def get_lap_time(self):
        if not self.started:
            return 0
        return round(time.time() - self.lap_start_time)


class AbstractCar:
    def __init__(self, max_vel, rotation_vel):
        self.img = self.IMG
        self.max_vel = max_vel
        self.vel = 0
        self.rotation_vel = rotation_vel
        self.angle = 0
        self.x, self.y = self.START_POS
        self.acceleration = 0.1

    def rotate(self, left=False, right=False):
        if left:
            self.angle += self.rotation_vel
        elif right:
            self.angle -= self.rotation_vel

    def draw(self, win):
        blit_rotate_center(win, self.img, (self.x, self.y), self.angle)

    def move_forward(self):
        self.vel = min(self.vel + self.acceleration, self.max_vel)
        self.move()

    def move_backward(self):
        self.vel = max(self.vel - self.acceleration, -self.max_vel/2)
        self.move()

    def move(self):
        radians = math.radians(self.angle)
        vertical = math.cos(radians) * self.vel
        horizontal = math.sin(radians) * self.vel

        self.y -= vertical
        self.x -= horizontal

    def collide(self, mask, x=0, y=0):
        car_mask = pygame.mask.from_surface(self.img)
        offset = (int(self.x - x), int(self.y - y))
        poi = mask.overlap(car_mask, offset)
        return poi

    def reset(self):
        self.x, self.y = self.START_POS
        self.angle = 0
        self.vel = 0        
        

class PlayerCar1(AbstractCar):
    IMG = RED_CAR
    START_POS = (113, 150)

    def reduce_speed(self):
        self.vel = max(self.vel - self.acceleration / 2, 0)
        self.move()

    def bounce(self):
        self.vel = -self.vel / 2
        self.move()
    

class PlayerCar2(AbstractCar):
    IMG = GREEN_CAR
    START_POS = (138, 150)

    def reduce_speed(self):
        self.vel = max(self.vel - self.acceleration / 2, 0)
        self.move()

    def bounce(self):
        self.vel = -self.vel / 2
        self.move()


def draw(win, images, player_car1, player_car2):
    for img, pos in images:
        win.blit(img, pos)

    player_car1.draw(win)
    player_car2.draw(win)
    pygame.display.update()

def move_player(player_car1, player_car2):
    keys = pygame.key.get_pressed()
    moved1 = False
    moved2 = False

    if keys[pygame.K_LEFT]:
        player_car1.rotate(left=True)
    if keys[pygame.K_RIGHT]:
        player_car1.rotate(right=True)
    if keys[pygame.K_UP]:
        moved1 = True
        player_car1.move_forward()
    if keys[pygame.K_DOWN]:
        moved1 = True
        player_car1.move_backward()

    if keys[pygame.K_a]:
        player_car2.rotate(left=True)
    if keys[pygame.K_d]:
        player_car2.rotate(right=True)
    if keys[pygame.K_w]:
        moved2 = True
        player_car2.move_forward()
    if keys[pygame.K_s]:
        moved2 = True
        player_car2.move_backward()

    if not moved1:
        player_car1.reduce_speed()

    if not moved2:
        player_car2.reduce_speed()

def handle_collision(player_car1, player_car2):
    if player_car1.collide(TRACK_BORDER_MASK) != None:
        player_car1.bounce()
    if player_car2.collide(TRACK_BORDER_MASK) != None:
        player_car2.bounce()

    finish_poi_collide1 = player_car1.collide(FINISH_MASK, *FINISH_POSITION)
    finish_poi_collide2 = player_car2.collide(FINISH_MASK, *FINISH_POSITION)
    if finish_poi_collide1 !=None:
        if finish_poi_collide1[1] == 0:
            player_car1.bounce()
        else:
            game_info.next_lap()
            player_car1.reset()
            print(game_info.lap)
    if finish_poi_collide2 !=None:
        if finish_poi_collide2[1] == 0:
            player_car2.bounce()
        else:
            game_info.next_lap()
            player_car2.reset()
            print(game_info.lap)
        
run = True
clock = pygame.time.Clock()
images = [(GRASS, (0, 0)), (TRACK, (0, 0)), (FINISH, FINISH_POSITION), (TRACK_BORDER, (0,0))]
player_car1 = PlayerCar1(4, 4)
player_car2 = PlayerCar2(4, 4)
game_info = GameInfo()

while run:
    clock.tick(FPS)

    draw(WIN, images, player_car1, player_car2)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
            break

    move_player(player_car1, player_car2)
    handle_collision(player_car1, player_car2)

    if game_info.game_finished():
        blit_text_center(WIN, MAIN_FONT, "You won the game!")
        pygame.time.wait(5000)
        game_info.reset()
        player_car1.reset()
        player_car2.reset()

        
    
pygame.quit()

Sorry I was unsure how I could shorten it so that it was still coherent, nevertheless please can you help me, thank you

Rabbid76
  • 202,892
  • 27
  • 131
  • 174

0 Answers0