diff --git a/NOTE.md b/NOTE.md index a16cc19..5cb4be6 100644 --- a/NOTE.md +++ b/NOTE.md @@ -1,9 +1,9 @@ A faire : +- Prévisualisation des bateaux sur la grille avant de placer - Ecran de configuration de la partie - Nom dans les options -- Prévisualisation des bateaux sur la grille -- Faire une scène incluant par défaut les boutons "Retour" +- Faire une scène incluant par défaut les boutons "Retour" (?) - Police d'écriture Bug : diff --git a/source/core/Board.py b/source/core/Board.py index 2a36d7d..d7b7ef0 100644 --- a/source/core/Board.py +++ b/source/core/Board.py @@ -141,6 +141,14 @@ class Board: bombs=np.array(json_["bombs"], dtype=np.bool_) ) + def __copy__(self): + return self.__class__( + rows=self._rows, + columns=self._columns, + boats=self._boats.copy(), + bombs=self._bombs.copy(), + ) + if __name__ == "__main__": board = Board(5) diff --git a/source/gui/widget/grid/GameGridAlly.py b/source/gui/widget/grid/GameGridAlly.py index a66d5ea..5cecffb 100644 --- a/source/gui/widget/grid/GameGridAlly.py +++ b/source/gui/widget/grid/GameGridAlly.py @@ -1,3 +1,4 @@ +from copy import copy from typing import TYPE_CHECKING import pyglet @@ -9,7 +10,7 @@ from source.gui import texture from source.gui.sprite import Sprite from source.gui.widget.grid.abc import GameGrid from source.core import Board, Boat -from source.type import Point2D +from source.type import Point2D, ColorRGB from source.utils import dict_filter_prefix if TYPE_CHECKING: @@ -17,14 +18,21 @@ if TYPE_CHECKING: class GameGridAlly(GameGrid): - def __init__(self, scene: "Scene", boats_length: list[int], **kwargs): + def __init__(self, scene: "Scene", + + boats_length: list[int], + preview_color: ColorRGB = (150, 255, 150), + + **kwargs): self.cell_sprites: dict[Point2D, "Sprite"] = {} super().__init__(scene, **kwargs) - self.orientation: Orientation = Orientation.HORIZONTAL self.boats_length = boats_length # the list of the size of the boats to place + self.preview_color = preview_color + self.board = Board(rows=self.rows, columns=self.columns) + self.orientation: Orientation = Orientation.HORIZONTAL self._cell_kwargs = dict_filter_prefix("cell_", kwargs) @@ -49,10 +57,11 @@ class GameGridAlly(GameGrid): sprite.width = width sprite.height = height - def _refresh_board(self): + def display_board(self, board: Board, preview: bool = False): self.cell_sprites: dict[Point2D, "Sprite"] = {} - matrice = self.board.get_matrice() + matrice = board.get_matrice() + max_boat: int = matrice.max() for (y, x), value in np.ndenumerate(matrice): if value == 0: continue @@ -80,6 +89,9 @@ class GameGridAlly(GameGrid): ) sprite.rotation = rotation * 90 + if preview and value == max_boat: # if in preview and it is the latest boat + sprite.color = self.preview_color # make the image more greenish + self.cell_sprites[(x, y)] = sprite self._refresh_size() @@ -90,31 +102,58 @@ class GameGridAlly(GameGrid): Orientation.VERTICAL ) - def place_boat(self, x, y): - rel_x, rel_y = x - self.x, y - self.y - cell_x, cell_y = self.get_cell_from_rel(rel_x, rel_y) + def place_boat(self, cell: Point2D): + if len(self.boats_length) == 0: return try: self.board.add_boat( Boat(self.boats_length[0], orientation=self.orientation), - (cell_x, cell_y) + cell + ) + except InvalidBoatPosition: pass # if the boat can't be placed, ignore + + else: # if the boat have been placed + self.boats_length.pop(0) # remove the boat from the list of boat to place + + self.display_board(self.board) + + def preview_boat(self, cell: Point2D): + if len(self.boats_length) == 0: return + + try: + preview_board = copy(self.board) + preview_board.add_boat( + Boat(self.boats_length[0], orientation=self.orientation), + cell ) - except InvalidBoatPosition: - return - - else: - self.boats_length.pop(0) - - self._refresh_board() + except InvalidBoatPosition: self.display_board(self.board) # if the boat can't be placed, ignore + else: self.display_board(preview_board, preview=True) def on_mouse_release(self, x: int, y: int, button: int, modifiers: int): super().on_mouse_release(x, y, button, modifiers) - if button == pyglet.window.mouse.RIGHT: self.swap_orientation() - if button == pyglet.window.mouse.LEFT: self.place_boat(x, y) + rel_x, rel_y = x - self.x, y - self.y + cell = self.get_cell_from_rel(rel_x, rel_y) + + match button: + case pyglet.window.mouse.RIGHT: + self.swap_orientation() + self.preview_boat(cell) + + case pyglet.window.mouse.LEFT: + self.place_boat(cell) + + def on_mouse_motion(self, x: int, y: int, dx: int, dy: int): + super().on_mouse_motion(x, y, dx, dy) + + rel_x, rel_y = x - self.x, y - self.y + cell = self.get_cell_from_rel(rel_x, rel_y) + + self.preview_boat(cell) def draw(self): - super().draw() - for sprite in self.cell_sprites.values(): - sprite.draw() + self.background.draw() + for sprite in self.cell_sprites.values(): sprite.draw() + self.cursor.draw() + for line in self.lines: line.draw() diff --git a/source/gui/widget/grid/abc/GameGrid.py b/source/gui/widget/grid/abc/GameGrid.py index 434baab..512c4bd 100644 --- a/source/gui/widget/grid/abc/GameGrid.py +++ b/source/gui/widget/grid/abc/GameGrid.py @@ -64,7 +64,10 @@ class GameGrid(BoxWidget): Return the cell of the grid from a point relative position """ - return int(rel_x / self.cell_width), int(rel_y / self.cell_height) + return ( + int((rel_x-1) / self.cell_width), + int((rel_y-1) / self.cell_height) + ) # refresh diff --git a/source/gui/window/GameWindow.py b/source/gui/window/GameWindow.py index 65ff7fa..0f505f7 100644 --- a/source/gui/window/GameWindow.py +++ b/source/gui/window/GameWindow.py @@ -1,7 +1,7 @@ import pyglet.window from source.gui.window import Window -from source.type import Color +from source.type import ColorRGBA class GameWindow(Window): # NOQA @@ -11,7 +11,7 @@ class GameWindow(Window): # NOQA def __init__(self, - fps_color: Color = (255, 255, 255, 200), + fps_color: ColorRGBA = (255, 255, 255, 200), fps_enable: bool = True, *args, **kwargs): diff --git a/source/type.py b/source/type.py index c3c929d..c0488da 100644 --- a/source/type.py +++ b/source/type.py @@ -3,7 +3,8 @@ from typing import Union, Callable, Any Point2D = tuple[int, int] BBox = tuple[int, int, int, int] Percentage = float # a percentage, represented as a number between 0 and 1 -Color = tuple[int, int, int, int] +ColorRGB = tuple[int, int, int] +ColorRGBA = tuple[int, int, int, int] DistanceFunction = Callable[[Any], int] # a function that return a distance # a distance, represented either by a whole number, a percentage or a function