From ae5b2fc0dfb80a898e56f32c680a46ec6f6c9103 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 15 Jan 2024 07:37:41 +0200 Subject: [PATCH 1/7] chore(game): adjust speed increase --- src/game/screens/tetris.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/game/screens/tetris.py b/src/game/screens/tetris.py index 5764d21..88d0edb 100644 --- a/src/game/screens/tetris.py +++ b/src/game/screens/tetris.py @@ -299,8 +299,8 @@ class Tetris(BaseScreen): def _level_up(self) -> None: """Level up.""" self.level += 1 - self.initial_block_speed *= 0.5 - self.increased_block_speed *= 0.5 + self.initial_block_speed *= 0.3 + self.increased_block_speed *= 0.3 self.timers.vertical.duration = self.initial_block_speed def _draw_components(self) -> None: @@ -365,7 +365,7 @@ class Tetris(BaseScreen): def _initialize_game_state(self) -> None: """Initialize the game state.""" self.initial_block_speed = CONFIG.game.initial_speed - self.increased_block_speed = self.initial_block_speed * 0.4 + self.increased_block_speed = self.initial_block_speed * 0.5 self.down_pressed = False self.drop_pressed = False self.level: int = 1 From b8604f41c333adaeb8ed78d68bc5dff050413f0e Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 15 Jan 2024 09:00:32 +0200 Subject: [PATCH 2/7] feat(game): add `pause` method fix: `pause` --- src/game/screens/tetris.py | 45 ++++++++++++++++++++++++++++++-------- src/game/timer.py | 19 ++++++++++++++-- 2 files changed, 53 insertions(+), 11 deletions(-) diff --git a/src/game/screens/tetris.py b/src/game/screens/tetris.py index 88d0edb..461e375 100644 --- a/src/game/screens/tetris.py +++ b/src/game/screens/tetris.py @@ -97,6 +97,7 @@ class Tetris(BaseScreen): self._handle_rotation_keys(keys) self._handle_down_key(keys) self._handle_drop_key(keys) + self._handle_pause_key(keys) def move_down(self) -> bool: """ @@ -161,6 +162,27 @@ class Tetris(BaseScreen): """ return self.tetromino.drop() + def restart(self) -> None: + """Restart the game.""" + logger.info(f"Restarting the game. Score was {self.score}") + self._reset_game_state() + + def pause(self) -> None: + """Pause the game.""" + self.paused: bool + if self.paused: + logger.debug("Unpause") + self.paused = False + self.timers.unpause() + else: + logger.debug("Pause") + self.paused = True + self.timers.pause() + + def mute(self) -> None: + """Mute the game.""" + self.landing_sound.set_volume(0) + def create_new_tetromino(self, shape: Optional[Figure] = None) -> Optional[Tetromino]: """Create a new tetromino and perform necessary actions.""" self._play_landing_sound() @@ -204,15 +226,6 @@ class Tetris(BaseScreen): return True return False - def restart(self) -> None: - """Restart the game.""" - logger.info(f"Restarting the game. Score was {self.score}") - self._reset_game_state() - - def mute(self) -> None: - """Mute the game.""" - self.landing_sound.set_volume(0) - def _draw_grid(self) -> None: """Draw the grid on the game surface.""" for col in range(1, CONFIG.game.columns): @@ -372,6 +385,7 @@ class Tetris(BaseScreen): self.score: int = 0 self.lines: int = 0 self.game_over = False + self.paused = False def _initialize_sound(self) -> None: """Initialize game sounds.""" @@ -467,6 +481,19 @@ class Tetris(BaseScreen): self.drop() self.timers.drop.activate() + def _handle_pause_key(self, keys: pygame.key.ScancodeWrapper) -> None: + """ + Handle the pause key. + + See `settings.toml` for the default key bindings. + """ + pause_keys = [pygame.key.key_code(key) for key in self.settings["General"]["pause"]] + pause_key_pressed = any(keys[key] for key in pause_keys) + + if pause_key_pressed and not self.timers.horizontal.active: + self.pause() + self.timers.horizontal.activate() + def _reset_game_state(self) -> None: """Reset the game state.""" self.sprites.empty() diff --git a/src/game/timer.py b/src/game/timer.py index 1df5ce1..55fc401 100644 --- a/src/game/timer.py +++ b/src/game/timer.py @@ -1,4 +1,4 @@ -from typing import Any, Callable, NamedTuple, Optional +from typing import Any, Callable, Iterator, Optional import pygame from attrs import define, field @@ -55,7 +55,8 @@ class Timer: self.activate() -class Timers(NamedTuple): +@define +class Timers: """ NamedTuple for grouping different timers. @@ -70,3 +71,17 @@ class Timers(NamedTuple): horizontal: Timer rotation: Timer drop: Timer + + def __iter__(self) -> Iterator[Timer]: + """Returns an iterator over the timers.""" + return iter((self.vertical, self.horizontal, self.rotation, self.drop)) + + def pause(self) -> None: + """Pauses all timers.""" + for timer in self: + timer.deactivate() + + def unpause(self) -> None: + """Unpauses all timers.""" + for timer in self: + timer.activate() From 68452de415c88a2f485e4f74888b42129985b5c1 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 15 Jan 2024 09:17:58 +0200 Subject: [PATCH 3/7] refacor(game): add separate `_get_keys` function --- src/game/screens/tetris.py | 62 ++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/src/game/screens/tetris.py b/src/game/screens/tetris.py index 461e375..53dd353 100644 --- a/src/game/screens/tetris.py +++ b/src/game/screens/tetris.py @@ -91,13 +91,11 @@ class Tetris(BaseScreen): def handle_events(self) -> None: """Handle player input events.""" - keys: pygame.key.ScancodeWrapper = pygame.key.get_pressed() - - self._handle_movement_keys(keys) - self._handle_rotation_keys(keys) - self._handle_down_key(keys) - self._handle_drop_key(keys) - self._handle_pause_key(keys) + self._handle_movement_keys() + self._handle_rotation_keys() + self._handle_down_key() + self._handle_drop_key() + self._handle_pause_key() def move_down(self) -> bool: """ @@ -411,17 +409,17 @@ class Tetris(BaseScreen): """Fill the game surface with background color.""" self.surface.fill(CONFIG.colors.bg_float) - def _handle_movement_keys(self, keys: pygame.key.ScancodeWrapper) -> None: + def _handle_movement_keys(self) -> None: """ Handle movement keys. See `settings.toml` for the default key bindings. """ - right_keys: list[int] = [pygame.key.key_code(key) for key in self.settings["Movement"]["right"]] - right_key_pressed = any(keys[key] for key in right_keys) + right_keys = _get_keys(self.settings["Movement"]["right"]) + right_key_pressed = _is_key_pressed(right_keys) - left_keys: list[int] = [pygame.key.key_code(key) for key in self.settings["Movement"]["left"]] - left_key_pressed = any(keys[key] for key in left_keys) + left_keys = _get_keys(self.settings["Movement"]["left"]) + left_key_pressed = _is_key_pressed(left_keys) if not self.timers.horizontal.active: if left_key_pressed: @@ -431,17 +429,18 @@ class Tetris(BaseScreen): self.move_right() self.timers.horizontal.activate() - def _handle_rotation_keys(self, keys: pygame.key.ScancodeWrapper) -> None: + def _handle_rotation_keys(self) -> None: """ Handle rotation keys. See `settings.toml` for the default key bindings. """ - cw_keys: list[int] = [pygame.key.key_code(key) for key in self.settings["Rotation"]["cw"]] - cw_key_pressed = any(keys[key] for key in cw_keys) - ccw_keys: list[int] = [pygame.key.key_code(key) for key in self.settings["Rotation"]["ccw"]] - ccw_key_pressed = any(keys[key] for key in ccw_keys) + cw_keys = _get_keys(self.settings["Rotation"]["cw"]) + cw_key_pressed = _is_key_pressed(cw_keys) + + ccw_keys = _get_keys(self.settings["Rotation"]["ccw"]) + ccw_key_pressed = _is_key_pressed(ccw_keys) if not self.timers.rotation.active: if cw_key_pressed: @@ -452,14 +451,14 @@ class Tetris(BaseScreen): self.rotate_reverse() self.timers.rotation.activate() - def _handle_down_key(self, keys: pygame.key.ScancodeWrapper) -> None: + def _handle_down_key(self) -> None: """ Handle the down key. See `settings.toml` for the default key bindings. """ - down_keys: list[int] = [pygame.key.key_code(key) for key in self.settings["Movement"]["down"]] - down_key_pressed = any(keys[key] for key in down_keys) + down_keys = _get_keys(self.settings["Movement"]["down"]) + down_key_pressed = _is_key_pressed(down_keys) if not self.down_pressed and down_key_pressed: self.down_pressed = True self.timers.vertical.duration = self.increased_block_speed @@ -468,27 +467,27 @@ class Tetris(BaseScreen): self.down_pressed = False self.timers.vertical.duration = self.initial_block_speed - def _handle_drop_key(self, keys: pygame.key.ScancodeWrapper) -> None: + def _handle_drop_key(self) -> None: """ Handle the drop key. See `settings.toml` for the default key bindings. """ - drop_keys = [pygame.key.key_code(key) for key in self.settings["Action"]["drop"]] - drop_key_pressed = any(keys[key] for key in drop_keys) + drop_keys = _get_keys(self.settings["Action"]["drop"]) + drop_key_pressed = _is_key_pressed(drop_keys) if not self.timers.drop.active and drop_key_pressed: self.drop() self.timers.drop.activate() - def _handle_pause_key(self, keys: pygame.key.ScancodeWrapper) -> None: + def _handle_pause_key(self) -> None: """ Handle the pause key. See `settings.toml` for the default key bindings. """ - pause_keys = [pygame.key.key_code(key) for key in self.settings["General"]["pause"]] - pause_key_pressed = any(keys[key] for key in pause_keys) + pause_keys = _get_keys(self.settings["General"]["pause"]) + pause_key_pressed = _is_key_pressed(pause_keys) if pause_key_pressed and not self.timers.horizontal.active: self.pause() @@ -521,3 +520,14 @@ class Tetris(BaseScreen): (self.grid_surface.get_width(), y), CONFIG.game.line_width, ) + + +def _get_keys(keys: dict[str, str]) -> list[int]: + """Get the key codes for the specified keys.""" + return [pygame.key.key_code(key) for key in keys] + + +def _is_key_pressed(keys: list[int]) -> bool: + """Check if any of the specified keys is pressed.""" + keys_pressed = pygame.key.get_pressed() + return any(keys_pressed[key] for key in keys) From 4eed4a18e98e3cbbe7e6628341362bfd0b460d96 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 15 Jan 2024 22:39:39 +0200 Subject: [PATCH 4/7] refactor(game): pause --- src/game/screens/game.py | 4 ++++ src/game/screens/main.py | 5 ++++- src/game/screens/tetris.py | 42 +++++++++++++------------------------- 3 files changed, 22 insertions(+), 29 deletions(-) diff --git a/src/game/screens/game.py b/src/game/screens/game.py index db11dc0..6ef5d11 100644 --- a/src/game/screens/game.py +++ b/src/game/screens/game.py @@ -64,6 +64,10 @@ class Game(BaseScreen): self.music.set_volume(0) self.tetris.mute() + def pause(self) -> None: + """Pause the game.""" + self.tetris.pause() + def _initialize_game_components(self) -> None: """Initialize game-related components.""" self.clock = pygame.time.Clock() diff --git a/src/game/screens/main.py b/src/game/screens/main.py index 8d38995..de57002 100644 --- a/src/game/screens/main.py +++ b/src/game/screens/main.py @@ -8,6 +8,7 @@ from utils import CONFIG, GameMode, read_settings from .base import BaseScreen, SceenElement, TextScreen from .button import Button from .game import Game +from .tetris import get_keys class Main(BaseScreen, SceenElement, TextScreen): @@ -45,8 +46,10 @@ class Main(BaseScreen, SceenElement, TextScreen): if event.type == pygame.QUIT: self.exit() elif event.type == pygame.KEYDOWN: - if event.key in [pygame.key.key_code(key) for key in self.settings["General"]["quit"]]: + if event.key in get_keys(self.settings["General"]["quit"]): self.exit() + elif event.key in get_keys(self.settings["General"]["pause"]) and self.game: + self.game.pause() if not self.game: for button in self.buttons: diff --git a/src/game/screens/tetris.py b/src/game/screens/tetris.py index 53dd353..2822662 100644 --- a/src/game/screens/tetris.py +++ b/src/game/screens/tetris.py @@ -95,7 +95,6 @@ class Tetris(BaseScreen): self._handle_rotation_keys() self._handle_down_key() self._handle_drop_key() - self._handle_pause_key() def move_down(self) -> bool: """ @@ -415,11 +414,11 @@ class Tetris(BaseScreen): See `settings.toml` for the default key bindings. """ - right_keys = _get_keys(self.settings["Movement"]["right"]) - right_key_pressed = _is_key_pressed(right_keys) + right_keys = get_keys(self.settings["Movement"]["right"]) + right_key_pressed = is_key_pressed(right_keys) - left_keys = _get_keys(self.settings["Movement"]["left"]) - left_key_pressed = _is_key_pressed(left_keys) + left_keys = get_keys(self.settings["Movement"]["left"]) + left_key_pressed = is_key_pressed(left_keys) if not self.timers.horizontal.active: if left_key_pressed: @@ -436,11 +435,11 @@ class Tetris(BaseScreen): See `settings.toml` for the default key bindings. """ - cw_keys = _get_keys(self.settings["Rotation"]["cw"]) - cw_key_pressed = _is_key_pressed(cw_keys) + cw_keys = get_keys(self.settings["Rotation"]["cw"]) + cw_key_pressed = is_key_pressed(cw_keys) - ccw_keys = _get_keys(self.settings["Rotation"]["ccw"]) - ccw_key_pressed = _is_key_pressed(ccw_keys) + ccw_keys = get_keys(self.settings["Rotation"]["ccw"]) + ccw_key_pressed = is_key_pressed(ccw_keys) if not self.timers.rotation.active: if cw_key_pressed: @@ -457,8 +456,8 @@ class Tetris(BaseScreen): See `settings.toml` for the default key bindings. """ - down_keys = _get_keys(self.settings["Movement"]["down"]) - down_key_pressed = _is_key_pressed(down_keys) + down_keys = get_keys(self.settings["Movement"]["down"]) + down_key_pressed = is_key_pressed(down_keys) if not self.down_pressed and down_key_pressed: self.down_pressed = True self.timers.vertical.duration = self.increased_block_speed @@ -473,26 +472,13 @@ class Tetris(BaseScreen): See `settings.toml` for the default key bindings. """ - drop_keys = _get_keys(self.settings["Action"]["drop"]) - drop_key_pressed = _is_key_pressed(drop_keys) + drop_keys = get_keys(self.settings["Action"]["drop"]) + drop_key_pressed = is_key_pressed(drop_keys) if not self.timers.drop.active and drop_key_pressed: self.drop() self.timers.drop.activate() - def _handle_pause_key(self) -> None: - """ - Handle the pause key. - - See `settings.toml` for the default key bindings. - """ - pause_keys = _get_keys(self.settings["General"]["pause"]) - pause_key_pressed = _is_key_pressed(pause_keys) - - if pause_key_pressed and not self.timers.horizontal.active: - self.pause() - self.timers.horizontal.activate() - def _reset_game_state(self) -> None: """Reset the game state.""" self.sprites.empty() @@ -522,12 +508,12 @@ class Tetris(BaseScreen): ) -def _get_keys(keys: dict[str, str]) -> list[int]: +def get_keys(keys: dict[str, str]) -> list[int]: """Get the key codes for the specified keys.""" return [pygame.key.key_code(key) for key in keys] -def _is_key_pressed(keys: list[int]) -> bool: +def is_key_pressed(keys: list[int]) -> bool: """Check if any of the specified keys is pressed.""" keys_pressed = pygame.key.get_pressed() return any(keys_pressed[key] for key in keys) From 36edbacbbc2da229b8f282cf9d702a132ad65d0f Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 15 Jan 2024 22:39:52 +0200 Subject: [PATCH 5/7] chore(game): adjust block speed --- src/game/screens/tetris.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/screens/tetris.py b/src/game/screens/tetris.py index 2822662..9be94b6 100644 --- a/src/game/screens/tetris.py +++ b/src/game/screens/tetris.py @@ -309,8 +309,8 @@ class Tetris(BaseScreen): def _level_up(self) -> None: """Level up.""" self.level += 1 - self.initial_block_speed *= 0.3 - self.increased_block_speed *= 0.3 + self.initial_block_speed *= 0.8 # the larger the multiplier, the slower the game + self.increased_block_speed *= 0.8 self.timers.vertical.duration = self.initial_block_speed def _draw_components(self) -> None: From a136a6ebf71c285b06a5cb4b940d093e86dcfcf7 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Tue, 16 Jan 2024 19:07:25 +0200 Subject: [PATCH 6/7] feat(game): disable movement while paused --- src/game/screens/game.py | 13 ++++++++++++- src/game/screens/tetris.py | 29 ++++++++++++++--------------- src/game/timer.py | 8 ++++---- 3 files changed, 30 insertions(+), 20 deletions(-) diff --git a/src/game/screens/game.py b/src/game/screens/game.py index 6ef5d11..42026f0 100644 --- a/src/game/screens/game.py +++ b/src/game/screens/game.py @@ -1,6 +1,7 @@ from typing import Any import pygame +from loguru import logger from utils import CONFIG, Figure, GameMode from .base import BaseScreen @@ -34,6 +35,7 @@ class Game(BaseScreen): self.settings = settings self._initialize_game_components() self._start_background_music() + self.paused = False def draw(self) -> None: """ @@ -66,7 +68,16 @@ class Game(BaseScreen): def pause(self) -> None: """Pause the game.""" - self.tetris.pause() + 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.""" diff --git a/src/game/screens/tetris.py b/src/game/screens/tetris.py index 9be94b6..b45e8bf 100644 --- a/src/game/screens/tetris.py +++ b/src/game/screens/tetris.py @@ -91,10 +91,11 @@ class Tetris(BaseScreen): def handle_events(self) -> None: """Handle player input events.""" - self._handle_movement_keys() - self._handle_rotation_keys() - self._handle_down_key() - self._handle_drop_key() + if not self.paused: + self._handle_movement_keys() + self._handle_rotation_keys() + self._handle_down_key() + self._handle_drop_key() def move_down(self) -> bool: """ @@ -164,17 +165,15 @@ class Tetris(BaseScreen): logger.info(f"Restarting the game. Score was {self.score}") self._reset_game_state() - def pause(self) -> None: - """Pause the game.""" - self.paused: bool - if self.paused: - logger.debug("Unpause") - self.paused = False - self.timers.unpause() - else: - logger.debug("Pause") - self.paused = True - self.timers.pause() + def freeze(self) -> None: + """Freeze all timers.""" + self.timers.freeze() + self.paused = True + + def unfreeze(self) -> None: + """Unfreeze all timers.""" + self.timers.unfreeze() + self.paused = False def mute(self) -> None: """Mute the game.""" diff --git a/src/game/timer.py b/src/game/timer.py index 55fc401..1d65ad7 100644 --- a/src/game/timer.py +++ b/src/game/timer.py @@ -76,12 +76,12 @@ class Timers: """Returns an iterator over the timers.""" return iter((self.vertical, self.horizontal, self.rotation, self.drop)) - def pause(self) -> None: - """Pauses all timers.""" + def freeze(self) -> None: + """Freezes all timers.""" for timer in self: timer.deactivate() - def unpause(self) -> None: - """Unpauses all timers.""" + def unfreeze(self) -> None: + """Unfreezes all timers.""" for timer in self: timer.activate() From 280c6be84dde4f71477966021df1ecfda4b7f230 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Tue, 16 Jan 2024 19:55:22 +0200 Subject: [PATCH 7/7] feat(game): add pause screen --- src/game/screens/game.py | 46 ++++++++++++++++++++----- src/game/screens/main.py | 7 ++-- src/game/screens/pause.py | 71 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 112 insertions(+), 12 deletions(-) create mode 100644 src/game/screens/pause.py diff --git a/src/game/screens/game.py b/src/game/screens/game.py index 42026f0..1dcd05d 100644 --- a/src/game/screens/game.py +++ b/src/game/screens/game.py @@ -4,13 +4,14 @@ import pygame from loguru import logger from utils import CONFIG, Figure, GameMode -from .base import BaseScreen +from .base import BaseScreen, SceenElement +from .pause import Pause from .preview import Preview from .score import Score from .tetris import Tetris -class Game(BaseScreen): +class Game(BaseScreen, SceenElement): """ Game class. @@ -33,16 +34,16 @@ class Game(BaseScreen): def __init__(self, game_mode: GameMode, settings: dict[str, Any]) -> None: self.game_mode = game_mode self.settings = settings + self._initialize_surface() + self._initialize_rect() self._initialize_game_components() self._start_background_music() self.paused = False def draw(self) -> None: - """ - Raises: - NotImplementedError: Not implemented yet. - """ - raise NotImplementedError + """Draw the score on the score surface.""" + self._update_display_surface() + self._draw_background() def update(self) -> None: """ @@ -53,12 +54,15 @@ class Game(BaseScreen): def run(self) -> None: """Run a single iteration of the game loop.""" - + self.draw() self.tetris.run() self.score.run() self.preview.update(self.next_figure) self.preview.run() + if self.paused: + self.pause_screen.draw() + self.clock.tick(CONFIG.game.fps) def mute(self) -> None: @@ -87,6 +91,7 @@ class Game(BaseScreen): self.tetris = Tetris(self._get_next_figure, self._update_score, self.game_mode, self.settings) self.score = Score(self.game_mode) self.preview = Preview() + self.pause_screen = Pause() def _update_score(self, lines: int, score: int, level: int) -> None: """ @@ -125,3 +130,28 @@ class Game(BaseScreen): self.music = pygame.mixer.Sound(CONFIG.music.background) self.music.set_volume(self.settings["Volume"]["Music"]["level"]) self.music.play(-1) + + def _initialize_surface(self) -> None: + """Initialize the pause screen surface.""" + self.surface = pygame.Surface(CONFIG.window.size) + self.display_surface = pygame.display.get_surface() + + def _initialize_rect(self) -> None: + """Initialize the score rectangle.""" + self.rect = self.surface.get_rect(topleft=(0, 0)) + + def _draw_background(self) -> None: + """Draw the background.""" + self.surface.fill(CONFIG.colors.bg) + + def _update_display_surface(self) -> None: + """Update the display surface.""" + self.display_surface.blit(self.surface, self.rect) + + def _draw_border(self) -> None: + """Draw the border. + + Raises: + NotImplementedError: Not implemented yet. + """ + raise NotImplementedError diff --git a/src/game/screens/main.py b/src/game/screens/main.py index de57002..e6f0e0e 100644 --- a/src/game/screens/main.py +++ b/src/game/screens/main.py @@ -63,14 +63,13 @@ class Main(BaseScreen, SceenElement, TextScreen): def run_game_loop(self) -> None: """Run a single iteration of the game loop.""" - if not self.game: + if self.game: + self.game.run() + else: self.draw() self.handle_events() - if self.game: - self.game.run() - self.update() def exit(self) -> None: diff --git a/src/game/screens/pause.py b/src/game/screens/pause.py new file mode 100644 index 0000000..1bb3f34 --- /dev/null +++ b/src/game/screens/pause.py @@ -0,0 +1,71 @@ +import pygame +from utils import CONFIG + +from .base import BaseScreen, SceenElement, TextScreen + + +class Pause(BaseScreen, SceenElement, TextScreen): + def __init__(self) -> None: + self._initialize_surface() + self._initialize_rect() + self._initialize_font() + + def run(self) -> None: + """ + Raises: + NotImplementedError: Not implemented yet. + """ + raise NotImplementedError + + def update(self) -> None: + self._update_display_surface() + + def draw(self) -> None: + """Update the display.""" + self.update() + self._draw_background() + self._draw_text() + + def _draw_text(self) -> None: + """Draw the text.""" + self._display_text("Paused") + + def _display_text(self, text: str) -> None: + """Display the text.""" + text_surface = self.font.render(text, True, CONFIG.colors.fg_float) + text_rect = text_surface.get_rect(center=self.rect.center) + self.text_surface.blit(text_surface, text_rect) + + def _draw_background(self) -> None: + """Draw the background.""" + self.surface.fill(CONFIG.colors.bg_float) + self.surface.set_alpha(100) + self.text_surface.set_colorkey("#000000") + self.text_surface.set_alpha(255) + + def _initialize_surface(self) -> None: + """Initialize the pause screen surface.""" + self.surface = pygame.Surface(CONFIG.window.size) + self.display_surface = pygame.display.get_surface() + self.text_surface = pygame.Surface(CONFIG.window.size) + + def _initialize_rect(self) -> None: + """Initialize the score rectangle.""" + self.rect = self.surface.get_rect(topleft=(0, 0)) + + def _initialize_font(self) -> None: + """Initialize the font used to display the text.""" + self.font = pygame.font.Font(CONFIG.font.family, CONFIG.font.size * 2) + + def _update_display_surface(self) -> None: + """Update the display surface.""" + self.display_surface.blit(self.surface, self.rect) + self.display_surface.blit(self.text_surface, self.rect) + + def _draw_border(self) -> None: + """Draw the border. + + Raises: + NotImplementedError: Not implemented yet. + """ + raise NotImplementedError