from typing import Any import pygame from loguru import logger from utils import CONFIG, Figure, GameMode from .base import BaseScreen from .preview import Preview from .score import Score from .tetris import Tetris class Game(BaseScreen): """ Game class. Args: mode: The game mode to start with. Attributes: game_mode: The game mode. settings: The game settings. display_surface: Pygame display surface. clock: Pygame clock. music: Pygame music. game: Game object. score: Score object. preview: Preview object. next_figure: List of upcoming figures. music: Music that plays in the background. """ def __init__(self, game_mode: GameMode, settings: dict[str, Any]) -> None: self.game_mode = game_mode self.settings = settings self._initialize_game_components() self._start_background_music() self.paused = False def draw(self) -> None: """ Raises: NotImplementedError: Not implemented yet. """ raise NotImplementedError def update(self) -> None: """ Raises: NotImplementedError: Not implemented yet. """ raise NotImplementedError def run(self) -> None: """Run a single iteration of the game loop.""" self.tetris.run() self.score.run() self.preview.update(self.next_figure) self.preview.run() self.clock.tick(CONFIG.game.fps) def mute(self) -> None: """Mute the game.""" self.music.set_volume(0) self.tetris.mute() def pause(self) -> None: """Pause the game.""" if self.paused: logger.debug("Unpause") self.paused = False self.tetris.unfreeze() self.music.play(-1, fade_ms=100) else: logger.debug("Pause") self.paused = True self.tetris.freeze() self.music.fadeout(100) def _initialize_game_components(self) -> None: """Initialize game-related components.""" self.clock = pygame.time.Clock() self.next_figure: Figure = self._generate_next_figure() self.tetris = Tetris(self._get_next_figure, self._update_score, self.game_mode, self.settings) self.score = Score(self.game_mode) self.preview = Preview() def _update_score(self, lines: int, score: int, level: int) -> None: """ Update the game score. Args: lines: Number of lines cleared. score: Current score. level: Current game level. """ self.score.update(lines, score, level) def _generate_next_figure(self) -> Figure: """ Generate the next set of random figures. Returns: Randomly generated figure. """ return Figure.random() def _get_next_figure(self) -> Figure: """ Get the next figure in the sequence. Returns: The next figure in the sequence. """ next_figure: Figure = self.next_figure self.next_figure = self._generate_next_figure() return next_figure def _start_background_music(self) -> None: """Start playing background music.""" if self.game_mode is GameMode.PLAYER and self.settings["Volume"]["Music"]["enabled"]: self.music = pygame.mixer.Sound(CONFIG.music.background) self.music.set_volume(self.settings["Volume"]["Music"]["level"]) self.music.play(-1)