refactor(game): remove Field enum

This commit is contained in:
Kristofers Solo 2024-01-06 16:45:30 +02:00
parent 786ecb3536
commit 40b6556c97
10 changed files with 46 additions and 34 deletions

View File

@ -31,7 +31,7 @@ class SceenElement(ABC, metaclass=ABCMeta):
"""Initialize the surface.""" """Initialize the surface."""
@abstractmethod @abstractmethod
def _initialize_rect(self) -> None: def _initialize_rect(self, *args, **kwargs) -> None:
"""Initialize the rectangle.""" """Initialize the rectangle."""
@abstractmethod @abstractmethod

View File

@ -1,5 +1,5 @@
from abc import ABC, ABCMeta, abstractmethod from abc import ABC, ABCMeta, abstractmethod
from typing import Callable, Optional from typing import Any, Callable, Optional
import pygame import pygame
@ -7,7 +7,9 @@ import pygame
class BaseButton(ABC, metaclass=ABCMeta): class BaseButton(ABC, metaclass=ABCMeta):
"""Base button class.""" """Base button class."""
def __init__(self, text: str, action: Optional[Callable[[], None]]) -> None: def __init__(
self, text: str, action: Optional[Callable[[], Optional[Any]]]
) -> None:
self.action = action self.action = action
self.text = text self.text = text

View File

@ -1,4 +1,4 @@
from typing import Callable, Optional from typing import Any, Callable, Optional
import pygame import pygame
from utils import CONFIG from utils import CONFIG
@ -8,7 +8,9 @@ from .base_button import BaseButton
class Button(BaseButton, BaseScreen, SceenElement, TextScreen): class Button(BaseButton, BaseScreen, SceenElement, TextScreen):
def __init__(self, text: str, action: Optional[Callable[[], None]]) -> None: def __init__(
self, text: str, action: Optional[Callable[[], Optional[Any]]]
) -> None:
super().__init__(text, action) super().__init__(text, action)
self._initialize_surface() self._initialize_surface()
self._initialize_font() self._initialize_font()

View File

@ -27,9 +27,10 @@ class Game(BaseScreen):
music: Pygame music that plays in the background. music: Pygame music that plays in the background.
""" """
def __init__(self) -> None: def __init__(self, game_mode: GameMode) -> None:
self._initialize_game_components() self._initialize_game_components()
self._start_background_music() self._start_background_music()
self.game_mode = game_mode # TODO: use this
def draw(self) -> None: def draw(self) -> None:
"""Update the display.""" """Update the display."""
@ -40,7 +41,6 @@ class Game(BaseScreen):
def run(self) -> None: def run(self) -> None:
"""Run a single iteration of the game loop.""" """Run a single iteration of the game loop."""
self.draw() self.draw()
self.handle_events() # FIX:
self.tetris.run() self.tetris.run()
self.score.run() self.score.run()

View File

@ -1,4 +1,5 @@
import sys import sys
from typing import Optional
import pygame import pygame
from utils import CONFIG, GameMode from utils import CONFIG, GameMode
@ -19,16 +20,16 @@ class Main(BaseScreen, SceenElement, TextScreen):
self._initialize_font() self._initialize_font()
self._set_buttons() self._set_buttons()
self._initialize_increment_height() self._initialize_increment_height()
self.game_mode = mode # TODO: use this self.game_mode = mode
self.game: Optional[Game] = None
def draw(self) -> None: def draw(self) -> None:
"""Update the display.""" """Update the display."""
self._draw_background() self._draw_background()
self._draw_text() self._draw_text()
pygame.display.update()
def update(self) -> None: def update(self) -> None:
pass pygame.display.update()
def handle_events(self) -> None: def handle_events(self) -> None:
for event in pygame.event.get(): for event in pygame.event.get():
@ -48,17 +49,25 @@ class Main(BaseScreen, SceenElement, TextScreen):
def run(self) -> None: def run(self) -> None:
while True: while True:
self.draw() if not self.game:
self.draw()
self.handle_events() self.handle_events()
if self.game:
self.game.run()
self.update()
def exit(self) -> None: def exit(self) -> None:
"""Exit the game.""" """Exit the game."""
log.info("Exiting the game") log.info("Exiting the game")
pygame.quit() pygame.quit()
sys.exit() sys.exit()
def play(self) -> None: def play(self) -> "Main":
pass self.game = Game(self.game_mode)
return self
def _set_buttons(self) -> None: def _set_buttons(self) -> None:
self.buttons: list[Button] = [ self.buttons: list[Button] = [
@ -91,7 +100,7 @@ class Main(BaseScreen, SceenElement, TextScreen):
def _initialize_increment_height(self) -> None: def _initialize_increment_height(self) -> None:
"""Initialize the increment height for positioning text elements/buttons.""" """Initialize the increment height for positioning text elements/buttons."""
self.increment_height = ( self.increment_height: float = (
self.display_surface.get_height() - CONFIG.window.size.height / 2 self.display_surface.get_height() - CONFIG.window.size.height / 2
) / len(self.buttons) ) / len(self.buttons)
@ -114,7 +123,8 @@ class Main(BaseScreen, SceenElement, TextScreen):
def _draw_text(self) -> None: def _draw_text(self) -> None:
"""Draw the text and buttons on the surface.""" """Draw the text and buttons on the surface."""
x, y = self.display_surface.get_width() / 2, 100 x: float = self.display_surface.get_width() / 2
y: float = 100
self._display_text("Tetris", (x, y)) self._display_text("Tetris", (x, y))
for idx, button in enumerate(self.buttons): for idx, button in enumerate(self.buttons):

View File

@ -2,7 +2,7 @@ from typing import Any, Callable, Optional
import numpy as np import numpy as np
import pygame import pygame
from utils import CONFIG, Direction, Field, Figure, Rotation from utils import CONFIG, Direction, Figure, Rotation
from game.log import log from game.log import log
from game.sprites.block import Block from game.sprites.block import Block
@ -47,6 +47,7 @@ class Tetris(BaseScreen):
update_score: Callable[[int, int, int], None], update_score: Callable[[int, int, int], None],
) -> None: ) -> None:
self._initialize_surface() self._initialize_surface()
self._initialize_rect()
self._initialize_sprites() self._initialize_sprites()
self.get_next_figure = get_next_figure self.get_next_figure = get_next_figure
@ -201,7 +202,8 @@ class Tetris(BaseScreen):
def _remove_blocks_in_row(self, row: int) -> None: def _remove_blocks_in_row(self, row: int) -> None:
"""Remove blocks in the specified row.""" """Remove blocks in the specified row."""
for block in self.field[row]: for block in self.field[row]:
block.kill() if block:
block.kill()
def _move_rows_down(self, deleted_row: int) -> None: def _move_rows_down(self, deleted_row: int) -> None:
"""Move rows down after deleting a row.""" """Move rows down after deleting a row."""
@ -217,11 +219,9 @@ class Tetris(BaseScreen):
for block in self.sprites: for block in self.sprites:
self.field[int(block.pos.y), int(block.pos.x)] = block self.field[int(block.pos.y), int(block.pos.x)] = block
def _generate_empty_field(self) -> np.ndarray[Field, Any]: def _generate_empty_field(self) -> np.ndarray[Optional[Block], Any]:
"""Generate an empty game field.""" """Generate an empty game field."""
return np.full( return np.full((CONFIG.game.rows, CONFIG.game.columns), None)
(CONFIG.game.rows, CONFIG.game.columns), Field.EMPTY, dtype=Field
)
def _calculate_score(self, rows_deleted: int) -> None: def _calculate_score(self, rows_deleted: int) -> None:
"""Calculate and update the game score.""" """Calculate and update the game score."""

View File

@ -1,8 +1,8 @@
from typing import Any from typing import Any, Optional
import numpy as np import numpy as np
import pygame import pygame
from utils import CONFIG, Field, Rotation, Size from utils import CONFIG, Rotation, Size
class Block(pygame.sprite.Sprite): class Block(pygame.sprite.Sprite):
@ -40,7 +40,9 @@ class Block(pygame.sprite.Sprite):
self.pos.y * CONFIG.game.cell.width, self.pos.y * CONFIG.game.cell.width,
) )
def vertical_collision(self, x: int, field: np.ndarray[Field, Any]) -> bool: def vertical_collision(
self, x: int, field: np.ndarray[Optional["Block"], Any]
) -> bool:
""" """
Checks for vertical collision with the game field. Checks for vertical collision with the game field.
@ -53,7 +55,9 @@ class Block(pygame.sprite.Sprite):
""" """
return not 0 <= x < CONFIG.game.columns or field[int(self.pos.y), x] return not 0 <= x < CONFIG.game.columns or field[int(self.pos.y), x]
def horizontal_collision(self, y: int, field: np.ndarray[Field, Any]) -> bool: def horizontal_collision(
self, y: int, field: np.ndarray[Optional["Block"], Any]
) -> bool:
""" """
Checks for horizontal collision with the game field. Checks for horizontal collision with the game field.

View File

@ -2,7 +2,7 @@ from typing import Any, Callable, Optional
import numpy as np import numpy as np
import pygame import pygame
from utils import CONFIG, Direction, Field, Figure, Rotation, Size from utils import CONFIG, Direction, Figure, Rotation, Size
from game.log import log from game.log import log
@ -32,7 +32,7 @@ class Tetromino:
self, self,
group: pygame.sprite.Group, group: pygame.sprite.Group,
create_new: Callable[[], None], create_new: Callable[[], None],
field: np.ndarray[Field, Any], field: np.ndarray[Optional[Block], Any],
shape: Optional[Figure] = None, shape: Optional[Figure] = None,
) -> None: ) -> None:
self.figure: Figure = self._generate_figure(shape) self.figure: Figure = self._generate_figure(shape)

View File

@ -1,5 +1,5 @@
from .config import CONFIG from .config import CONFIG
from .enum import Direction, Field, GameMode, Rotation from .enum import Direction, GameMode, Rotation
from .figure import Figure, FigureConfig from .figure import Figure, FigureConfig
from .log import log from .log import log
from .path import BASE_PATH from .path import BASE_PATH
@ -13,7 +13,6 @@ __all__ = [
"Figure", "Figure",
"FigureConfig", "FigureConfig",
"Direction", "Direction",
"Field",
"Rotation", "Rotation",
"GameMode", "GameMode",
] ]

View File

@ -13,11 +13,6 @@ class Rotation(Enum):
COUNTER_CLOCKWISE = -90 COUNTER_CLOCKWISE = -90
class Field(Enum):
EMPTY = None
FILLED = "Block"
class GameMode(Enum): class GameMode(Enum):
PLAYER = auto() PLAYER = auto()
AI_PLAYING = auto() AI_PLAYING = auto()