added a function to render board on the grid (unoptimised !!!)

This commit is contained in:
Faraphel 2023-02-20 15:21:43 +01:00
parent 8a385a75bf
commit 39d44e7ec2
15 changed files with 169 additions and 29 deletions

View file

@ -8,3 +8,6 @@ A faire :
Bug : Bug :
- / - /
Autre :
- Tester sur Linux

View file

@ -4,6 +4,7 @@ import pyglet
from source.gui.scene.abc import Scene from source.gui.scene.abc import Scene
from source.gui import widget, texture from source.gui import widget, texture
from source.gui.widget.grid import GameGridAlly, GameGridEnemy
from source import core from source import core
if TYPE_CHECKING: if TYPE_CHECKING:
@ -30,10 +31,12 @@ class Game(Scene):
) )
self.grid_ally = self.add_widget( self.grid_ally = self.add_widget(
widget.GameGrid, GameGridAlly,
x=75, y=0.25, width=0.35, height=0.5, x=75, y=0.25, width=0.35, height=0.5,
boats_length=(5, 5, 4, 3, 2),
style=texture.Grid.Style1, style=texture.Grid.Style1,
rows=8, columns=8, rows=8, columns=8,
@ -43,7 +46,7 @@ class Game(Scene):
) )
self.grid_enemy = self.add_widget( 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, 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_button_background.draw()
self.batch_input_background.draw() self.batch_input_background.draw()
self.batch_grid_background.draw() # self.batch_grid_background.draw()
self.batch_grid_line.draw() # self.batch_grid_line.draw()
self.batch_grid_cursor.draw() # self.batch_grid_cursor.draw()
self.batch_label.draw() self.batch_label.draw()
self.grid_ally.draw() # DEBUG
self.grid_enemy.draw() # DEBUG

View file

@ -10,8 +10,8 @@ if TYPE_CHECKING:
class MainMenu(Scene): class MainMenu(Scene):
def __init__(self, window: "Window", *args, **kwargs): def __init__(self, window: "Window", **kwargs):
super().__init__(window, *args, **kwargs) super().__init__(window, **kwargs)
self.batch_button_background = pyglet.graphics.Batch() self.batch_button_background = pyglet.graphics.Batch()
self.batch_label = pyglet.graphics.Batch() self.batch_label = pyglet.graphics.Batch()

View file

@ -11,8 +11,8 @@ if TYPE_CHECKING:
class RoomJoin(Scene): class RoomJoin(Scene):
def __init__(self, window: "Window", *args, **kwargs): def __init__(self, window: "Window", **kwargs):
super().__init__(window, *args, **kwargs) super().__init__(window, **kwargs)
self.batch_button_background = pyglet.graphics.Batch() self.batch_button_background = pyglet.graphics.Batch()
self.batch_input_background = pyglet.graphics.Batch() self.batch_input_background = pyglet.graphics.Batch()

View file

@ -44,6 +44,9 @@ class Settings(Scene):
batch=self.batch_checkbox batch=self.batch_checkbox
) )
self.checkbox.add_listener("on_click_release",
lambda *_: self.window.set_fullscreen(self.checkbox.state))
self.scroller = self.add_widget( self.scroller = self.add_widget(
widget.Scroller, widget.Scroller,

View file

@ -16,7 +16,7 @@ class Scene(ABC, EventPropagationMixin):
It can react to any "on_" event from the window. 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.window = window
self._widgets: list["Widget"] = list() self._widgets: list["Widget"] = list()
@ -28,17 +28,17 @@ class Scene(ABC, EventPropagationMixin):
# Widget Managing # 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. Add a widget to the scene.
:param widget_class: the class of the widget to add. :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. :param widget_kwargs: kwargs for the creation of the widget object.
:return: the new created widget. :return: the new created widget.
""" """
widget: "Widget" = widget_class(self, **widget_kwargs) widget: "Widget" = widget_class(self, **widget_kwargs)
self._widgets.append(widget) self._widgets.insert(priority, widget)
return widget return widget
def remove_widget(self, widget: "Widget") -> None: def remove_widget(self, widget: "Widget") -> None:

View file

@ -2,8 +2,15 @@ from . import _image_path
from .abc import Style from .abc import Style
_image_path = _image_path + "grid/" _image_path = _image_path + "grid/"
_image_boat_path = _image_path + "boat/"
class Grid: class Grid:
class Style1(Style): class Style1(Style):
background = _image_path + "background.png" 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"

View file

@ -4,4 +4,3 @@ from .Input import Input
from .Image import Image from .Image import Image
from .Checkbox import Checkbox from .Checkbox import Checkbox
from .Scroller import Scroller from .Scroller import Scroller
from .GameGrid import GameGrid

View file

@ -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()

View file

@ -0,0 +1,5 @@
from source.gui.widget.grid.abc import GameGrid
class GameGridEnemy(GameGrid):
pass

View file

@ -0,0 +1,2 @@
from .GameGridAlly import GameGridAlly
from .GameGridEnemy import GameGridEnemy

View file

@ -28,8 +28,8 @@ class GameGrid(BoxWidget):
**kwargs): **kwargs):
super().__init__(scene, x, y, width, height) super().__init__(scene, x, y, width, height)
self._rows = rows self.rows = rows
self._columns = columns self.columns = columns
self.style = style self.style = style
@ -43,7 +43,7 @@ class GameGrid(BoxWidget):
0, 0, 0, 0, 0, 0, 0, 0,
**dict_filter_prefix("line_", kwargs) **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( 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_leave", lambda *_: self.hide_cursor())
self.add_listener("on_hover", self._refresh_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() self._refresh_size()
@ -72,13 +72,13 @@ class GameGrid(BoxWidget):
self.background.x, self.background.y = self.xy self.background.x, self.background.y = self.xy
self.background.width, self.background.height = self.size 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.x = self.x + self.cell_width * column
line.x2 = line.x line.x2 = line.x
line.y = self.y line.y = self.y
line.y2 = self.y2 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.x = self.x
line.x2 = self.x2 line.x2 = self.x2
line.y = self.y + self.cell_height * row 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): def _refresh_cursor(self, rel_x: int, rel_y: int):
cell_x, cell_y = self.get_cell_from_rel(rel_x, rel_y) 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.x = self.x + cell_x * self.width / self.columns
self.cursor.y = self.y + cell_y * self.height / self._rows self.cursor.y = self.y + cell_y * self.height / self.rows
self.cursor.width, self.cursor.height = self.cell_size self.cursor.width, self.cursor.height = self.cell_size
def hide_cursor(self): def hide_cursor(self):
@ -98,11 +98,11 @@ class GameGrid(BoxWidget):
@property @property
def cell_width(self) -> float: def cell_width(self) -> float:
return self.width / self._columns return self.width / self.columns
@property @property
def cell_height(self) -> float: def cell_height(self) -> float:
return self.height / self._rows return self.height / self.rows
@property @property
def cell_size(self) -> tuple[float, float]: def cell_size(self) -> tuple[float, float]:

View file

@ -0,0 +1 @@
from .GameGrid import GameGrid

View file

@ -39,16 +39,15 @@ class Window(pyglet.window.Window, EventPropagationMixin): # NOQA
self.clear_scene() self.clear_scene()
return self.add_scene(scene_class, *scene_args, **scene_kwargs) 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. Add a scene of the window.
:scene_class: the class of the scene to add. :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. :scene_kwargs: kwargs for the creation of the scene object.
:return: the new created scene. :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) self._scenes.insert(priority, scene)
return scene return scene

View file

@ -30,7 +30,7 @@ class Host(Thread):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind(("", self.port)) # connecte le socket au port indiqué 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 s.listen() # écoute de nouvelle connexion
while True: while True: