feat(game): add header and center board

This commit is contained in:
Kristofers Solo 2024-01-01 21:17:36 +02:00
parent 70e0172ec7
commit e7932303c2
5 changed files with 73 additions and 30 deletions

View File

@ -61,10 +61,11 @@ class Block(pygame.sprite.Sprite):
def _is_out_if_bounds(self, x: int, y: int) -> bool:
"""Return whether the block is out of bounds."""
return not (
0 <= x <= Config.GRID_WIDTH - Config.BLOCK_SIZE
and 0 <= y <= Config.GRID_HEIGHT - Config.BLOCK_SIZE
)
board_left = Config.BOARD_X
board_right = Config.BOARD_X + Config.BOARD_WIDTH - Config.BLOCK_SIZE
board_top = Config.BOARD_Y
board_bottom = Config.BOARD_Y + Config.BOARD_HEIGHT - Config.BLOCK_SIZE
return not (board_left <= x <= board_right and board_top <= y <= board_bottom)
def _has_collision(self, x: int, y: int) -> bool:
"""Checks whether the block has a collision with any other block."""

View File

@ -10,12 +10,26 @@ from .utils import Direction
class Board(pygame.sprite.Group):
def __init__(self, screen: pygame.Surface):
def __init__(self):
super().__init__()
self.screen = screen
self.rect = pygame.Rect(0, 0, Config.BOARD_WIDTH, Config.BOARD_HEIGHT)
self.rect.x = Config.BOARD_X
self.rect.y = Config.BOARD_Y
self.initiate_game()
def initiate_game(self) -> None:
"""Initiate the game."""
self.generate_initial_blocks()
def draw(self, screen: pygame.Surface) -> None:
"""Draw the board."""
block: Block
pygame.draw.rect(screen, Color.YELLOW, self.rect, 2)
super().draw(screen)
def move(self, direction: Direction):
"""Move the blocks in the specified direction."""
blocks = self.sprites()
block: Block
@ -54,8 +68,8 @@ class Board(pygame.sprite.Group):
"""Generate a block with random coordinates aligned with the grid."""
while True:
# Generate random coordinates aligned with the grid
x = random.randint(0, 3) * Config.BLOCK_SIZE
y = random.randint(0, 3) * Config.BLOCK_SIZE
x = random.randint(0, 3) * Config.BLOCK_SIZE + Config.BOARD_X
y = random.randint(0, 3) * Config.BLOCK_SIZE + Config.BOARD_Y
block = Block(x, y, self)
colliding_blocks = pygame.sprite.spritecollide(
@ -64,12 +78,11 @@ class Board(pygame.sprite.Group):
if not colliding_blocks:
self.add(block)
logger.debug(f"Created block at {block.pos}")
break
return
def _is_full(self) -> bool:
"""Check if the board is full."""
return len(self.sprites()) == Config.GRID_SIZE**2
return len(self.sprites()) == Config.BOARD_SIZE**2
def _can_move(self) -> bool:
"""Check if any movement is possible on the board."""
@ -83,7 +96,7 @@ class Board(pygame.sprite.Group):
"""Check if the game is over."""
return self._is_full() and not self._can_move()
def restart(self) -> None:
"""Restart the game."""
def reset(self) -> None:
"""Reset the board."""
self.empty()
self.generate_initial_blocks()
self.initiate_game()

View File

@ -1,11 +1,25 @@
class Config:
FONT_FAMILY = "Roboto"
FONT_SIZE = 40
GRID_SIZE = 4
FONT_SIZE = 32
BOARD_SIZE = 4
BLOCK_SIZE = 50
WIDTH = GRID_SIZE * BLOCK_SIZE
HEIGHT = GRID_SIZE * BLOCK_SIZE + 100
GRID_HEIGHT = GRID_SIZE * BLOCK_SIZE
GRID_WIDTH = GRID_SIZE * BLOCK_SIZE
# WIDTH = BOARD_SIZE * BLOCK_SIZE + BLOCK_SIZE
# HEIGHT = BOARD_SIZE * BLOCK_SIZE + BLOCK_SIZE * 2
BOARD_WIDTH = BOARD_SIZE * BLOCK_SIZE
BOARD_HEIGHT = BOARD_SIZE * BLOCK_SIZE
HEADER_WIDTH = BOARD_WIDTH + BLOCK_SIZE
HEADER_HEIGHT = BLOCK_SIZE
BOARD_X = BLOCK_SIZE // 2
BOARD_Y = HEADER_HEIGHT + BLOCK_SIZE // 2
SCREEN_WIDTH = HEADER_WIDTH
SCREEN_HEIGHT = BOARD_HEIGHT + BLOCK_SIZE + HEADER_HEIGHT
SCREEN_SIZE = SCREEN_WIDTH, SCREEN_HEIGHT
INITIAL_BLOCK_COUNT = 2
BLOCK_VALUE_PROBABILITY = 0.9

View File

@ -7,6 +7,7 @@ from .board import Board
from .color import Color
from .config import Config
from .logger import setup_logger
from .screens.header import Header
from .utils import Direction
@ -16,11 +17,10 @@ class Game:
logger.info("Initializing game")
pygame.init()
self.screen: pygame.Surface = pygame.display.set_mode(
(Config.WIDTH, Config.HEIGHT)
)
self.screen: pygame.Surface = pygame.display.set_mode(Config.SCREEN_SIZE)
pygame.display.set_caption("2048")
self.blocks = Board(self.screen)
self.board = Board()
self.header = Header()
def run(self) -> None:
"""Run the game loop."""
@ -31,12 +31,13 @@ class Game:
def _update(self) -> None:
"""Update the game."""
self.blocks.update()
self.board.update()
def _render(self) -> None:
"""Render the game."""
self.screen.fill(Color.BG)
self.blocks.draw(self.screen)
self.board.draw(self.screen)
self.header.draw(self.screen)
pygame.display.flip()
def _hande_events(self) -> None:
@ -57,16 +58,16 @@ class Game:
self.exit()
def move_up(self) -> None:
self.blocks.move(Direction.UP)
self.board.move(Direction.UP)
def move_down(self) -> None:
self.blocks.move(Direction.DOWN)
self.board.move(Direction.DOWN)
def move_left(self) -> None:
self.blocks.move(Direction.LEFT)
self.board.move(Direction.LEFT)
def move_right(self) -> None:
self.blocks.move(Direction.RIGHT)
self.board.move(Direction.RIGHT)
def exit(self) -> None:
"""Exit the game."""

View File

@ -0,0 +1,14 @@
import pygame
from ..color import Color
from ..config import Config
class Header:
def __init__(self) -> None:
self.rect = pygame.Rect(0, 0, Config.HEADER_WIDTH, Config.HEADER_HEIGHT)
self.score = 0 # TODO: Implement score
def draw(self, screen: pygame.Surface) -> None:
"""Draw the header."""
pygame.draw.rect(screen, Color.MAGENTA, self.rect, 2)