feat(game): add figure rotation

This commit is contained in:
Kristofers Solo 2024-01-04 04:46:50 +02:00
parent 2df1c0a156
commit 2c040b4575
4 changed files with 57 additions and 10 deletions

View File

@ -27,3 +27,6 @@ class Block(pygame.sprite.Sprite):
def horizontal_collision(self, y: int, field: np.ndarray) -> bool:
return y >= CONFIG.game.rows or (y >= 0 and field[y, int(self.pos.x)])
def rotate(self, pivot: pygame.Vector2) -> pygame.Vector2:
return pivot + (self.pos - pivot).rotate(90)

View File

@ -31,6 +31,7 @@ class Game:
self.timers = Timers(
Timer(CONFIG.game.initial_speed, True, self.move_down),
Timer(CONFIG.game.movment_delay),
Timer(CONFIG.game.rotation_delay),
)
self.timers.vertical.activate()
@ -64,6 +65,17 @@ class Game:
self.move_right()
self.timers.horizontal.activate()
if not self.timers.rotation.active:
if (
keys[pygame.K_SPACE]
or keys[pygame.K_r]
or keys[pygame.K_UP]
or keys[pygame.K_w]
or keys[pygame.K_k]
):
self.tetromino.rotate()
self.timers.rotation.activate()
def move_down(self) -> None:
self.tetromino.move_down()
@ -131,7 +143,9 @@ class Game:
self._delete_rows(delete_rows)
def _delete_rows(self, delete_rows: list[int]) -> None:
if delete_rows:
if not delete_rows:
return
for row in delete_rows:
for block in self.field[row]:
block.kill()

View File

@ -2,7 +2,7 @@ from typing import Callable, Optional
import numpy as np
import pygame
from utils import CONFIG, Direction, Figure, FigureConfig, Size
from utils import CONFIG, Direction, Figure, Size
from .block import Block
from .log import log
@ -16,9 +16,9 @@ class Tetromino:
field: np.ndarray,
shape: Optional[Figure] = None,
) -> None:
self.figure: FigureConfig = shape.value if shape else Figure.random().value
self.block_positions: list[pygame.Vector2] = self.figure.shape
self.color: str = self.figure.color
self.figure: Figure = shape if shape else Figure.random()
self.block_positions: list[pygame.Vector2] = self.figure.value.shape
self.color: str = self.figure.value.color
self.create_new = func
self.field = field
@ -41,6 +41,21 @@ class Tetromino:
for block in self.blocks:
block.pos.x += direction.value
def rotate(self) -> None:
if self.figure == Figure.O:
return
pivot: pygame.Vector2 = self.blocks[0].pos
new_positions: list[pygame.Vector2] = [
block.rotate(pivot) for block in self.blocks
]
if not self._are_new_positions_valid(new_positions):
return
self._update_block_positions(new_positions)
def _check_vertical_collision(
self, blocks: list[Block], direction: Direction
) -> bool:
@ -56,3 +71,17 @@ class Tetromino:
block.horizontal_collision(int(block.pos.y + direction.value), self.field)
for block in self.blocks
)
def _are_new_positions_valid(self, new_positions: list[pygame.Vector2]) -> bool:
for pos in new_positions:
if not (
0 <= pos.x < CONFIG.game.columns and 0 <= pos.y <= CONFIG.game.rows
):
return False
if self.field[int(pos.y), int(pos.x)]:
return False
return True
def _update_block_positions(self, new_positions: list[pygame.Vector2]) -> None:
for block, new_pos in zip(self.blocks, new_positions):
block.pos = new_pos

View File

@ -35,3 +35,4 @@ class Timer:
class Timers(NamedTuple):
vertical: Timer
horizontal: Timer
rotation: Timer