diff --git a/src/py2048/objects/abc/movable_ui_element.py b/src/py2048/objects/abc/movable_ui_element.py index 413a6fe..f8f6f23 100644 --- a/src/py2048/objects/abc/movable_ui_element.py +++ b/src/py2048/objects/abc/movable_ui_element.py @@ -1,4 +1,5 @@ from abc import abstractmethod +from typing import Any import pygame @@ -12,7 +13,7 @@ class MovableUIElement(UIElement): UIElement.__init__(self, *args, **kwargs) @abstractmethod - def move(self, direction: Direction) -> None: + def move(self, direction: Direction) -> Any: """Move the element in the given direction.""" @property diff --git a/src/py2048/objects/board.py b/src/py2048/objects/board.py index 2b7b7ea..004d549 100644 --- a/src/py2048/objects/board.py +++ b/src/py2048/objects/board.py @@ -15,16 +15,15 @@ class Board(pygame.sprite.Group): self.rect = pygame.Rect(0, 0, *Config.BOARD.size) self.score: int = 0 self.rect.x, self.rect.y = Config.BOARD.pos - self.initiate_game() + self._initiate_game() - def initiate_game(self) -> None: + def _initiate_game(self) -> None: """Initiate the game.""" self.generate_initial_tiles() def draw(self, surface: pygame.Surface) -> None: """Draw the board.""" self._draw_background(surface) - super().draw(surface) def _draw_background(self, surface: pygame.Surface) -> None: @@ -45,7 +44,6 @@ class Board(pygame.sprite.Group): def move(self, direction: Direction) -> None: """Move the tiles in the specified direction.""" - score = 0 tiles = self.sprites() tile: Tile @@ -60,8 +58,7 @@ class Board(pygame.sprite.Group): tiles.sort(key=lambda tile: tile.rect.x, reverse=True) for tile in tiles: - tile.move(direction) - self.score += tile.value + self.score += tile.move(direction) if not self._is_full(): self.generate_random_tile() @@ -116,4 +113,4 @@ class Board(pygame.sprite.Group): def reset(self) -> None: """Reset the board.""" self.empty() - self.initiate_game() + self._initiate_game() diff --git a/src/py2048/objects/tile.py b/src/py2048/objects/tile.py index 2ef9664..30feb94 100644 --- a/src/py2048/objects/tile.py +++ b/src/py2048/objects/tile.py @@ -33,7 +33,6 @@ class Tile(MovableUIElement, pygame.sprite.Sprite): border_radius=Config.TILE.border.radius, border_width=Config.TILE.border.width, ) - self.score: int = 0 self.group = group self.image = self._create_surface() @@ -88,33 +87,29 @@ class Tile(MovableUIElement, pygame.sprite.Sprite): self._draw_background(surface) return surface - def move(self, direction: Direction) -> None: + def move(self, direction: Direction) -> int: """ Move the tile by `dx` and `dy`. If the tile collides with another tile, it will merge with it if possible. - Before moving, reset the score of the tile. """ + score = 0 while True: new_x, new_y = self._calc_new_pos(direction) if self._is_out_if_bounds(new_x, new_y): - return + return score if self._has_collision(new_x, new_y): collided_tile = self._get_collided_tile(new_x, new_y) if collided_tile and self._can_merge(collided_tile): - self._merge(collided_tile) + score += self._merge(collided_tile) else: - return + return score self.group.remove(self) self.rect.topleft = new_x, new_y self.group.add(self) - def get_score(self) -> int: - """Return the score of the tile.""" - return self.score - def _calc_new_pos(self, direction: Direction) -> tuple[int, int]: """Calculate the new position of the tile.""" dx, dy = direction * Config.TILE.size @@ -148,13 +143,14 @@ class Tile(MovableUIElement, pygame.sprite.Sprite): """Check if the tile can merge with another tile.""" return self.value == other.value - def _merge(self, other: "Tile") -> None: + def _merge(self, other: "Tile") -> int: """Merge the tile with another tile.""" self.group.remove(other) self.group.remove(self) self.value += other.value self.update() self.group.add(self) + return self.value def can_move(self) -> bool: """Check if the tile can move""" diff --git a/src/py2048/screens/game.py b/src/py2048/screens/game.py index 21fde46..bc309e9 100644 --- a/src/py2048/screens/game.py +++ b/src/py2048/screens/game.py @@ -30,14 +30,18 @@ class Game: elif event.key in (pygame.K_DOWN, pygame.K_s, pygame.K_j): self.move_down() + def move(self, direction: Direction) -> None: + self.board.move(direction) + self.header.update(self.board.score) + def move_up(self) -> None: - self.board.move(Direction.UP) + self.move(Direction.UP) def move_down(self) -> None: - self.board.move(Direction.DOWN) + self.move(Direction.DOWN) def move_left(self) -> None: - self.board.move(Direction.LEFT) + self.move(Direction.LEFT) def move_right(self) -> None: - self.board.move(Direction.RIGHT) + self.move(Direction.RIGHT) diff --git a/src/py2048/screens/header.py b/src/py2048/screens/header.py index 432148a..22c6b42 100644 --- a/src/py2048/screens/header.py +++ b/src/py2048/screens/header.py @@ -13,7 +13,7 @@ class Header: def _create_labels(self) -> pygame.sprite.Group: size = Size(60, 40) - score = ScoreLabel( + self.score = ScoreLabel( value=0, text="Score", size=size, @@ -39,14 +39,12 @@ class Header: border_radius=2, ) - return pygame.sprite.Group(score, highscore) + return pygame.sprite.Group(self.score, highscore) def draw(self, surface: pygame.Surface) -> None: """Draw the header.""" self.labels.draw(surface) def update(self, score: int) -> None: - """Update the header.""" - for label in self.labels: - if label.text == "SCORE": - label.update_score(score) + """Update the score.""" + self.score.update_score(score)