Files
tetri5/entity/Piece.py

95 lines
4.1 KiB
Python

from typing import List, Tuple
import pygame
import copy
from entity.Entity import Entity
from util.ConfigurationManager import ConfigurationManager
'''
For information on the Tetris piece Tetromino go here:
https://tetris.fandom.com/wiki/Tetromino
'''
class Piece(Entity):
def __init__(self, shape: Tuple, position: Tuple, color: str):
super().__init__()
self.color = color
self.points = self.__get_points(shape, position)
self.center = self.__get_center(shape, position)
self.previous_points = None
self.previous_center = None
def draw(self, surface: pygame.Surface) -> None:
tile_size = ConfigurationManager.configuration["engine"]["tile-size"]
hex_color = ConfigurationManager.configuration["color"]["border"] # TODO should abstract out color call?
base_color = pygame.Color(self.color)
border_color = pygame.Color(hex_color)
for sub_points in self.points:
pygame.draw.polygon(surface, base_color, sub_points, 0)
pygame.draw.polygon(surface, border_color, sub_points, max(tile_size // 6, 1))
def move(self, vector: Tuple) -> None:
self.previous_points = copy.deepcopy(self.points)
self.previous_center = copy.deepcopy(self.center)
self.center[0] += vector[0]
self.center[1] += vector[1]
for sub_points in self.points:
for point in sub_points:
point[0] += vector[0]
point[1] += vector[1]
'''
For more information on a rotation of a piece go here:
https://gamedev.stackexchange.com/questions/17974/how-to-rotate-blocks-in-tetris
'''
def rotate(self) -> None:
self.previous_points = copy.deepcopy(self.points)
self.previous_center = copy.deepcopy(self.center)
for sub_points in self.points:
for point in sub_points:
h = point[0] - self.center[0]
k = point[1] - self.center[1]
point[0] = (k * -1) + self.center[0]
point[1] = h + self.center[1]
def revert(self) -> None:
if self.previous_points and self.previous_center:
self.points = self.previous_points
self.center = self.previous_center
def __get_points(self, shape: Tuple, position: Tuple) -> List:
tile_size = ConfigurationManager.configuration["engine"]["tile-size"]
points = []
for square in shape[:-1]:
sub_points = []
for vertex in square:
point = [vertex[0] * tile_size + position[0], vertex[1] * tile_size + position[1]]
sub_points.append(point)
points.append(sub_points)
return points
def __get_center(self, shape: Tuple, position: Tuple) -> List:
tile_size = ConfigurationManager.configuration["engine"]["tile-size"]
center = shape[-1]
# cast to int and avoid exception from pygame
return [int(center[0] * tile_size + position[0]), int(center[1] * tile_size + position[1])]
# shape attributes
I_SHAPE = (((0, 0), (1, 0), (1, 1), (0, 1)), ((1, 0), (2, 0), (2, 1), (1, 1)), ((2, 0), (3, 0), (3, 1), (2, 1)), ((3, 0), (4, 0), (4, 1), (3, 1)), (2, 0))
J_SHAPE = (((0, 0), (1, 0), (1, 1), (0, 1)), ((1, 0), (2, 0), (2, 1), (1, 1)), ((2, 0), (3, 0), (3, 1), (2, 1)), ((2, 1), (3, 1), (3, 2), (2, 2)), (1.5, 0.5))
L_SHAPE = (((0, 0), (1, 0), (1, 1), (0, 1)), ((1, 0), (2, 0), (2, 1), (1, 1)), ((2, 0), (3, 0), (3, 1), (2, 1)), ((0, 1), (1, 1), (1, 2), (0, 2)), (1.5, 0.5))
O_SHAPE = (((0, 0), (1, 0), (1, 1), (0, 1)), ((1, 0), (2, 0), (2, 1), (1, 1)), ((1, 1), (2, 1), (2, 2), (1, 2)), ((0, 1), (1, 1), (1, 2), (0, 2)), (1, 1))
S_SHAPE = (((0, 1), (1, 1), (1, 2), (0, 2)), ((1, 0), (2, 0), (2, 1), (1, 1)), ((1, 1), (2, 1), (2, 2), (1, 2)), ((2, 0), (3, 0), (3, 1), (2, 1)), (1.5, 0.5))
T_SHAPE = (((0, 0), (1, 0), (1, 1), (0, 1)), ((1, 0), (2, 0), (2, 1), (1, 1)), ((1, 1), (2, 1), (2, 2), (1, 2)), ((2, 0), (3, 0), (3, 1), (2, 1)), (1.5, 0.5))
Z_SHAPE = (((0, 0), (1, 0), (1, 1), (0, 1)), ((1, 0), (2, 0), (2, 1), (1, 1)), ((1, 1), (2, 1), (2, 2), (1, 2)), ((2, 1), (3, 1), (3, 2), (2, 2)), (1.5, 0.5))