Files
rally-racer/src/car.py
2025-10-18 21:02:24 +02:00

97 lines
2.9 KiB
Python

from math import radians
import pygame
from src.camera import Camera
from src.utils import segments_intersect
from src.vec import Vec
class Car:
MAX_SPEED = 0.05
MAX_BACK_SPEED = -0.025
ROTATE_SPEED = radians(1)
COLOR = (230, 150, 80)
WIDTH = 0.4
LENGTH = 0.6
COLLISION_MARGIN = 0.4
def __init__(self, pos: Vec, direction: Vec) -> None:
self.pos: Vec = pos
self.direction: Vec = direction
self.speed: float = 0
self.forward: bool = False
self.backward: bool = False
self.left: bool = False
self.right: bool = False
self.colliding: bool = False
def update(self):
if self.forward:
self.speed += 0.001
self.speed = min(self.MAX_SPEED, self.speed)
if self.backward:
self.speed -= 0.002
self.speed = max(self.MAX_BACK_SPEED, self.speed)
rotate_angle: float = 0
if self.left:
rotate_angle -= self.ROTATE_SPEED
if self.right:
rotate_angle += self.ROTATE_SPEED
# if self.backward:
# rotate_angle *= -1
if rotate_angle != 0:
self.direction = self.direction.rotate(rotate_angle)
self.speed *= 0.98
if abs(self.speed) < 1e-8:
self.speed = 0
self.pos += self.direction * self.speed
def render(self, surf: pygame.Surface, camera: Camera):
pts: list[Vec] = self.get_corners()
pts = [camera.world2screen(p) for p in pts]
pygame.draw.polygon(surf, self.COLOR, pts)
def get_corners(self) -> list[Vec]:
u: Vec = self.direction * self.LENGTH / 2
v: Vec = self.direction.perp * self.WIDTH / 2
pt: Vec = self.pos
p1: Vec = pt + u + v
p2: Vec = pt - u + v
p3: Vec = pt - u - v
p4: Vec = pt + u - v
return [p1, p2, p3, p4]
def check_collisions(self, polygons: list[list[Vec]]):
self.colliding = False
corners: list[Vec] = self.get_corners()
sides: list[tuple[Vec, Vec]] = [
(corners[i], corners[(i + 1) % 4]) for i in range(4)
]
for polygon in polygons:
n_pts: int = len(polygon)
for i in range(n_pts):
pt1: Vec = polygon[i]
pt2: Vec = polygon[(i + 1) % n_pts]
d: Vec = pt2 - pt1
for s1, s2 in sides:
if segments_intersect(s1, s2, pt1, pt2):
self.colliding = True
self.direction = d.normalized
n: Vec = self.direction.perp
dist: float = (self.pos - pt1).dot(n)
if dist < 0:
n *= -1
dist = -dist
self.speed = 0
self.pos = self.pos + n * (self.COLLISION_MARGIN - dist)
return