parent
74fb7c664c
commit
788c7e983c
@ -1,290 +0,0 @@
|
||||
import pygame
|
||||
import time
|
||||
import math
|
||||
from utils import scale_image, blit_rotate_center, blit_text_center
|
||||
pygame.font.init()
|
||||
|
||||
GRASS = scale_image(pygame.image.load("imgs/grass.jpg"), 2.5)
|
||||
TRACK = scale_image(pygame.image.load("imgs/track.png"), 0.9)
|
||||
|
||||
TRACK_BORDER = scale_image(pygame.image.load("imgs/track-border.png"), 0.9)
|
||||
TRACK_BORDER_MASK = pygame.mask.from_surface(TRACK_BORDER)
|
||||
|
||||
FINISH = pygame.image.load("imgs/finish.png")
|
||||
FINISH_MASK = pygame.mask.from_surface(FINISH)
|
||||
FINISH_POSITION = (130, 250)
|
||||
|
||||
RED_CAR = scale_image(pygame.image.load("imgs/red-car.png"), 0.55)
|
||||
GREEN_CAR = scale_image(pygame.image.load("imgs/green-car.png"), 0.55)
|
||||
|
||||
WIDTH, HEIGHT = TRACK.get_width(), TRACK.get_height()
|
||||
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
|
||||
pygame.display.set_caption("Racing Game!")
|
||||
|
||||
MAIN_FONT = pygame.font.SysFont("comicsans", 44)
|
||||
|
||||
FPS = 60
|
||||
PATH = [(175, 119), (110, 70), (56, 133), (70, 481), (318, 731), (404, 680), (418, 521), (507, 475), (600, 551), (613, 715), (736, 713),
|
||||
(734, 399), (611, 357), (409, 343), (433, 257), (697, 258), (738, 123), (581, 71), (303, 78), (275, 377), (176, 388), (178, 260)]
|
||||
|
||||
|
||||
class GameInfo:
|
||||
LEVELS = 10
|
||||
|
||||
def __init__(self, level=1):
|
||||
self.level = level
|
||||
self.started = False
|
||||
self.level_start_time = 0
|
||||
|
||||
def next_level(self):
|
||||
self.level += 1
|
||||
self.started = False
|
||||
|
||||
def reset(self):
|
||||
self.level = 1
|
||||
self.started = False
|
||||
self.level_start_time = 0
|
||||
|
||||
def game_finished(self):
|
||||
return self.level > self.LEVELS
|
||||
|
||||
def start_level(self):
|
||||
self.started = True
|
||||
self.level_start_time = time.time()
|
||||
|
||||
def get_level_time(self):
|
||||
if not self.started:
|
||||
return 0
|
||||
return round(time.time() - self.level_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 PlayerCar(AbstractCar):
|
||||
IMG = RED_CAR
|
||||
START_POS = (180, 200)
|
||||
|
||||
def reduce_speed(self):
|
||||
self.vel = max(self.vel - self.acceleration / 2, 0)
|
||||
self.move()
|
||||
|
||||
def bounce(self):
|
||||
self.vel = -self.vel
|
||||
self.move()
|
||||
|
||||
|
||||
class ComputerCar(AbstractCar):
|
||||
IMG = GREEN_CAR
|
||||
START_POS = (150, 200)
|
||||
|
||||
def __init__(self, max_vel, rotation_vel, path=[]):
|
||||
super().__init__(max_vel, rotation_vel)
|
||||
self.path = path
|
||||
self.current_point = 0
|
||||
self.vel = max_vel
|
||||
|
||||
def draw_points(self, win):
|
||||
for point in self.path:
|
||||
pygame.draw.circle(win, (255, 0, 0), point, 5)
|
||||
|
||||
def draw(self, win):
|
||||
super().draw(win)
|
||||
# self.draw_points(win)
|
||||
|
||||
def calculate_angle(self):
|
||||
target_x, target_y = self.path[self.current_point]
|
||||
x_diff = target_x - self.x
|
||||
y_diff = target_y - self.y
|
||||
|
||||
if y_diff == 0:
|
||||
desired_radian_angle = math.pi / 2
|
||||
else:
|
||||
desired_radian_angle = math.atan(x_diff / y_diff)
|
||||
|
||||
if target_y > self.y:
|
||||
desired_radian_angle += math.pi
|
||||
|
||||
difference_in_angle = self.angle - math.degrees(desired_radian_angle)
|
||||
if difference_in_angle >= 180:
|
||||
difference_in_angle -= 360
|
||||
|
||||
if difference_in_angle > 0:
|
||||
self.angle -= min(self.rotation_vel, abs(difference_in_angle))
|
||||
else:
|
||||
self.angle += min(self.rotation_vel, abs(difference_in_angle))
|
||||
|
||||
def update_path_point(self):
|
||||
target = self.path[self.current_point]
|
||||
rect = pygame.Rect(
|
||||
self.x, self.y, self.img.get_width(), self.img.get_height())
|
||||
if rect.collidepoint(*target):
|
||||
self.current_point += 1
|
||||
|
||||
def move(self):
|
||||
if self.current_point >= len(self.path):
|
||||
return
|
||||
|
||||
self.calculate_angle()
|
||||
self.update_path_point()
|
||||
super().move()
|
||||
|
||||
def next_level(self, level):
|
||||
self.reset()
|
||||
self.vel = self.max_vel + (level - 1) * 0.2
|
||||
self.current_point = 0
|
||||
|
||||
|
||||
def draw(win, images, player_car, computer_car, game_info):
|
||||
for img, pos in images:
|
||||
win.blit(img, pos)
|
||||
|
||||
level_text = MAIN_FONT.render(
|
||||
f"Level {game_info.level}", 1, (255, 255, 255))
|
||||
win.blit(level_text, (10, HEIGHT - level_text.get_height() - 70))
|
||||
|
||||
time_text = MAIN_FONT.render(
|
||||
f"Time: {game_info.get_level_time()}s", 1, (255, 255, 255))
|
||||
win.blit(time_text, (10, HEIGHT - time_text.get_height() - 40))
|
||||
|
||||
vel_text = MAIN_FONT.render(
|
||||
f"Vel: {round(player_car.vel, 1)}px/s", 1, (255, 255, 255))
|
||||
win.blit(vel_text, (10, HEIGHT - vel_text.get_height() - 10))
|
||||
|
||||
player_car.draw(win)
|
||||
computer_car.draw(win)
|
||||
pygame.display.update()
|
||||
|
||||
|
||||
def move_player(player_car):
|
||||
keys = pygame.key.get_pressed()
|
||||
moved = False
|
||||
|
||||
if keys[pygame.K_a]:
|
||||
player_car.rotate(left=True)
|
||||
if keys[pygame.K_d]:
|
||||
player_car.rotate(right=True)
|
||||
if keys[pygame.K_w]:
|
||||
moved = True
|
||||
player_car.move_forward()
|
||||
if keys[pygame.K_s]:
|
||||
moved = True
|
||||
player_car.move_backward()
|
||||
|
||||
if not moved:
|
||||
player_car.reduce_speed()
|
||||
|
||||
|
||||
def handle_collision(player_car, computer_car, game_info):
|
||||
if player_car.collide(TRACK_BORDER_MASK) != None:
|
||||
player_car.bounce()
|
||||
|
||||
computer_finish_poi_collide = computer_car.collide(
|
||||
FINISH_MASK, *FINISH_POSITION)
|
||||
if computer_finish_poi_collide != None:
|
||||
blit_text_center(WIN, MAIN_FONT, "You lost!")
|
||||
pygame.display.update()
|
||||
pygame.time.wait(5000)
|
||||
game_info.reset()
|
||||
player_car.reset()
|
||||
computer_car.reset()
|
||||
|
||||
player_finish_poi_collide = player_car.collide(
|
||||
FINISH_MASK, *FINISH_POSITION)
|
||||
if player_finish_poi_collide != None:
|
||||
if player_finish_poi_collide[1] == 0:
|
||||
player_car.bounce()
|
||||
else:
|
||||
game_info.next_level()
|
||||
player_car.reset()
|
||||
computer_car.next_level(game_info.level)
|
||||
|
||||
|
||||
run = True
|
||||
clock = pygame.time.Clock()
|
||||
images = [(GRASS, (0, 0)), (TRACK, (0, 0)),
|
||||
(FINISH, FINISH_POSITION), (TRACK_BORDER, (0, 0))]
|
||||
player_car = PlayerCar(4, 4)
|
||||
computer_car = ComputerCar(2, 4, PATH)
|
||||
game_info = GameInfo()
|
||||
|
||||
while run:
|
||||
clock.tick(FPS)
|
||||
|
||||
draw(WIN, images, player_car, computer_car, game_info)
|
||||
|
||||
while not game_info.started:
|
||||
blit_text_center(
|
||||
WIN, MAIN_FONT, f"Press any key to start level {game_info.level}!")
|
||||
pygame.display.update()
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
pygame.quit()
|
||||
break
|
||||
|
||||
if event.type == pygame.KEYDOWN:
|
||||
game_info.start_level()
|
||||
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
run = False
|
||||
break
|
||||
|
||||
move_player(player_car)
|
||||
computer_car.move()
|
||||
|
||||
handle_collision(player_car, computer_car, game_info)
|
||||
|
||||
if game_info.game_finished():
|
||||
blit_text_center(WIN, MAIN_FONT, "You won the game!")
|
||||
pygame.time.wait(5000)
|
||||
game_info.reset()
|
||||
player_car.reset()
|
||||
computer_car.reset()
|
||||
|
||||
|
||||
pygame.quit()
|
Loading…
Reference in new issue