From 50145ae6a65b0c2ab315477a1e05a650e815bd01 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Thu, 28 Dec 2023 16:47:59 +0200 Subject: [PATCH] feat(game): add "dunder" methods for `Block` --- src/py2048/block.py | 75 +++++++++++++++++++++++++++++---------------- 1 file changed, 48 insertions(+), 27 deletions(-) diff --git a/src/py2048/block.py b/src/py2048/block.py index 3d24324..354228a 100644 --- a/src/py2048/block.py +++ b/src/py2048/block.py @@ -8,21 +8,23 @@ from .config import Config class Block(pygame.sprite.Sprite): def __init__(self, x: int, y: int): + """Initialize a block""" super().__init__() self.image = pygame.Surface((Config.BLOCK_SIZE, Config.BLOCK_SIZE)) - self.image.fill(COLORS.ERROR) self.rect = self.image.get_rect() self.rect.topleft = (x, y) self.value: int = 2 if random.random() <= Config.BLOCK_VALUE_PROBABILITY else 4 - self.draw_value() + self.font = pygame.font.SysFont(Config.FONT_FAMILY, Config.FONT_SIZE) + self.update() def draw_value(self) -> None: - font = pygame.font.SysFont(Config.FONT_FAMILY, Config.FONT_SIZE) - text = font.render(str(self.value), True, COLORS.FG) + """Draw the value of the block""" + text = self.font.render(str(self.value), True, COLORS.FG) text_rect = text.get_rect(center=self.image.get_rect().center) self.image.blit(text, text_rect) def move(self, dx: int, dy: int) -> None: + """Move the block by `dx` and `dy`""" new_x = self.rect.x + dx new_y = self.rect.y + dy if 0 <= new_x <= Config.WIDTH - Config.BLOCK_SIZE and 0 <= new_y <= Config.HEIGHT - Config.BLOCK_SIZE: @@ -35,30 +37,49 @@ class Block(pygame.sprite.Sprite): self.update() def update(self) -> None: + """Update the block""" self.change_color() self.draw_value() def change_color(self) -> None: - match self.value: - case 2: - self.image.fill(COLORS.BLUE) - case 4: - self.image.fill(COLORS.BLUE0) - case 8: - self.image.fill(COLORS.BLUE1) - case 16: - self.image.fill(COLORS.BLUE2) - case 32: - self.image.fill(COLORS.DARK3) - case 64: - self.image.fill(COLORS.BORDER_HIGHLIGHT) - case 128: - self.image.fill(COLORS.BLUE5) - case 256: - self.image.fill(COLORS.BLUE6) - case 512: - self.image.fill(COLORS.BLUE7) - case 1024: - self.image.fill(COLORS.ORANGE) - case 2048: - self.image.fill(COLORS.RED) + """Change the color of the block based on its value""" + color_map = { + 2: COLORS.BLUE, + 4: COLORS.BLUE0, + 8: COLORS.BLUE1, + 16: COLORS.BLUE2, + 32: COLORS.DARK3, + 64: COLORS.BORDER_HIGHLIGHT, + 128: COLORS.BLUE5, + 256: COLORS.BLUE6, + 512: COLORS.BLUE7, + 1024: COLORS.ORANGE, + 2048: COLORS.RED, + } + self.image.fill(color_map.get(self.value, COLORS.ERROR)) + + def __add__(self, other: "Block") -> "Block": + """Add the value of two blocks and return a new block""" + new_block = Block(self.rect.x, self.rect.y) + new_block.value = self.value + other.value + return new_block + + def __iadd__(self, other: "Block") -> "Block": + """Add the value of two blocks and return a new block""" + return self + other + + def __eq__(self, other: "Block") -> bool: + """Check if two block values are equal""" + return self.value == other.value + + def __repr__(self) -> str: + """Return a string representation of the block""" + return f"Block({self.rect.x}, {self.rect.y})" + + def __str__(self) -> str: + """Return a string representation of the block""" + self.__repr__() + + def __hash__(self) -> int: + """Return a hash of the block""" + return hash((self.rect.x, self.rect.y, self.value))