diff --git a/NOTE.md b/NOTE.md index c80ca67..02547a2 100644 --- a/NOTE.md +++ b/NOTE.md @@ -8,3 +8,6 @@ A faire : Bug : - / + +Autre : +- Tester sur Linux \ No newline at end of file diff --git a/source/gui/scene/Game.py b/source/gui/scene/Game.py index 27d8c04..8296d4f 100644 --- a/source/gui/scene/Game.py +++ b/source/gui/scene/Game.py @@ -4,6 +4,7 @@ import pyglet from source.gui.scene.abc import Scene from source.gui import widget, texture +from source.gui.widget.grid import GameGridAlly, GameGridEnemy from source import core if TYPE_CHECKING: @@ -30,10 +31,12 @@ class Game(Scene): ) self.grid_ally = self.add_widget( - widget.GameGrid, + GameGridAlly, x=75, y=0.25, width=0.35, height=0.5, + boats_length=(5, 5, 4, 3, 2), + style=texture.Grid.Style1, rows=8, columns=8, @@ -43,7 +46,7 @@ class Game(Scene): ) self.grid_enemy = self.add_widget( - widget.GameGrid, + GameGridEnemy, x=lambda widget: widget.scene.window.width - 75 - widget.width, y=0.25, width=0.35, height=0.5, @@ -160,8 +163,11 @@ class Game(Scene): self.batch_button_background.draw() self.batch_input_background.draw() - self.batch_grid_background.draw() - self.batch_grid_line.draw() - self.batch_grid_cursor.draw() + # self.batch_grid_background.draw() + # self.batch_grid_line.draw() + # self.batch_grid_cursor.draw() self.batch_label.draw() + + self.grid_ally.draw() # DEBUG + self.grid_enemy.draw() # DEBUG diff --git a/source/gui/scene/MainMenu.py b/source/gui/scene/MainMenu.py index 4ca5746..ae77656 100644 --- a/source/gui/scene/MainMenu.py +++ b/source/gui/scene/MainMenu.py @@ -10,8 +10,8 @@ if TYPE_CHECKING: class MainMenu(Scene): - def __init__(self, window: "Window", *args, **kwargs): - super().__init__(window, *args, **kwargs) + def __init__(self, window: "Window", **kwargs): + super().__init__(window, **kwargs) self.batch_button_background = pyglet.graphics.Batch() self.batch_label = pyglet.graphics.Batch() diff --git a/source/gui/scene/RoomJoin.py b/source/gui/scene/RoomJoin.py index d16f714..84671a9 100644 --- a/source/gui/scene/RoomJoin.py +++ b/source/gui/scene/RoomJoin.py @@ -11,8 +11,8 @@ if TYPE_CHECKING: class RoomJoin(Scene): - def __init__(self, window: "Window", *args, **kwargs): - super().__init__(window, *args, **kwargs) + def __init__(self, window: "Window", **kwargs): + super().__init__(window, **kwargs) self.batch_button_background = pyglet.graphics.Batch() self.batch_input_background = pyglet.graphics.Batch() diff --git a/source/gui/scene/Settings.py b/source/gui/scene/Settings.py index 118427f..54543f9 100644 --- a/source/gui/scene/Settings.py +++ b/source/gui/scene/Settings.py @@ -44,6 +44,9 @@ class Settings(Scene): batch=self.batch_checkbox ) + self.checkbox.add_listener("on_click_release", + lambda *_: self.window.set_fullscreen(self.checkbox.state)) + self.scroller = self.add_widget( widget.Scroller, diff --git a/source/gui/scene/abc/Scene.py b/source/gui/scene/abc/Scene.py index 6ae9a69..eee2603 100644 --- a/source/gui/scene/abc/Scene.py +++ b/source/gui/scene/abc/Scene.py @@ -16,7 +16,7 @@ class Scene(ABC, EventPropagationMixin): It can react to any "on_" event from the window. """ - def __init__(self, window: "Window", *args, **kwargs): + def __init__(self, window: "Window", **kwargs): self.window = window self._widgets: list["Widget"] = list() @@ -28,17 +28,17 @@ class Scene(ABC, EventPropagationMixin): # Widget Managing - def add_widget(self, widget_class: Type["Widget"], **widget_kwargs): + def add_widget(self, widget_class: Type["Widget"], priority: int = 0, **widget_kwargs): """ Add a widget to the scene. :param widget_class: the class of the widget to add. - :param widget_args: args for the creation of the widget object. + :param priority: the priority of the widget. :param widget_kwargs: kwargs for the creation of the widget object. :return: the new created widget. """ widget: "Widget" = widget_class(self, **widget_kwargs) - self._widgets.append(widget) + self._widgets.insert(priority, widget) return widget def remove_widget(self, widget: "Widget") -> None: diff --git a/source/gui/texture/Grid.py b/source/gui/texture/Grid.py index eb1b0e1..6c69068 100644 --- a/source/gui/texture/Grid.py +++ b/source/gui/texture/Grid.py @@ -2,8 +2,15 @@ from . import _image_path from .abc import Style _image_path = _image_path + "grid/" +_image_boat_path = _image_path + "boat/" class Grid: class Style1(Style): background = _image_path + "background.png" + + class Boat: + class Style1(Style): + body = _image_boat_path + "body.png" + edge = _image_boat_path + "edge.png" + broken = _image_boat_path + "broken.png" diff --git a/source/gui/widget/__init__.py b/source/gui/widget/__init__.py index 4b98369..096854d 100644 --- a/source/gui/widget/__init__.py +++ b/source/gui/widget/__init__.py @@ -4,4 +4,3 @@ from .Input import Input from .Image import Image from .Checkbox import Checkbox from .Scroller import Scroller -from .GameGrid import GameGrid diff --git a/source/gui/widget/grid/GameGridAlly.py b/source/gui/widget/grid/GameGridAlly.py new file mode 100644 index 0000000..04ad2b7 --- /dev/null +++ b/source/gui/widget/grid/GameGridAlly.py @@ -0,0 +1,115 @@ +from typing import TYPE_CHECKING + +import pyglet +import numpy as np + +from source.core.enums import Orientation +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 + +if TYPE_CHECKING: + from source.gui.scene.abc import Scene + + +class GameGridAlly(GameGrid): + def __init__(self, scene: "Scene", boats_length: tuple[int, ...], **kwargs): + super().__init__(scene, **kwargs) + + self.orientation = False + self.boats_length = boats_length # the list of the size of the boats to place + + self.add_listener("on_hover", + lambda rel_x, rel_y: self.preview_boat(self.get_cell_from_rel(rel_x, rel_y), self.boats_length[0])) + + self.cell_sprites: list["Sprite"] = [] + self.boat_sprites_preview: list["Sprite"] = [] + + def draw_board(self, board: Board): + matrice = board.get_matrice() + + for (y, x), value in np.ndenumerate(matrice): + if value == 0: continue + + # calcul de la forme et de la rotation de cette cellule du bateau + + rotation = 0 + + # body + + if 0 < y < (self.rows-1) and matrice[y-1, x] == matrice[y+1, x] == value: # haut et bas + form = "body" + + elif 0 < x < (self.columns-1) and matrice[y, x-1] == matrice[y, x+1] == value: # droite et gauche + form = "body" + rotation = 90 + + # edge + + elif 0 < y and matrice[y-1, x] == value: # haut + form = "edge" + + elif y < (self.rows-1) and matrice[y+1, x] == value: # bas + form = "edge" + rotation = 180 + + elif 0 < x and matrice[y, x-1] == value: # gauche + form = "edge" + rotation = 90 + + elif x < (self.columns-1) and matrice[y, x+1] == value: # droite + form = "edge" + rotation = 270 + + else: # 1 piece boat + form = "solo" + + # calcul des décalages à cause de la rotation qui est faite par rapport à l'origine de l'image + offset_x = 0 if rotation < 180 else self.cell_width + offset_y = self.cell_height if 90 <= rotation <= 180 else 0 + width = self.cell_width if rotation % 180 == 0 else self.cell_height + height = self.cell_height if rotation % 180 == 0 else self.cell_width + + s = Sprite( + img=texture.Grid.Boat.Style1.get(form), + + x=self.x + (x * self.cell_width) + offset_x, + y=self.y + (y * self.cell_height) + offset_y, + width=int(width), + height=int(height), + ) + s.rotation = rotation + s.draw() + + def preview_boat(self, cell: tuple[int, int], length: int): + cell_x, cell_y = cell + + self.boat_sprites_preview = [] + + for i in range(length): + self.boat_sprites_preview.append( + Sprite( + img=texture.Grid.Boat.Style1.body, + + x=self.x + (cell_x * self.cell_width) + ((self.cell_width * i) if not self.orientation else 0), + y=self.y + (cell_y * self.cell_height) + ((self.cell_height * i) if self.orientation else 0), + width=int(self.cell_width), + height=int(self.cell_height), + ) + ) + + def swap_orientation(self): + self.orientation = not self.orientation + + 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() + + def on_draw(self): + b = Board(rows=self.rows, columns=self.columns) + b.add_boat(Boat(length=4, orientation=Orientation.VERTICAL), (0, 0)) + b.add_boat(Boat(length=5, orientation=Orientation.HORIZONTAL), (0, 1)) + b.add_boat(Boat(length=2, orientation=Orientation.HORIZONTAL), (0, 6)) + self.draw_board(b) + for boat_sprite in self.boat_sprites_preview: boat_sprite.draw() diff --git a/source/gui/widget/grid/GameGridEnemy.py b/source/gui/widget/grid/GameGridEnemy.py new file mode 100644 index 0000000..a0c8802 --- /dev/null +++ b/source/gui/widget/grid/GameGridEnemy.py @@ -0,0 +1,5 @@ +from source.gui.widget.grid.abc import GameGrid + + +class GameGridEnemy(GameGrid): + pass diff --git a/source/gui/widget/grid/__init__.py b/source/gui/widget/grid/__init__.py new file mode 100644 index 0000000..ad1f32c --- /dev/null +++ b/source/gui/widget/grid/__init__.py @@ -0,0 +1,2 @@ +from .GameGridAlly import GameGridAlly +from .GameGridEnemy import GameGridEnemy diff --git a/source/gui/widget/GameGrid.py b/source/gui/widget/grid/abc/GameGrid.py similarity index 81% rename from source/gui/widget/GameGrid.py rename to source/gui/widget/grid/abc/GameGrid.py index b647b2f..434baab 100644 --- a/source/gui/widget/GameGrid.py +++ b/source/gui/widget/grid/abc/GameGrid.py @@ -28,8 +28,8 @@ class GameGrid(BoxWidget): **kwargs): super().__init__(scene, x, y, width, height) - self._rows = rows - self._columns = columns + self.rows = rows + self.columns = columns self.style = style @@ -43,7 +43,7 @@ class GameGrid(BoxWidget): 0, 0, 0, 0, **dict_filter_prefix("line_", kwargs) ) - for _ in range((self._columns - 1) + (self._rows - 1)) + for _ in range((self.columns - 1) + (self.rows - 1)) ] self.cursor = pyglet.shapes.Rectangle( @@ -54,8 +54,8 @@ class GameGrid(BoxWidget): self.add_listener("on_hover_leave", lambda *_: self.hide_cursor()) self.add_listener("on_hover", self._refresh_cursor) - self.add_listener("on_click_release", - lambda rel_x, rel_y, *_: print("click", self.get_cell_from_rel(rel_x, rel_y))) + + self.add_listener("on_click_release", lambda rel_x, rel_y, *_: print("click", self.get_cell_from_rel(rel_x, rel_y))) self._refresh_size() @@ -72,13 +72,13 @@ class GameGrid(BoxWidget): self.background.x, self.background.y = self.xy self.background.width, self.background.height = self.size - for column, line in enumerate(self.lines[:self._columns-1], start=1): + for column, line in enumerate(self.lines[:self.columns - 1], start=1): line.x = self.x + self.cell_width * column line.x2 = line.x line.y = self.y line.y2 = self.y2 - for row, line in enumerate(self.lines[-self._rows+1:], start=1): + for row, line in enumerate(self.lines[-self.rows + 1:], start=1): line.x = self.x line.x2 = self.x2 line.y = self.y + self.cell_height * row @@ -87,8 +87,8 @@ class GameGrid(BoxWidget): def _refresh_cursor(self, rel_x: int, rel_y: int): cell_x, cell_y = self.get_cell_from_rel(rel_x, rel_y) - self.cursor.x = self.x + cell_x * self.width / self._columns - self.cursor.y = self.y + cell_y * self.height / self._rows + self.cursor.x = self.x + cell_x * self.width / self.columns + self.cursor.y = self.y + cell_y * self.height / self.rows self.cursor.width, self.cursor.height = self.cell_size def hide_cursor(self): @@ -98,11 +98,11 @@ class GameGrid(BoxWidget): @property def cell_width(self) -> float: - return self.width / self._columns + return self.width / self.columns @property def cell_height(self) -> float: - return self.height / self._rows + return self.height / self.rows @property def cell_size(self) -> tuple[float, float]: diff --git a/source/gui/widget/grid/abc/__init__.py b/source/gui/widget/grid/abc/__init__.py new file mode 100644 index 0000000..bc73df7 --- /dev/null +++ b/source/gui/widget/grid/abc/__init__.py @@ -0,0 +1 @@ +from .GameGrid import GameGrid diff --git a/source/gui/window/Window.py b/source/gui/window/Window.py index a386626..357091b 100644 --- a/source/gui/window/Window.py +++ b/source/gui/window/Window.py @@ -39,16 +39,15 @@ class Window(pyglet.window.Window, EventPropagationMixin): # NOQA self.clear_scene() return self.add_scene(scene_class, *scene_args, **scene_kwargs) - def add_scene(self, scene_class: Type["Scene"], priority: int = 0, *scene_args, **scene_kwargs) -> "Scene": + def add_scene(self, scene_class: Type["Scene"], priority: int = 0, **scene_kwargs) -> "Scene": """ Add a scene of the window. :scene_class: the class of the scene to add. - :scene_args: args for the creation of the scene object. :scene_kwargs: kwargs for the creation of the scene object. :return: the new created scene. """ - scene: "Scene" = scene_class(window=self, *scene_args, **scene_kwargs) + scene: "Scene" = scene_class(window=self, **scene_kwargs) self._scenes.insert(priority, scene) return scene diff --git a/source/network/Host.py b/source/network/Host.py index a9bf3a6..d27f283 100644 --- a/source/network/Host.py +++ b/source/network/Host.py @@ -30,7 +30,7 @@ class Host(Thread): with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind(("", self.port)) # connecte le socket au port indiqué - s.settimeout(5) # defini le timeout à 5 secondes + s.settimeout(5) # défini le timeout à 5 secondes s.listen() # écoute de nouvelle connexion while True: