From f4049ca3bbd79c2c6568e519cde92836cc79769a Mon Sep 17 00:00:00 2001 From: Olivier Gayot Date: Sat, 13 Nov 2021 12:05:18 +0100 Subject: Add optional coordinates to a piece Signed-off-by: Olivier Gayot --- cameltris/coordinates.py | 11 ++++++ cameltris/piece.py | 4 ++ cameltris/player.py | 98 +++++++++++++++++++++++++++++++++--------------- 3 files changed, 83 insertions(+), 30 deletions(-) create mode 100644 cameltris/coordinates.py (limited to 'cameltris') diff --git a/cameltris/coordinates.py b/cameltris/coordinates.py new file mode 100644 index 0000000..a5cee80 --- /dev/null +++ b/cameltris/coordinates.py @@ -0,0 +1,11 @@ +from dataclasses import dataclass + + +@dataclass +class Coordinates: + x: int + y: int + + def __add__(self, other: "Coordinates"): + """ Return the result of the addition of two Coordinates objects. """ + return Coordinates(x=self.x + other.x, y = self.y + other.y) diff --git a/cameltris/piece.py b/cameltris/piece.py index d8e7b63..3636fbd 100644 --- a/cameltris/piece.py +++ b/cameltris/piece.py @@ -1,8 +1,11 @@ """ Module that defines all types of pieces """ +from typing import Optional + import pygame from .color import Color +from .coordinates import Coordinates square_template = pygame.Surface((48, 48)) @@ -12,6 +15,7 @@ class Piece: """ A piece class that provides default methods for performing rotations """ def __init__(self): """ Initialize a piece """ + self.coord: Optional[Coordinates] = None self.square = square_template.copy() def rotate_clockwise(self): diff --git a/cameltris/player.py b/cameltris/player.py index 90eb2db..88d62d4 100644 --- a/cameltris/player.py +++ b/cameltris/player.py @@ -29,8 +29,8 @@ class Player: self.controller = controller self.playfield = PlayField() - self.current_piece, self.current_piece_position = self.generate_piece() - self.next_piece, self.next_piece_position = self.generate_piece() + self.current_piece: Piece = self.generate_piece() + self.next_piece = self.generate_piece() self.level = self.starting_level = starting_level self.score = 0 @@ -47,8 +47,8 @@ class Player: self.score_canvas = pygame.Surface((296, 50)) self.level_canvas = pygame.Surface((296, 50)) - def generate_piece(self) -> tuple[Piece, list[int]]: - """ Generate a new piece and return it alongside its coordinates """ + def generate_piece(self) -> Piece: + """ Generate a new piece and return it """ # We may want to make this a function outside the class piece = random.choice((TPiece, SPiece, IPiece, ZPiece, SquarePiece, LPiece, JPiece))() @@ -56,22 +56,29 @@ class Player: if list(filter(lambda x: x is not None, row)): break - initial_y_position = -row_id - initial_x_position = (len(self.playfield.grid[0]) // 2) - (len(piece.elements[0]) // 2) + piece.coord = Coordinates( + y = -row_id, + x = (len(self.playfield.grid[0]) // 2) - (len(piece.elements[0]) // 2) + ) - return (piece, [initial_y_position, initial_x_position]) + return piece def lock_piece(self) -> None: """ Lock a piece in its current position and trigger lines burning. Can raise a WouldCollide exception """ - if self.has_collision(self.current_piece_position[0], self.current_piece_position[1]): + + assert self.current_piece.coord is not None + + if self.has_collision(self.current_piece.coord): raise WouldCollide() - for row_id, row in enumerate(self.current_piece.elements): - for col_id, element in enumerate(row): + for piece_row_id, piece_row in enumerate(self.current_piece.elements): + for piece_col_id, element in enumerate(piece_row): if element is None: continue - self.playfield.grid[row_id + self.current_piece_position[0]][col_id + self.current_piece_position[1]] = element + row_idx = piece_row_id + self.current_piece.coord.y + col_idx = piece_col_id + self.current_piece.coord.x + self.playfield.grid[row_idx][col_idx] = element count = self.playfield.burn_rows() @@ -96,26 +103,28 @@ class Player: if self.lines_burnt >= self.level * 10: self.level += 1 - self.current_piece, self.current_piece_position = self.next_piece, self.next_piece_position - self.next_piece, self.next_piece_position = self.generate_piece() + self.current_piece, self.next_piece = self.next_piece, self.generate_piece() self.refresh_piece_preview_canvas() - def has_collision(self, y: int, x: int) -> bool: + def has_collision(self, coord: Coordinates) -> bool: """ Check if the current piece would collide with something else in the - playfield if it were placed on (y, x) """ + playfield if it were placed at the coordinates specified """ + + assert self.current_piece.coord is not None + try: for row_id, row in enumerate(self.current_piece.elements): for col_id, element in enumerate(row): if element is None: continue - if row_id + y < 0: + if row_id + coord.y < 0: continue - if col_id + x < 0: + if col_id + coord.x < 0: return True - if self.playfield.grid[row_id + y][col_id + x] is not None: + if self.playfield.grid[row_id + coord.y][col_id + coord.x] is not None: return True except IndexError: @@ -125,45 +134,63 @@ class Player: def move_piece_down(self) -> None: """ Try to move the current piece down. Can raise a WouldCollide exception """ - if not self.has_collision(self.current_piece_position[0] + 1, self.current_piece_position[1]): - self.current_piece_position[0] += 1 + + assert self.current_piece.coord is not None + + if not self.has_collision(self.current_piece.coord + Coordinates(x=0, y=1)): + self.current_piece.coord.y += 1 else: raise WouldCollide() def move_piece_up(self) -> None: """ Try to move the current piece up. Can raise a WouldCollide exception """ - if not self.has_collision(self.current_piece_position[0] - 1, self.current_piece_position[1]): - self.current_piece_position[0] -= 1 + + assert self.current_piece.coord is not None + + if not self.has_collision(self.current_piece.coord + Coordinates(x=0, y=-1)): + self.current_piece.coord.y -= 1 else: raise WouldCollide() def move_piece_left(self) -> None: """ Try to move the current piece left. Can raise a WouldCollide exception """ - if not self.has_collision(self.current_piece_position[0], self.current_piece_position[1] - 1): - self.current_piece_position[1] -= 1 + + assert self.current_piece.coord is not None + + if not self.has_collision(self.current_piece.coord + Coordinates(x=-1, y=0)): + self.current_piece.coord.x -= 1 else: raise WouldCollide() def move_piece_right(self) -> None: """ Try to move the current piece right. Can raise a WouldCollide exception """ - if not self.has_collision(self.current_piece_position[0], self.current_piece_position[1] + 1): - self.current_piece_position[1] += 1 + + assert self.current_piece.coord is not None + + if not self.has_collision(self.current_piece.coord + Coordinates(x=1, y=0)): + self.current_piece.coord.x += 1 else: raise WouldCollide() def rotate_piece_counter_clockwise(self) -> None: """ Rotate the current piece counter-clockwise. Can raise a WouldCollide exception """ + + assert self.current_piece.coord is not None + self.current_piece.rotate_counter_clockwise() - if self.has_collision(self.current_piece_position[0], self.current_piece_position[1]): + if self.has_collision(self.current_piece.coord): self.current_piece.rotate_clockwise() raise WouldCollide() def rotate_piece_clockwise(self) -> None: """ Rotate the current piece clockwise. Can raise a WouldCollide exception """ + + assert self.current_piece.coord is not None + self.current_piece.rotate_clockwise() - if self.has_collision(self.current_piece_position[0], self.current_piece_position[1]): + if self.has_collision(self.current_piece.coord): self.current_piece.rotate_counter_clockwise() raise WouldCollide() @@ -221,10 +248,17 @@ class Player: for row_idx, row in enumerate(non_empty_rows): for col_idx, element in enumerate(row): if element is not None: - self.piece_preview_canvas.blit(element, ((col_idx + x_offset) * 50 + 1, (row_idx + y_offset) * 50 + 1)) + coordinates = Coordinates( + x = (col_idx + x_offset) * 50 + 1, + y = (row_idx + y_offset) * 50 + 1 + ) + self.piece_preview_canvas.blit(element, (coordinates.x, coordinates.y)) def refresh_grid_canvas(self) -> None: """ Refresh the display of the playfield """ + + assert self.current_piece.coord is not None + self.grid_canvas.fill(Color.black.value) for row_idx, row in enumerate(self.playfield.grid): @@ -236,4 +270,8 @@ class Player: for row_idx, row in enumerate(self.current_piece.elements): for col_idx, element in enumerate(row): if element is not None: - self.grid_canvas.blit(element, ((col_idx + self.current_piece_position[1]) * 50 + 1, (row_idx + self.current_piece_position[0]) * 50 + 1)) + coordinates = Coordinates( + x = (col_idx + self.current_piece.coord.x) * 50 + 1, + y = (row_idx + self.current_piece.coord.y) * 50 + 1 + ) + self.grid_canvas.blit(element, (coordinates.x, coordinates.y)) -- cgit v1.2.3