mirror of
https://github.com/kristoferssolo/Tetris.git
synced 2025-10-21 20:00:35 +00:00
refactor(game): remove Field enum
This commit is contained in:
parent
786ecb3536
commit
40b6556c97
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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()
|
||||||
|
|||||||
@ -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()
|
||||||
|
|||||||
@ -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):
|
||||||
|
|||||||
@ -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."""
|
||||||
|
|||||||
@ -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.
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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",
|
||||||
]
|
]
|
||||||
|
|||||||
@ -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()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user