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 :
- 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__":
board = Board(5)
board.add_boat(Boat(3, Orientation.VERTICAL), (0, 4))
board.add_boat(Boat(4, Orientation.HORIZONTAL), (4, 1))
board.add_boat(Boat(3, Orientation.VERTICAL), (4, 0))
board.add_boat(Boat(4, Orientation.HORIZONTAL), (1, 4))
print(board.bomb((4, 1)))
print(board.bomb((4, 2)))
print(board.bomb((4, 3)))
print(board.bomb((4, 4)))
print(board)

View file

@ -35,7 +35,7 @@ class Game(Scene):
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,
rows=8, columns=8,

View file

@ -14,3 +14,4 @@ class Grid:
body = _image_boat_path + "body.png"
edge = _image_boat_path + "edge.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
from source.core.enums import Orientation
from source.core.error import InvalidBoatPosition
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.utils import dict_filter_prefix
if TYPE_CHECKING:
from source.gui.scene.abc import Scene
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)
self.orientation = False
self.orientation: Orientation = Orientation.HORIZONTAL
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",
lambda rel_x, rel_y: self.preview_boat(self.get_cell_from_rel(rel_x, rel_y), self.boats_length[0]))
self._cell_kwargs = dict_filter_prefix("cell_", kwargs)
self.cell_sprites: list["Sprite"] = []
self.boat_sprites_preview: list["Sprite"] = []
# refresh
def _refresh_size(self):
super()._refresh_size()
def draw_board(self, board: Board):
matrice = board.get_matrice()
for (x, y), sprite in self.cell_sprites.items():
# 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):
if value == 0: continue
# 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
form = "body"
# aucune bordure (bateau de taille 1)
("solo", 0)
)
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(
sprite = 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),
**self._cell_kwargs
)
s.rotation = rotation
s.draw()
sprite.rotation = rotation * 90
def preview_boat(self, cell: tuple[int, int], length: int):
cell_x, cell_y = cell
self.cell_sprites[(x, y)] = sprite
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),
)
)
self._refresh_size()
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):
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()
if button == pyglet.window.mouse.RIGHT: self.swap_orientation()
if button == pyglet.window.mouse.LEFT: self.place_boat(x, y)
def draw(self):
super().draw()
for sprite in self.cell_sprites.values():
sprite.draw()