mirror of
https://github.com/kristoferssolo/2048.git
synced 2025-10-21 15:20:35 +00:00
feat(game): add game restard option
This commit is contained in:
parent
4b02daf12b
commit
97a64b44b6
3
src/path.py
Normal file
3
src/path.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
BASE_PATH = Path(__file__).resolve().parent.parent
|
||||||
@ -1,5 +1,4 @@
|
|||||||
from .game import Game
|
from .game import Game
|
||||||
from .header import Header
|
|
||||||
from .menu import Menu
|
from .menu import Menu
|
||||||
|
|
||||||
__all__ = ["Header", "Menu", "Game"]
|
__all__ = ["Menu", "Game"]
|
||||||
|
|||||||
@ -2,25 +2,36 @@ import pygame
|
|||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
|
||||||
from py2048 import Config
|
from py2048 import Config
|
||||||
from py2048.objects import Board
|
from py2048.objects import Board, Button, ScoreLabel
|
||||||
from py2048.utils import Direction, setup_logger
|
from py2048.utils import Direction, Position, Size, setup_logger
|
||||||
|
|
||||||
from .header import Header
|
|
||||||
|
|
||||||
|
|
||||||
class Game:
|
class Game:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.header = Header()
|
self.rect = pygame.Rect(0, 0, *Config.HEADER.size)
|
||||||
|
self.labels = self._create_labels()
|
||||||
|
self.buttons = self._create_buttons()
|
||||||
self.board = Board()
|
self.board = Board()
|
||||||
|
|
||||||
|
def update_score(self, new_score: int) -> None:
|
||||||
|
"""Updates the score to `new_score`."""
|
||||||
|
self.score.update_score(new_score)
|
||||||
|
|
||||||
def draw(self, surface: pygame.Surface) -> None:
|
def draw(self, surface: pygame.Surface) -> None:
|
||||||
surface.fill(Config.COLORSCHEME.BG)
|
surface.fill(Config.COLORSCHEME.BG)
|
||||||
self.board.draw(surface)
|
self.board.draw(surface)
|
||||||
self.header.draw(surface)
|
self.labels.draw(surface)
|
||||||
|
self.buttons.draw(surface)
|
||||||
pygame.display.flip()
|
pygame.display.flip()
|
||||||
|
|
||||||
def handle_events(self, event: pygame.Event) -> None:
|
def handle_events(self, event: pygame.Event) -> None:
|
||||||
if event.type == pygame.KEYDOWN:
|
if event.type == pygame.MOUSEBUTTONDOWN:
|
||||||
|
for button in self.buttons:
|
||||||
|
button.on_click(Position(*event.pos))
|
||||||
|
elif event.type == pygame.MOUSEMOTION:
|
||||||
|
for button in self.buttons:
|
||||||
|
button.on_hover(Position(*event.pos))
|
||||||
|
elif event.type == pygame.KEYDOWN:
|
||||||
if event.key in (pygame.K_LEFT, pygame.K_a, pygame.K_h):
|
if event.key in (pygame.K_LEFT, pygame.K_a, pygame.K_h):
|
||||||
self.move_left()
|
self.move_left()
|
||||||
elif event.key in (pygame.K_RIGHT, pygame.K_d, pygame.K_l):
|
elif event.key in (pygame.K_RIGHT, pygame.K_d, pygame.K_l):
|
||||||
@ -33,7 +44,14 @@ class Game:
|
|||||||
def move(self, direction: Direction) -> None:
|
def move(self, direction: Direction) -> None:
|
||||||
"""Moved the board in the given direction and updates the score."""
|
"""Moved the board in the given direction and updates the score."""
|
||||||
self.board.move(direction)
|
self.board.move(direction)
|
||||||
self.header.update(self.board.score)
|
self.update_score(self.board.score)
|
||||||
|
if self.board.is_game_over():
|
||||||
|
logger.info("Game over!")
|
||||||
|
self.restart()
|
||||||
|
|
||||||
|
def restart(self) -> None:
|
||||||
|
self.board.reset()
|
||||||
|
self.update_score(0)
|
||||||
|
|
||||||
def move_up(self) -> None:
|
def move_up(self) -> None:
|
||||||
self.move(Direction.UP)
|
self.move(Direction.UP)
|
||||||
@ -46,3 +64,49 @@ class Game:
|
|||||||
|
|
||||||
def move_right(self) -> None:
|
def move_right(self) -> None:
|
||||||
self.move(Direction.RIGHT)
|
self.move(Direction.RIGHT)
|
||||||
|
|
||||||
|
def _create_labels(self) -> pygame.sprite.Group:
|
||||||
|
size = Size(60, 40)
|
||||||
|
|
||||||
|
self.score = ScoreLabel(
|
||||||
|
value=0,
|
||||||
|
text="Score",
|
||||||
|
size=size,
|
||||||
|
position=Position(
|
||||||
|
Config.SCREEN.size.width - Config.TILE.size // 2 - size.width * 2 - 10,
|
||||||
|
10,
|
||||||
|
),
|
||||||
|
bg_color=Config.COLORSCHEME.BOARD_BG,
|
||||||
|
font_color=Config.COLORSCHEME.LIGHT_TEXT,
|
||||||
|
font_size=16,
|
||||||
|
border_radius=2,
|
||||||
|
)
|
||||||
|
highscore = ScoreLabel(
|
||||||
|
value=2048,
|
||||||
|
text="Best",
|
||||||
|
size=size,
|
||||||
|
position=Position(
|
||||||
|
Config.SCREEN.size.width - Config.TILE.size // 2 - size.width, 10
|
||||||
|
),
|
||||||
|
bg_color=Config.COLORSCHEME.BOARD_BG,
|
||||||
|
font_color=Config.COLORSCHEME.LIGHT_TEXT,
|
||||||
|
font_size=16,
|
||||||
|
border_radius=2,
|
||||||
|
)
|
||||||
|
|
||||||
|
return pygame.sprite.Group(self.score, highscore)
|
||||||
|
|
||||||
|
def _create_buttons(self) -> pygame.sprite.Group:
|
||||||
|
reset = Button(
|
||||||
|
position=(10, 10),
|
||||||
|
bg_color=Config.COLORSCHEME.BOARD_BG,
|
||||||
|
font_color=Config.COLORSCHEME.LIGHT_TEXT,
|
||||||
|
hover_color=Config.COLORSCHEME.TILE_0,
|
||||||
|
size=(100, 30),
|
||||||
|
text="New Game",
|
||||||
|
border_radius=Config.TILE.border.radius,
|
||||||
|
action=self.restart,
|
||||||
|
font_size=16,
|
||||||
|
border_width=2,
|
||||||
|
)
|
||||||
|
return pygame.sprite.Group(reset)
|
||||||
|
|||||||
@ -1,49 +0,0 @@
|
|||||||
import pygame
|
|
||||||
|
|
||||||
from py2048 import Config
|
|
||||||
from py2048.objects import ScoreLabel
|
|
||||||
from py2048.utils import Position, Size
|
|
||||||
|
|
||||||
|
|
||||||
class Header:
|
|
||||||
def __init__(self) -> None:
|
|
||||||
self.rect = pygame.Rect(0, 0, *Config.HEADER.size)
|
|
||||||
self.labels = self._create_labels()
|
|
||||||
|
|
||||||
def _create_labels(self) -> pygame.sprite.Group:
|
|
||||||
size = Size(60, 40)
|
|
||||||
|
|
||||||
self.score = ScoreLabel(
|
|
||||||
value=0,
|
|
||||||
text="Score",
|
|
||||||
size=size,
|
|
||||||
position=Position(
|
|
||||||
Config.SCREEN.size.width - Config.TILE.size // 2 - size.width * 2 - 10,
|
|
||||||
10,
|
|
||||||
),
|
|
||||||
bg_color=Config.COLORSCHEME.BOARD_BG,
|
|
||||||
font_color=Config.COLORSCHEME.LIGHT_TEXT,
|
|
||||||
font_size=16,
|
|
||||||
border_radius=2,
|
|
||||||
)
|
|
||||||
highscore = ScoreLabel(
|
|
||||||
value=2048,
|
|
||||||
text="Best",
|
|
||||||
size=size,
|
|
||||||
position=Position(
|
|
||||||
Config.SCREEN.size.width - Config.TILE.size // 2 - size.width, 10
|
|
||||||
),
|
|
||||||
bg_color=Config.COLORSCHEME.BOARD_BG,
|
|
||||||
font_color=Config.COLORSCHEME.LIGHT_TEXT,
|
|
||||||
font_size=16,
|
|
||||||
border_radius=2,
|
|
||||||
)
|
|
||||||
|
|
||||||
return pygame.sprite.Group(self.score, highscore)
|
|
||||||
|
|
||||||
def draw(self, surface: pygame.Surface) -> None:
|
|
||||||
self.labels.draw(surface)
|
|
||||||
|
|
||||||
def update(self, new_score: int) -> None:
|
|
||||||
"""Updates the score to `new_score`."""
|
|
||||||
self.score.update_score(new_score)
|
|
||||||
@ -1,13 +1,10 @@
|
|||||||
from pathlib import Path
|
|
||||||
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
from path import BASE_PATH
|
||||||
|
|
||||||
from .collections import Board, Font, Header, Position, Screen, Size, Tile
|
from .collections import Board, Font, Header, Position, Screen, Size, Tile
|
||||||
from .color import ColorScheme
|
from .color import ColorScheme
|
||||||
from .enums import Direction
|
from .enums import Direction
|
||||||
|
|
||||||
BASE_PATH = Path(__file__).resolve().parent.parent.parent.parent
|
|
||||||
|
|
||||||
|
|
||||||
def setup_logger() -> None:
|
def setup_logger() -> None:
|
||||||
logger.add(
|
logger.add(
|
||||||
@ -20,7 +17,6 @@ def setup_logger() -> None:
|
|||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"BASE_PATH",
|
|
||||||
"Board",
|
"Board",
|
||||||
"ColorScheme",
|
"ColorScheme",
|
||||||
"Direction",
|
"Direction",
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user