mirror of
https://github.com/kristoferssolo/2048.git
synced 2025-10-21 15:20:35 +00:00
refactor(game): move grid to separate class
This commit is contained in:
parent
73a49d4d65
commit
fd48aa5b1b
@ -6,6 +6,8 @@ from loguru import logger
|
|||||||
from .colors import COLORS
|
from .colors import COLORS
|
||||||
from .config import Config
|
from .config import Config
|
||||||
|
|
||||||
|
from .utils import Direction
|
||||||
|
|
||||||
|
|
||||||
def _show_pos(pos: int) -> int:
|
def _show_pos(pos: int) -> int:
|
||||||
"""Return the position in the grid."""
|
"""Return the position in the grid."""
|
||||||
@ -32,10 +34,13 @@ class Block(pygame.sprite.Sprite):
|
|||||||
text_rect = text.get_rect(center=self.image.get_rect().center)
|
text_rect = text.get_rect(center=self.image.get_rect().center)
|
||||||
self.image.blit(text, text_rect)
|
self.image.blit(text, text_rect)
|
||||||
|
|
||||||
def move(self, dx: int, dy: int) -> None:
|
def move(self, direction: Direction) -> None:
|
||||||
"""Move the block by `dx` and `dy`."""
|
"""Move the block by `dx` and `dy`."""
|
||||||
new_x = self.rect.x + dx
|
dx, dy = direction.value
|
||||||
new_y = self.rect.y + dy
|
|
||||||
|
new_x = self.rect.x + dx * Config.BLOCK_SIZE
|
||||||
|
new_y = self.rect.y + dy * Config.BLOCK_SIZE
|
||||||
|
|
||||||
if 0 <= new_x <= Config.WIDTH - Config.BLOCK_SIZE and 0 <= new_y <= Config.HEIGHT - Config.BLOCK_SIZE:
|
if 0 <= new_x <= Config.WIDTH - Config.BLOCK_SIZE and 0 <= new_y <= Config.HEIGHT - Config.BLOCK_SIZE:
|
||||||
logger.debug(f"Moving block({id(self)}): {self} => ({_show_pos(new_x)}, {_show_pos(new_y)})")
|
logger.debug(f"Moving block({id(self)}): {self} => ({_show_pos(new_x)}, {_show_pos(new_y)})")
|
||||||
self.rect.x = new_x
|
self.rect.x = new_x
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
import random
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import pygame
|
import pygame
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
|
||||||
from .block import Block
|
|
||||||
from .colors import COLORS
|
from .colors import COLORS
|
||||||
from .config import Config
|
from .config import Config
|
||||||
|
from .grid import Grid
|
||||||
from .logger import setup_logger
|
from .logger import setup_logger
|
||||||
|
from .utils import Direction
|
||||||
|
|
||||||
|
|
||||||
class Game:
|
class Game:
|
||||||
@ -18,8 +18,8 @@ class Game:
|
|||||||
pygame.init()
|
pygame.init()
|
||||||
self.screen: pygame.Surface = pygame.display.set_mode((Config.WIDTH, Config.HEIGHT))
|
self.screen: pygame.Surface = pygame.display.set_mode((Config.WIDTH, Config.HEIGHT))
|
||||||
pygame.display.set_caption("2048")
|
pygame.display.set_caption("2048")
|
||||||
self.sprites = pygame.sprite.Group()
|
self.blocks = Grid()
|
||||||
self._generate_random_block(Config.INITIAL_BLOCK_COUNT)
|
self.blocks.generate_random_block(Config.INITIAL_BLOCK_COUNT)
|
||||||
|
|
||||||
def run(self) -> None:
|
def run(self) -> None:
|
||||||
"""Run the game loop."""
|
"""Run the game loop."""
|
||||||
@ -30,12 +30,12 @@ class Game:
|
|||||||
|
|
||||||
def _update(self) -> None:
|
def _update(self) -> None:
|
||||||
"""Update the game."""
|
"""Update the game."""
|
||||||
self.sprites.update()
|
self.blocks.update()
|
||||||
|
|
||||||
def _render(self) -> None:
|
def _render(self) -> None:
|
||||||
"""Render the game."""
|
"""Render the game."""
|
||||||
self.screen.fill(COLORS.BG)
|
self.screen.fill(COLORS.BG)
|
||||||
self.sprites.draw(self.screen)
|
self.blocks.draw(self.screen)
|
||||||
pygame.display.flip()
|
pygame.display.flip()
|
||||||
|
|
||||||
def _hande_events(self) -> None:
|
def _hande_events(self) -> None:
|
||||||
@ -56,60 +56,20 @@ class Game:
|
|||||||
self.exit()
|
self.exit()
|
||||||
|
|
||||||
def move_up(self) -> None:
|
def move_up(self) -> None:
|
||||||
"""Move all blocks up"""
|
|
||||||
logger.debug("Move up")
|
logger.debug("Move up")
|
||||||
self._move_blocks(0, -Config.BLOCK_SIZE)
|
self.blocks.move(Direction.UP)
|
||||||
|
|
||||||
def move_down(self) -> None:
|
def move_down(self) -> None:
|
||||||
"""Move all blocks down"""
|
|
||||||
logger.debug("Move down")
|
logger.debug("Move down")
|
||||||
self._move_blocks(0, Config.BLOCK_SIZE)
|
self.blocks.move(Direction.DOWN)
|
||||||
|
|
||||||
def move_left(self) -> None:
|
def move_left(self) -> None:
|
||||||
"""Move all blocks left"""
|
|
||||||
logger.debug("Move left")
|
logger.debug("Move left")
|
||||||
self._move_blocks(-Config.BLOCK_SIZE, 0)
|
self.blocks.move(Direction.LEFT)
|
||||||
|
|
||||||
def move_right(self) -> None:
|
def move_right(self) -> None:
|
||||||
"""Move all blocks right"""
|
|
||||||
logger.debug("Move right")
|
logger.debug("Move right")
|
||||||
self._move_blocks(Config.BLOCK_SIZE, 0)
|
self.blocks.move(Direction.RIGHT)
|
||||||
|
|
||||||
def _move_blocks(self, dx: int, dy: int) -> None:
|
|
||||||
"""Move all the blocks by `dx` and `dy`."""
|
|
||||||
moved_blocks = pygame.sprite.Group() # Keep track of moved blocks to avoid double merging
|
|
||||||
blocks_to_remove = []
|
|
||||||
|
|
||||||
for block in self.sprites:
|
|
||||||
block.move(dx, dy)
|
|
||||||
|
|
||||||
for block in self.sprites:
|
|
||||||
colliding_blocks = pygame.sprite.spritecollide(block, self.sprites, False)
|
|
||||||
|
|
||||||
for other_block in colliding_blocks:
|
|
||||||
if block != other_block and block.value == other_block.value and other_block not in moved_blocks:
|
|
||||||
new_block = block + other_block
|
|
||||||
moved_blocks.add(new_block)
|
|
||||||
blocks_to_remove.extend([block, other_block])
|
|
||||||
|
|
||||||
for block in blocks_to_remove:
|
|
||||||
self.sprites.remove(block)
|
|
||||||
|
|
||||||
self._generate_random_block()
|
|
||||||
|
|
||||||
def _generate_random_block(self, count: int = 1) -> None:
|
|
||||||
"""Generate `count` number of random blocks."""
|
|
||||||
for _ in range(count):
|
|
||||||
while True:
|
|
||||||
x = random.randint(0, 2) * Config.BLOCK_SIZE # random column position
|
|
||||||
y = random.randint(0, 2) * Config.BLOCK_SIZE # random row position
|
|
||||||
block = Block(x, y)
|
|
||||||
|
|
||||||
colliding_blocks = pygame.sprite.spritecollide(block, self.sprites, False) # check collision
|
|
||||||
|
|
||||||
if not colliding_blocks:
|
|
||||||
self.sprites.add(block)
|
|
||||||
break
|
|
||||||
|
|
||||||
def exit(self) -> None:
|
def exit(self) -> None:
|
||||||
"""Exit the game."""
|
"""Exit the game."""
|
||||||
|
|||||||
27
src/py2048/grid.py
Normal file
27
src/py2048/grid.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import random
|
||||||
|
|
||||||
|
import pygame
|
||||||
|
|
||||||
|
from .block import Block
|
||||||
|
from .config import Config
|
||||||
|
from .utils import Direction
|
||||||
|
|
||||||
|
|
||||||
|
class Grid(pygame.sprite.Group):
|
||||||
|
def move(self, direction: Direction):
|
||||||
|
for block in self:
|
||||||
|
block.move(direction)
|
||||||
|
|
||||||
|
def generate_random_block(self, count: int = 1) -> None:
|
||||||
|
"""Generate `count` number of random blocks."""
|
||||||
|
for _ in range(count):
|
||||||
|
while True:
|
||||||
|
x = random.randint(0, 2) * Config.BLOCK_SIZE # random column position
|
||||||
|
y = random.randint(0, 2) * Config.BLOCK_SIZE # random row position
|
||||||
|
block = Block(x, y)
|
||||||
|
|
||||||
|
colliding_blocks = pygame.sprite.spritecollide(block, self, False) # check collision
|
||||||
|
|
||||||
|
if not colliding_blocks:
|
||||||
|
self.add(block)
|
||||||
|
break
|
||||||
Loading…
Reference in New Issue
Block a user