feat: initial implementation of image capture
This commit is contained in:
		
							
								
								
									
										12
									
								
								src/car.py
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								src/car.py
									
									
									
									
									
								
							| @@ -1,5 +1,7 @@ | |||||||
|  | from __future__ import annotations | ||||||
|  |  | ||||||
| from math import radians | from math import radians | ||||||
| from typing import Optional | from typing import TYPE_CHECKING, Optional | ||||||
|  |  | ||||||
| import pygame | import pygame | ||||||
|  |  | ||||||
| @@ -8,6 +10,9 @@ from src.remote_controller import RemoteController | |||||||
| from src.utils import get_segments_intersection, segments_intersect | from src.utils import get_segments_intersection, segments_intersect | ||||||
| from src.vec import Vec | from src.vec import Vec | ||||||
|  |  | ||||||
|  | if TYPE_CHECKING: | ||||||
|  |     from src.game import Game | ||||||
|  |  | ||||||
|  |  | ||||||
| def sign(x): return 0 if x == 0 else (-1 if x < 0 else 1) | def sign(x): return 0 if x == 0 else (-1 if x < 0 else 1) | ||||||
|  |  | ||||||
| @@ -27,7 +32,8 @@ class Car: | |||||||
|     RAYS_FOV = 180 |     RAYS_FOV = 180 | ||||||
|     RAYS_MAX_DIST = 100 |     RAYS_MAX_DIST = 100 | ||||||
|  |  | ||||||
|     def __init__(self, pos: Vec, direction: Vec) -> None: |     def __init__(self, game: Game, pos: Vec, direction: Vec) -> None: | ||||||
|  |         self.game: Game = game | ||||||
|         self.initial_pos: Vec = pos.copy() |         self.initial_pos: Vec = pos.copy() | ||||||
|         self.initial_dir: Vec = direction.copy() |         self.initial_dir: Vec = direction.copy() | ||||||
|         self.pos: Vec = pos |         self.pos: Vec = pos | ||||||
| @@ -42,7 +48,7 @@ class Car: | |||||||
|         self.rays: list[float] = [0] * self.N_RAYS |         self.rays: list[float] = [0] * self.N_RAYS | ||||||
|         self.rays_end: list[Vec] = [Vec() for _ in range(self.N_RAYS)] |         self.rays_end: list[Vec] = [Vec() for _ in range(self.N_RAYS)] | ||||||
|  |  | ||||||
|         self.controller: RemoteController = RemoteController(self) |         self.controller: RemoteController = RemoteController(self.game, self) | ||||||
|         self.controller.start_server() |         self.controller.start_server() | ||||||
|  |  | ||||||
|     def update(self, dt: float): |     def update(self, dt: float): | ||||||
|   | |||||||
							
								
								
									
										11
									
								
								src/game.py
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								src/game.py
									
									
									
									
									
								
							| @@ -19,10 +19,11 @@ class Game: | |||||||
|         self.win: pygame.Surface = pygame.display.set_mode( |         self.win: pygame.Surface = pygame.display.set_mode( | ||||||
|             self.DEFAULT_SIZE, pygame.RESIZABLE |             self.DEFAULT_SIZE, pygame.RESIZABLE | ||||||
|         ) |         ) | ||||||
|  |         self.game_surf: pygame.Surface = pygame.Surface(self.DEFAULT_SIZE) | ||||||
|         pygame.display.set_caption("Rally Racer") |         pygame.display.set_caption("Rally Racer") | ||||||
|         self.running: bool = True |         self.running: bool = True | ||||||
|         self.track: Track = Track.load("simple") |         self.track: Track = Track.load("simple") | ||||||
|         self.car: Car = Car(self.track.start_pos, self.track.start_dir) |         self.car: Car = Car(self, self.track.start_pos, self.track.start_dir) | ||||||
|         self.camera: Camera = Camera() |         self.camera: Camera = Camera() | ||||||
|  |  | ||||||
|         self.clock: pygame.time.Clock = pygame.time.Clock() |         self.clock: pygame.time.Clock = pygame.time.Clock() | ||||||
| @@ -49,6 +50,7 @@ class Game: | |||||||
|             if event.type == pygame.QUIT: |             if event.type == pygame.QUIT: | ||||||
|                 self.quit() |                 self.quit() | ||||||
|             elif event.type == pygame.VIDEORESIZE: |             elif event.type == pygame.VIDEORESIZE: | ||||||
|  |                 self.game_surf = pygame.Surface((event.w, event.h)) | ||||||
|                 self.camera.set_size(Vec(event.w, event.h)) |                 self.camera.set_size(Vec(event.w, event.h)) | ||||||
|             elif event.type == pygame.KEYDOWN: |             elif event.type == pygame.KEYDOWN: | ||||||
|                 if event.key == pygame.K_ESCAPE: |                 if event.key == pygame.K_ESCAPE: | ||||||
| @@ -68,9 +70,10 @@ class Game: | |||||||
|         self.car.controller.close() |         self.car.controller.close() | ||||||
|  |  | ||||||
|     def render(self): |     def render(self): | ||||||
|         self.win.fill(self.BACKGROUND_COLOR) |         self.game_surf.fill(self.BACKGROUND_COLOR) | ||||||
|         self.track.render(self.win, self.camera) |         self.track.render(self.game_surf, self.camera) | ||||||
|         self.car.render(self.win, self.camera, self.show_raycasts) |         self.car.render(self.game_surf, self.camera, self.show_raycasts) | ||||||
|  |         self.win.blit(self.game_surf, (0, 0)) | ||||||
|         if self.show_fps: |         if self.show_fps: | ||||||
|             self.render_fps() |             self.render_fps() | ||||||
|         if self.show_speed: |         if self.show_speed: | ||||||
|   | |||||||
| @@ -17,7 +17,7 @@ from src.snapshot import Snapshot | |||||||
|  |  | ||||||
|  |  | ||||||
| class RecorderClient(QObject): | class RecorderClient(QObject): | ||||||
|     DATA_CHUNK_SIZE = 4096 |     DATA_CHUNK_SIZE = 65536 | ||||||
|     data_received: pyqtSignal = pyqtSignal(Snapshot) |     data_received: pyqtSignal = pyqtSignal(Snapshot) | ||||||
|  |  | ||||||
|     def __init__(self, host: str, port: int) -> None: |     def __init__(self, host: str, port: int) -> None: | ||||||
|   | |||||||
| @@ -12,11 +12,12 @@ from src.utils import RepeatTimer | |||||||
|  |  | ||||||
| if TYPE_CHECKING: | if TYPE_CHECKING: | ||||||
|     from src.car import Car |     from src.car import Car | ||||||
|  |     from src.game import Game | ||||||
|  |  | ||||||
|  |  | ||||||
| class RemoteController: | class RemoteController: | ||||||
|     DEFAULT_PORT = 5000 |     DEFAULT_PORT = 5000 | ||||||
|     DATA_CHUNK_SIZE = 4096 |     DATA_CHUNK_SIZE = 65536 | ||||||
|  |  | ||||||
|     CONTROL_ATTRIBUTES: dict[CarControl, str] = { |     CONTROL_ATTRIBUTES: dict[CarControl, str] = { | ||||||
|         CarControl.FORWARD: "forward", |         CarControl.FORWARD: "forward", | ||||||
| @@ -27,7 +28,8 @@ class RemoteController: | |||||||
|  |  | ||||||
|     SNAPSHOT_INTERVAL = 0.1 |     SNAPSHOT_INTERVAL = 0.1 | ||||||
|  |  | ||||||
|     def __init__(self, car: Car, port: int = DEFAULT_PORT) -> None: |     def __init__(self, game: Game, car: Car, port: int = DEFAULT_PORT) -> None: | ||||||
|  |         self.game: Game = game | ||||||
|         self.car: Car = car |         self.car: Car = car | ||||||
|         self.port: int = port |         self.port: int = port | ||||||
|         self.server: socket.socket = socket.socket( |         self.server: socket.socket = socket.socket( | ||||||
| @@ -134,5 +136,6 @@ class RemoteController: | |||||||
|             return |             return | ||||||
|  |  | ||||||
|         snapshot: Snapshot = Snapshot.from_car(self.car) |         snapshot: Snapshot = Snapshot.from_car(self.car) | ||||||
|  |         snapshot.add_image(self.game) | ||||||
|         payload: bytes = snapshot.pack() |         payload: bytes = snapshot.pack() | ||||||
|         self.client.sendall(struct.pack(">I", len(payload)) + payload) |         self.client.sendall(struct.pack(">I", len(payload)) + payload) | ||||||
|   | |||||||
| @@ -5,11 +5,13 @@ from dataclasses import dataclass, field | |||||||
| from typing import TYPE_CHECKING, Optional | from typing import TYPE_CHECKING, Optional | ||||||
|  |  | ||||||
| import numpy as np | import numpy as np | ||||||
|  | import pygame | ||||||
|  |  | ||||||
| from src.vec import Vec | from src.vec import Vec | ||||||
|  |  | ||||||
| if TYPE_CHECKING: | if TYPE_CHECKING: | ||||||
|     from src.car import Car |     from src.car import Car | ||||||
|  |     from src.game import Game | ||||||
|  |  | ||||||
|  |  | ||||||
| def iter_unpack(format, data): | def iter_unpack(format, data): | ||||||
| @@ -99,3 +101,6 @@ class Snapshot: | |||||||
|         car.pos = self.position.copy() |         car.pos = self.position.copy() | ||||||
|         car.direction = self.direction.copy() |         car.direction = self.direction.copy() | ||||||
|         car.speed = 0 |         car.speed = 0 | ||||||
|  |  | ||||||
|  |     def add_image(self, game: Game): | ||||||
|  |         self.image = pygame.surfarray.array3d(game.game_surf) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user