simplified and added the possibility to place boat with the given boat size list on the grid

This commit is contained in:
Faraphel 2023-02-20 23:25:26 +01:00
parent b9e087d1fd
commit 930947aded
5 changed files with 92 additions and 79 deletions

10
NOTE.md
View file

@ -10,4 +10,12 @@ Bug :
- / - /
Autre : Autre :
- Tester sur Linux - Tester sur Linux
Bonus ultime :
- Envoyer la texture de la grille à l'adversaire

View file

@ -144,11 +144,10 @@ class Board:
if __name__ == "__main__": if __name__ == "__main__":
board = Board(5) board = Board(5)
board.add_boat(Boat(3, Orientation.VERTICAL), (0, 4)) board.add_boat(Boat(3, Orientation.VERTICAL), (4, 0))
board.add_boat(Boat(4, Orientation.HORIZONTAL), (4, 1)) board.add_boat(Boat(4, Orientation.HORIZONTAL), (1, 4))
print(board.bomb((4, 1))) print(board.bomb((4, 1)))
print(board.bomb((4, 2))) print(board.bomb((4, 2)))
print(board.bomb((4, 3))) print(board.bomb((4, 3)))
print(board.bomb((4, 4))) print(board.bomb((4, 4)))
print(board) print(board)

View file

@ -35,7 +35,7 @@ class Game(Scene):
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), boats_length=[5, 5, 4, 3, 2],
style=texture.Grid.Style1, style=texture.Grid.Style1,
rows=8, columns=8, rows=8, columns=8,

View file

@ -14,3 +14,4 @@ class Grid:
body = _image_boat_path + "body.png" body = _image_boat_path + "body.png"
edge = _image_boat_path + "edge.png" edge = _image_boat_path + "edge.png"
broken = _image_boat_path + "broken.png" broken = _image_boat_path + "broken.png"
solo = _image_boat_path + "solo.png"

View file

@ -4,112 +4,117 @@ import pyglet
import numpy as np import numpy as np
from source.core.enums import Orientation from source.core.enums import Orientation
from source.core.error import InvalidBoatPosition
from source.gui import texture from source.gui import texture
from source.gui.sprite import Sprite from source.gui.sprite import Sprite
from source.gui.widget.grid.abc import GameGrid from source.gui.widget.grid.abc import GameGrid
from source.core import Board, Boat from source.core import Board, Boat
from source.type import Point2D
from source.utils import dict_filter_prefix
if TYPE_CHECKING: if TYPE_CHECKING:
from source.gui.scene.abc import Scene from source.gui.scene.abc import Scene
class GameGridAlly(GameGrid): class GameGridAlly(GameGrid):
def __init__(self, scene: "Scene", boats_length: tuple[int, ...], **kwargs): def __init__(self, scene: "Scene", boats_length: list[int], **kwargs):
self.cell_sprites: dict[Point2D, "Sprite"] = {}
super().__init__(scene, **kwargs) super().__init__(scene, **kwargs)
self.orientation = False self.orientation: Orientation = Orientation.HORIZONTAL
self.boats_length = boats_length # the list of the size of the boats to place self.boats_length = boats_length # the list of the size of the boats to place
self.board = Board(rows=self.rows, columns=self.columns)
self.add_listener("on_hover", self._cell_kwargs = dict_filter_prefix("cell_", kwargs)
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"] = [] # refresh
self.boat_sprites_preview: list["Sprite"] = [] def _refresh_size(self):
super()._refresh_size()
def draw_board(self, board: Board): for (x, y), sprite in self.cell_sprites.items():
matrice = board.get_matrice()
# calcul des décalages à cause de la rotation qui est faite par rapport à l'origine de l'image
offset_x = 0 if sprite.rotation <= 90 else self.cell_width
offset_y = self.cell_height if 90 <= sprite.rotation <= 180 else 0
width, height = (
(self.cell_width, self.cell_height) if sprite.rotation % 180 == 0 else
(self.cell_height, self.cell_width)
)
sprite.x = self.x + (x * self.cell_width) + offset_x
sprite.y = self.y + (y * self.cell_height) + offset_y
sprite.width = width
sprite.height = height
def _refresh_board(self):
self.cell_sprites: dict[Point2D, "Sprite"] = {}
matrice = self.board.get_matrice()
for (y, x), value in np.ndenumerate(matrice): for (y, x), value in np.ndenumerate(matrice):
if value == 0: continue if value == 0: continue
# calcul de la forme et de la rotation de cette cellule du bateau # calcul de la forme et de la rotation de cette cellule du bateau
rotation = 0 form, rotation = (
# corps
("body", 0) if 0 < y < (self.rows-1) and matrice[y-1, x] == matrice[y+1, x] == value else # colonne
("body", 1) if 0 < x < (self.columns-1) and matrice[y, x-1] == matrice[y, x+1] == value else # ligne
# body # bordure
("edge", 0) if 0 < y and matrice[y-1, x] == value else # bas
("edge", 1) if 0 < x and matrice[y, x-1] == value else # droite
("edge", 2) if y < (self.rows-1) and matrice[y+1, x] == value else # haut
("edge", 3) if x < (self.columns-1) and matrice[y, x+1] == value else # gauche
if 0 < y < (self.rows-1) and matrice[y-1, x] == matrice[y+1, x] == value: # haut et bas # aucune bordure (bateau de taille 1)
form = "body" ("solo", 0)
)
elif 0 < x < (self.columns-1) and matrice[y, x-1] == matrice[y, x+1] == value: # droite et gauche sprite = Sprite(
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), img=texture.Grid.Boat.Style1.get(form),
**self._cell_kwargs
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 sprite.rotation = rotation * 90
s.draw()
def preview_boat(self, cell: tuple[int, int], length: int): self.cell_sprites[(x, y)] = sprite
cell_x, cell_y = cell
self.boat_sprites_preview = [] self._refresh_size()
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): def swap_orientation(self):
self.orientation = not self.orientation self.orientation = (
Orientation.HORIZONTAL if self.orientation is Orientation.VERTICAL else
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)
try:
self.board.add_boat(
Boat(self.boats_length[0], orientation=self.orientation),
(cell_x, cell_y)
)
except InvalidBoatPosition:
return
else:
self.boats_length.pop(0)
self._refresh_board()
def on_mouse_release(self, x: int, y: int, button: int, modifiers: int): def on_mouse_release(self, x: int, y: int, button: int, modifiers: int):
super().on_mouse_release(x, y, button, modifiers) super().on_mouse_release(x, y, button, modifiers)
if button == pyglet.window.mouse.RIGHT: self.swap_orientation()
def on_draw(self): if button == pyglet.window.mouse.RIGHT: self.swap_orientation()
b = Board(rows=self.rows, columns=self.columns) if button == pyglet.window.mouse.LEFT: self.place_boat(x, y)
b.add_boat(Boat(length=4, orientation=Orientation.VERTICAL), (0, 0))
b.add_boat(Boat(length=5, orientation=Orientation.HORIZONTAL), (0, 1)) def draw(self):
b.add_boat(Boat(length=2, orientation=Orientation.HORIZONTAL), (0, 6)) super().draw()
self.draw_board(b) for sprite in self.cell_sprites.values():
for boat_sprite in self.boat_sprites_preview: boat_sprite.draw() sprite.draw()