/
sibiskus
/
Drive_Studio
Обзор
Документация
Войти
/
sibiskus
/
Drive_Studio
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
controller/game_controller.py
304 строки
11 KB
Snezha
ещё раз прошлась по всем файлам, где-то дописала вот эти мини документации, чтобы быстрее ориентироваться по проекту
23 июн 2026, 03:06
23 июн 2026, 03:06
12ea40b
Код
Авторство
О чём код?
import pygame import config from models.car import Car from models.road import Road from utils.sound_manager import SoundManager from controller.spawn_manager import SpawnManager from controller.collision_manager import CollisionManager class GameController: def __init__(self, player: Car, road: Road): self.player = player self.road = road self.running = True self.obstacles = [] self.coins = [] self.fuels = [] self.spawn_timer = 0 self.coin_timer = 0 self.coin_score = 0 self.current_level = 1 self.elapsed_time = 0.0 self.fuel_spawns_triggered = { "2_3": False, "1_3": False, "low": False } self.load_level(self.current_level) self.game_state = "START_MENU" # LEVEL_INTRO, PLAYING, WIN, GAME_COMPLETE, LOSE_CRASH, LOSE_FUEL, LOSE_TIME self.spawn_manager = SpawnManager(self.road) self.collision_manager = CollisionManager(cell_size=100) self.sound_manager = SoundManager() def load_level(self, level_num): """Загружает параметры выбранного уровня + сброс параметров""" if level_num in config.LEVELS: level_data = config.LEVELS[level_num] self.target_time = level_data["target_time"] self.target_coins = level_data["target_coins"] self.elapsed_time = 0.0 self.coin_score = 0 self.spawn_timer = 0 self.coin_timer = 0 self.obstacles.clear() self.coins.clear() self.fuels.clear() self.fuel_spawns_triggered = {"2_3": False, "1_3": False, "low": False} self.player.current_fuel = self.player.max_fuel self.player.is_alive = True self.game_state = "LEVEL_INTRO" self.player.x = config.PLAYER_START_X - (config.PLAYER_WIDTH // 2) self.player.y = config.PLAYER_START_Y def is_night_level(self): """Проверяет, включен ли ночной режим на текущем уровне""" return config.LEVELS[self.current_level].get("night", False) def handle_input(self, dt: float): """Обрабатывает клавиатуру, мышь и закрытие окна""" for event in pygame.event.get(): if event.type == pygame.QUIT: self.running = False elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: self.running = False elif event.key == pygame.K_n: self.current_level = max(config.LEVELS) self.load_level(self.current_level) self.game_state = "PLAYING" elif event.type == pygame.MOUSEBUTTONDOWN: if event.button == 1: self.handle_mouse_click(event.pos) if self.game_state == "PLAYING": self.handle_continuous_movement(dt) def update(self, dt: float): """Обновляет таймеры, объекты, столкновения и состояние уровня""" if self.game_state != "PLAYING": return if not self.player.is_alive and self.player.current_fuel == 0: self.game_state = "LOSE_FUEL" self.sound_manager.play('lose') return self.elapsed_time += dt if self.elapsed_time >= self.target_time: self.game_state = "LOSE_TIME" self.sound_manager.play('lose') return self.player.update(dt) self.update_spawn_timers(dt) self.update_road_objects(dt) self.handle_fuel_spawns() self.collision_manager.rebuild_grid(self.obstacles, self.coins, self.fuels) collision_result = self.collision_manager.check_collisions( self.player, self.obstacles, self.coins, self.fuels ) self.apply_collision_result(collision_result) if self.game_state != "PLAYING": return if self.check_level_complete(): return def update_spawn_timers(self, dt): """Обновляет таймеры появления препятствий и монет""" self.spawn_timer += dt * 1000 if self.spawn_timer >= config.SPAWN_INTERVAL: self.spawn_manager.spawn_obstacle(self.obstacles, self.coins, self.fuels) self.spawn_timer = 0 self.coin_timer += dt * 1000 if self.coin_timer >= config.COIN_SPAWN_INTERVAL: self.spawn_manager.spawn_coin(self.obstacles, self.coins, self.fuels) self.coin_timer = 0 def update_road_objects(self, dt): """Обновляет объекты на дороге и удаляет ушедшие за экран""" road_objects = self.obstacles + self.coins + self.fuels for obstacle in self.obstacles: obstacle.update(dt, road_instance=self.road, all_obstacles=road_objects) self.obstacles = [obs for obs in self.obstacles if not obs.is_off_screen()] self.coins = self.update_moving_objects(self.coins, dt) self.fuels = self.update_moving_objects(self.fuels, dt) def handle_fuel_spawns(self): """Создает канистры топлива при достижении заданных порогов бензина""" fuel_pct = self.player.current_fuel / self.player.max_fuel thresholds = config.FUEL_SPAWN_THRESHOLDS if fuel_pct <= thresholds["2_3"] and not self.fuel_spawns_triggered["2_3"]: self.spawn_manager.spawn_fuel(self.obstacles, self.coins, self.fuels) self.fuel_spawns_triggered["2_3"] = True if fuel_pct <= thresholds["1_3"] and not self.fuel_spawns_triggered["1_3"]: self.spawn_manager.spawn_fuel(self.obstacles, self.coins, self.fuels) self.fuel_spawns_triggered["1_3"] = True if fuel_pct <= thresholds["low"] and not self.fuel_spawns_triggered["low"]: self.spawn_manager.spawn_fuel(self.obstacles, self.coins, self.fuels) self.fuel_spawns_triggered["low"] = True if fuel_pct > thresholds["2_3"]: self.fuel_spawns_triggered["2_3"] = False if fuel_pct > thresholds["1_3"]: self.fuel_spawns_triggered["1_3"] = False if fuel_pct > thresholds["low"]: self.fuel_spawns_triggered["low"] = False def check_level_complete(self): """Проверяет, выполнено ли условие прохождения уровня""" if self.coin_score >= self.target_coins: next_level = self.current_level + 1 if next_level in config.LEVELS: self.game_state = "WIN" else: self.game_state = "GAME_COMPLETE" self.sound_manager.play('win') return True return False def apply_collision_result(self, result): """Применяет результат столкновений к счету, состоянию игры и звукам""" if result["crashed"]: self.game_state = "LOSE_CRASH" self.sound_manager.play("lose") return self.coin_score += result["coins_collected"] for event in result.get("events", []): if event == "coin": self.sound_manager.play("coin") elif event == "fuel": self.sound_manager.play("fuel") def update_moving_objects(self, objects, dt): """Обновляет движущиеся объекты и оставляет только видимые на экране""" for obj in objects: obj.update(dt) return [obj for obj in objects if not obj.is_off_screen()] def handle_continuous_movement(self, dt: float): """Проверяет, удерживаются ли клавиши прямо сейчас, и двигает машину""" keys = pygame.key.get_pressed() direction = 0 if keys[pygame.K_LEFT]: direction = -1 elif keys[pygame.K_RIGHT]: direction = 1 borders = self.road.get_borders() self.player.move(direction, dt, borders) def handle_mouse_click(self, pos): """Обрабатывает клики по кнопкам в разных состояниях игры""" if self.game_state == "PLAYING": pause_button_rect = pygame.Rect( config.PAUSE_BUTTON_X, config.PAUSE_BUTTON_Y, config.PAUSE_BUTTON_SIZE, config.PAUSE_BUTTON_SIZE ) if pause_button_rect.collidepoint(pos): self.game_state = "PAUSED" return if self.game_state == "PAUSED": sound_toggle_rect = pygame.Rect( config.PAUSE_SOUND_TOGGLE_X, config.PAUSE_SOUND_TOGGLE_Y, config.PAUSE_SOUND_TOGGLE_WIDTH, config.PAUSE_SOUND_TOGGLE_HEIGHT ) continue_button_rect = pygame.Rect( config.PAUSE_CONTINUE_BUTTON_X, config.PAUSE_CONTINUE_BUTTON_Y, config.PAUSE_CONTINUE_BUTTON_WIDTH, config.PAUSE_CONTINUE_BUTTON_HEIGHT ) if sound_toggle_rect.collidepoint(pos): self.sound_manager.toggle() return if continue_button_rect.collidepoint(pos): self.game_state = "PLAYING" return return if self.game_state == "START_MENU": sound_toggle_rect = pygame.Rect( config.SOUND_TOGGLE_X, config.SOUND_TOGGLE_Y, config.SOUND_TOGGLE_WIDTH, config.SOUND_TOGGLE_HEIGHT ) start_button_rect = pygame.Rect( config.START_BUTTON_X, config.START_BUTTON_Y, config.START_BUTTON_WIDTH, config.START_BUTTON_HEIGHT ) if sound_toggle_rect.collidepoint(pos): self.sound_manager.toggle() return if start_button_rect.collidepoint(pos): self.game_state = "LEVEL_INTRO" return return button_rect = pygame.Rect( config.BUTTON_X, config.BUTTON_Y, config.BUTTON_WIDTH, config.BUTTON_HEIGHT ) if button_rect.collidepoint(pos): self.sound_manager.stop_all() if self.game_state == "LEVEL_INTRO": self.game_state = "PLAYING" elif self.game_state == "WIN": self.current_level += 1 self.load_level(self.current_level) elif self.game_state == "GAME_COMPLETE": self.current_level = 1 self.load_level(self.current_level) elif self.game_state in ["LOSE_CRASH", "LOSE_FUEL", "LOSE_TIME"]: self.load_level(self.current_level)