unified GameGridAlly and GameGridEnemy
This commit is contained in:
parent
db21bf5e04
commit
a096785c28
8 changed files with 110 additions and 209 deletions
2
NOTE.md
2
NOTE.md
|
@ -7,9 +7,9 @@ A faire :
|
||||||
|
|
||||||
- Voir si les event listener intégré à pyglet sont plus pratique que l'event propagation
|
- Voir si les event listener intégré à pyglet sont plus pratique que l'event propagation
|
||||||
- Documenter
|
- Documenter
|
||||||
|
- Ajouter plus d'event sur les widgets
|
||||||
|
|
||||||
- Ecran de victoire
|
- Ecran de victoire
|
||||||
- Affichage des coups de l'opposant
|
|
||||||
- Faire marcher le tchat
|
- Faire marcher le tchat
|
||||||
- Sauvegarde / Quitter
|
- Sauvegarde / Quitter
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ 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
|
||||||
from source.network.packet import PacketChat, PacketBombPlaced, PacketBoatPlaced
|
from source.network.packet import PacketChat, PacketBombPlaced, PacketBoatPlaced
|
||||||
from source.type import Point2D
|
from source.type import Point2D
|
||||||
|
@ -38,7 +37,7 @@ class Game(Scene):
|
||||||
)
|
)
|
||||||
|
|
||||||
self.grid_ally = self.add_widget(
|
self.grid_ally = self.add_widget(
|
||||||
GameGridAlly,
|
widget.GameGrid,
|
||||||
|
|
||||||
x=75, y=0.25, width=0.35, height=0.5,
|
x=75, y=0.25, width=0.35, height=0.5,
|
||||||
|
|
||||||
|
@ -63,17 +62,19 @@ class Game(Scene):
|
||||||
self.grid_ally.add_listener("on_all_boats_placed", board_ally_ready)
|
self.grid_ally.add_listener("on_all_boats_placed", board_ally_ready)
|
||||||
|
|
||||||
self.grid_enemy = self.add_widget(
|
self.grid_enemy = self.add_widget(
|
||||||
GameGridEnemy,
|
widget.GameGrid,
|
||||||
|
|
||||||
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,
|
||||||
|
|
||||||
grid_style=texture.Grid.Style1,
|
grid_style=texture.Grid.Style1,
|
||||||
|
boat_style=texture.Grid.Boat.Style1,
|
||||||
bomb_style=texture.Grid.Bomb.Style1,
|
bomb_style=texture.Grid.Bomb.Style1,
|
||||||
rows=8, columns=8,
|
rows=8, columns=8,
|
||||||
|
|
||||||
background_batch=self.batch_grid_background,
|
background_batch=self.batch_grid_background,
|
||||||
line_batch=self.batch_grid_line,
|
line_batch=self.batch_grid_line,
|
||||||
cursor_batch=self.batch_grid_cursor,
|
cursor_batch=self.batch_grid_cursor,
|
||||||
|
boat_batch=self.batch_grid_boat,
|
||||||
bomb_batch=self.batch_grid_bomb
|
bomb_batch=self.batch_grid_bomb
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
from copy import copy
|
from copy import copy
|
||||||
from typing import TYPE_CHECKING, Type
|
from typing import TYPE_CHECKING, Type
|
||||||
|
|
||||||
import pyglet
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
import pyglet.shapes
|
||||||
|
|
||||||
|
from source.core import Board, Boat
|
||||||
from source.core.enums import Orientation
|
from source.core.enums import Orientation
|
||||||
from source.core.error import InvalidBoatPosition
|
from source.core.error import InvalidBoatPosition
|
||||||
from source.gui.sprite import Sprite
|
from source.gui.sprite import Sprite
|
||||||
from source.gui.texture.abc import Style
|
from source.gui.texture.abc import Style
|
||||||
from source.gui.widget.grid.abc import GameGrid
|
from source.gui.widget.abc import BoxWidget
|
||||||
from source.core import Board, Boat
|
from source.type import Distance, ColorRGB, Point2D
|
||||||
from source.type import Point2D, ColorRGB
|
|
||||||
from source.utils import dict_filter_prefix
|
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 GameGrid(BoxWidget):
|
||||||
"""
|
"""
|
||||||
A game grid that represent the ally grid.
|
A widget that represent a game grid.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, scene: "Scene",
|
def __init__(self, scene: "Scene",
|
||||||
|
@ -31,15 +31,23 @@ class GameGridAlly(GameGrid):
|
||||||
boat_style: Type[Style],
|
boat_style: Type[Style],
|
||||||
bomb_style: Type[Style],
|
bomb_style: Type[Style],
|
||||||
|
|
||||||
boats_length: list[int],
|
x: Distance = 0,
|
||||||
|
y: Distance = 0,
|
||||||
|
width: Distance = None,
|
||||||
|
height: Distance = None,
|
||||||
|
|
||||||
preview_color: ColorRGB = (150, 255, 150),
|
preview_color: ColorRGB = (150, 255, 150),
|
||||||
|
boats_length: list[int] = None,
|
||||||
|
|
||||||
**kwargs):
|
**kwargs):
|
||||||
self.cell_sprites: dict[Point2D, "Sprite"] = {}
|
self.cell_sprites: dict[Point2D, "Sprite"] = {}
|
||||||
|
|
||||||
super().__init__(scene, rows, columns, grid_style, **kwargs)
|
super().__init__(scene, x, y, width, height)
|
||||||
|
|
||||||
self.boats_length = boats_length # the list of the size of the boats to place
|
self.rows = rows
|
||||||
|
self.columns = columns
|
||||||
|
|
||||||
|
self.boats_length = [] if boats_length is None else boats_length # the list of the size of the boats to place
|
||||||
self.preview_color = preview_color
|
self.preview_color = preview_color
|
||||||
|
|
||||||
self.board = Board(rows=self.rows, columns=self.columns)
|
self.board = Board(rows=self.rows, columns=self.columns)
|
||||||
|
@ -47,19 +55,69 @@ class GameGridAlly(GameGrid):
|
||||||
|
|
||||||
self._boat_kwargs = dict_filter_prefix("boat_", kwargs)
|
self._boat_kwargs = dict_filter_prefix("boat_", kwargs)
|
||||||
self._bomb_kwargs = dict_filter_prefix("bomb_", kwargs)
|
self._bomb_kwargs = dict_filter_prefix("bomb_", kwargs)
|
||||||
|
self.grid_style = grid_style
|
||||||
self.boat_style = boat_style
|
self.boat_style = boat_style
|
||||||
self.bomb_style = bomb_style
|
self.bomb_style = bomb_style
|
||||||
|
|
||||||
|
self.background = Sprite(
|
||||||
|
img=grid_style.get("background"),
|
||||||
|
**dict_filter_prefix("background_", kwargs)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.lines: list[pyglet.shapes.Line] = [
|
||||||
|
pyglet.shapes.Line(
|
||||||
|
0, 0, 0, 0,
|
||||||
|
**dict_filter_prefix("line_", kwargs)
|
||||||
|
)
|
||||||
|
for _ in range((self.columns - 1) + (self.rows - 1))
|
||||||
|
]
|
||||||
|
|
||||||
|
self.cursor = pyglet.shapes.Rectangle(
|
||||||
|
0, 0, 0, 0,
|
||||||
|
color=(0, 0, 0, 100),
|
||||||
|
**dict_filter_prefix("cursor_", kwargs)
|
||||||
|
)
|
||||||
|
|
||||||
self.add_listener("on_click_release", self.on_click_release)
|
self.add_listener("on_click_release", self.on_click_release)
|
||||||
self.add_listener("on_hover", lambda rel_x, rel_y: self.preview_boat(self.get_cell_from_rel(rel_x, rel_y)))
|
self.add_listener("on_hover_leave", lambda *_: self.hide_cursor())
|
||||||
|
self.add_listener("on_hover", self._refresh_cursor)
|
||||||
|
|
||||||
|
|
||||||
|
self._refresh_size()
|
||||||
|
|
||||||
|
def get_cell_from_rel(self, rel_x: int, rel_y: int) -> tuple[int, int]:
|
||||||
|
"""
|
||||||
|
Return the cell of the grid from a point relative position
|
||||||
|
"""
|
||||||
|
|
||||||
|
return (
|
||||||
|
int((rel_x-1) / self.cell_width),
|
||||||
|
int((rel_y-1) / self.cell_height)
|
||||||
|
)
|
||||||
|
|
||||||
# refresh
|
# refresh
|
||||||
|
|
||||||
def _refresh_size(self):
|
def _refresh_size(self):
|
||||||
super()._refresh_size()
|
self.background.x, self.background.y = self.xy
|
||||||
|
self.background.width, self.background.height = self.size
|
||||||
|
|
||||||
|
# lines
|
||||||
|
|
||||||
|
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):
|
||||||
|
line.x = self.x
|
||||||
|
line.x2 = self.x2
|
||||||
|
line.y = self.y + self.cell_height * row
|
||||||
|
line.y2 = line.y
|
||||||
|
|
||||||
|
# sprites
|
||||||
|
|
||||||
for (x, y), sprite in self.cell_sprites.items():
|
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
|
# 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_x = 0 if sprite.rotation <= 90 else self.cell_width
|
||||||
|
@ -75,6 +133,20 @@ class GameGridAlly(GameGrid):
|
||||||
sprite.width = width
|
sprite.width = width
|
||||||
sprite.height = height
|
sprite.height = height
|
||||||
|
|
||||||
|
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.width, self.cursor.height = self.cell_size
|
||||||
|
|
||||||
|
self.preview_boat((cell_x, cell_y)) # display the previsualisation of the boat on this cell
|
||||||
|
|
||||||
|
# function
|
||||||
|
|
||||||
|
def hide_cursor(self):
|
||||||
|
self.cursor.width, self.cursor.height = 0, 0
|
||||||
|
|
||||||
def display_board(self, board: Board, preview: bool = False):
|
def display_board(self, board: Board, preview: bool = False):
|
||||||
self.cell_sprites: dict[Point2D, "Sprite"] = {}
|
self.cell_sprites: dict[Point2D, "Sprite"] = {}
|
||||||
|
|
||||||
|
@ -151,7 +223,6 @@ class GameGridAlly(GameGrid):
|
||||||
else: self.display_board(preview_board, preview=True)
|
else: self.display_board(preview_board, preview=True)
|
||||||
|
|
||||||
def place_bomb(self, cell: Point2D, touched: bool):
|
def place_bomb(self, cell: Point2D, touched: bool):
|
||||||
|
|
||||||
self.cell_sprites[cell] = Sprite(
|
self.cell_sprites[cell] = Sprite(
|
||||||
img=self.bomb_style.get("touched" if touched else "missed"),
|
img=self.bomb_style.get("touched" if touched else "missed"),
|
||||||
**self._bomb_kwargs
|
**self._bomb_kwargs
|
||||||
|
@ -169,6 +240,26 @@ class GameGridAlly(GameGrid):
|
||||||
|
|
||||||
case pyglet.window.mouse.LEFT:
|
case pyglet.window.mouse.LEFT:
|
||||||
self.place_boat(cell)
|
self.place_boat(cell)
|
||||||
|
self.trigger_event("on_request_place_bomb", cell)
|
||||||
|
|
||||||
|
# property
|
||||||
|
|
||||||
|
@property
|
||||||
|
def cell_width(self) -> float:
|
||||||
|
return self.width / self.columns
|
||||||
|
|
||||||
|
@property
|
||||||
|
def cell_height(self) -> float:
|
||||||
|
return self.height / self.rows
|
||||||
|
|
||||||
|
@property
|
||||||
|
def cell_size(self) -> tuple[float, float]:
|
||||||
|
return self.cell_width, self.cell_height
|
||||||
|
|
||||||
|
# event
|
||||||
|
|
||||||
|
def on_resize(self, width: int, height: int):
|
||||||
|
self._refresh_size()
|
||||||
|
|
||||||
def draw(self):
|
def draw(self):
|
||||||
self.background.draw()
|
self.background.draw()
|
|
@ -4,3 +4,4 @@ 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
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
from typing import Type, TYPE_CHECKING
|
|
||||||
|
|
||||||
import pyglet
|
|
||||||
|
|
||||||
from source.gui.texture.abc import Style
|
|
||||||
from source.gui.widget.grid.abc import GameGrid
|
|
||||||
from source.gui.sprite import Sprite
|
|
||||||
from source.type import Point2D
|
|
||||||
from source.utils import dict_filter_prefix
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from source.gui.scene.abc import Scene
|
|
||||||
|
|
||||||
|
|
||||||
class GameGridEnemy(GameGrid):
|
|
||||||
"""
|
|
||||||
A game grid that represent the enemy grid.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, scene: "Scene",
|
|
||||||
|
|
||||||
rows: int,
|
|
||||||
columns: int,
|
|
||||||
|
|
||||||
grid_style: Type[Style],
|
|
||||||
bomb_style: Type[Style],
|
|
||||||
|
|
||||||
**kwargs):
|
|
||||||
self.cell_sprites: dict[Point2D, "Sprite"] = {}
|
|
||||||
|
|
||||||
super().__init__(scene, rows, columns, grid_style, **kwargs)
|
|
||||||
|
|
||||||
self._bomb_kwargs = dict_filter_prefix("bomb_", kwargs)
|
|
||||||
self.bomb_style = bomb_style
|
|
||||||
|
|
||||||
self.add_listener("on_click_release", self.on_click_release)
|
|
||||||
|
|
||||||
def _refresh_size(self):
|
|
||||||
super()._refresh_size()
|
|
||||||
|
|
||||||
for (x, y), sprite in self.cell_sprites.items():
|
|
||||||
sprite.x = self.x + (self.cell_width * x)
|
|
||||||
sprite.y = self.y + (self.cell_height * y)
|
|
||||||
sprite.width = self.cell_width
|
|
||||||
sprite.height = self.cell_height
|
|
||||||
|
|
||||||
def place_bomb(self, cell: Point2D, touched: bool):
|
|
||||||
self.cell_sprites[cell] = Sprite(
|
|
||||||
img=self.bomb_style.get("touched" if touched else "missed"),
|
|
||||||
**self._bomb_kwargs
|
|
||||||
)
|
|
||||||
|
|
||||||
self._refresh_size()
|
|
||||||
|
|
||||||
def on_click_release(self, rel_x: int, rel_y: int, button: int, modifiers: int):
|
|
||||||
cell = self.get_cell_from_rel(rel_x, rel_y)
|
|
||||||
|
|
||||||
if button == pyglet.window.mouse.LEFT:
|
|
||||||
self.trigger_event("on_request_place_bomb", cell)
|
|
||||||
|
|
||||||
def draw(self):
|
|
||||||
self.background.draw()
|
|
||||||
for sprite in self.cell_sprites.values(): sprite.draw()
|
|
||||||
self.cursor.draw()
|
|
||||||
for line in self.lines: line.draw()
|
|
|
@ -1,2 +0,0 @@
|
||||||
from .GameGridAlly import GameGridAlly
|
|
||||||
from .GameGridEnemy import GameGridEnemy
|
|
|
@ -1,124 +0,0 @@
|
||||||
from typing import TYPE_CHECKING, Type
|
|
||||||
|
|
||||||
import pyglet.shapes
|
|
||||||
|
|
||||||
from source.gui.sprite import Sprite
|
|
||||||
from source.gui.texture.abc import Style
|
|
||||||
from source.gui.widget.abc import BoxWidget
|
|
||||||
from source.type import Distance
|
|
||||||
from source.utils import dict_filter_prefix
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from source.gui.scene.abc import Scene
|
|
||||||
|
|
||||||
|
|
||||||
class GameGrid(BoxWidget):
|
|
||||||
"""
|
|
||||||
A widget that represent a game grid.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, scene: "Scene",
|
|
||||||
|
|
||||||
rows: int,
|
|
||||||
columns: int,
|
|
||||||
|
|
||||||
style: Type[Style],
|
|
||||||
|
|
||||||
x: Distance = 0,
|
|
||||||
y: Distance = 0,
|
|
||||||
width: Distance = None,
|
|
||||||
height: Distance = None,
|
|
||||||
|
|
||||||
**kwargs):
|
|
||||||
super().__init__(scene, x, y, width, height)
|
|
||||||
|
|
||||||
self.rows = rows
|
|
||||||
self.columns = columns
|
|
||||||
|
|
||||||
self.style = style
|
|
||||||
|
|
||||||
self.background = Sprite(
|
|
||||||
img=style.get("background"),
|
|
||||||
**dict_filter_prefix("background_", kwargs)
|
|
||||||
)
|
|
||||||
|
|
||||||
self.lines: list[pyglet.shapes.Line] = [
|
|
||||||
pyglet.shapes.Line(
|
|
||||||
0, 0, 0, 0,
|
|
||||||
**dict_filter_prefix("line_", kwargs)
|
|
||||||
)
|
|
||||||
for _ in range((self.columns - 1) + (self.rows - 1))
|
|
||||||
]
|
|
||||||
|
|
||||||
self.cursor = pyglet.shapes.Rectangle(
|
|
||||||
0, 0, 0, 0,
|
|
||||||
color=(0, 0, 0, 100),
|
|
||||||
**dict_filter_prefix("cursor_", kwargs)
|
|
||||||
)
|
|
||||||
|
|
||||||
self.add_listener("on_hover_leave", lambda *_: self.hide_cursor())
|
|
||||||
self.add_listener("on_hover", self._refresh_cursor)
|
|
||||||
|
|
||||||
self._refresh_size()
|
|
||||||
|
|
||||||
def get_cell_from_rel(self, rel_x: int, rel_y: int) -> tuple[int, int]:
|
|
||||||
"""
|
|
||||||
Return the cell of the grid from a point relative position
|
|
||||||
"""
|
|
||||||
|
|
||||||
return (
|
|
||||||
int((rel_x-1) / self.cell_width),
|
|
||||||
int((rel_y-1) / self.cell_height)
|
|
||||||
)
|
|
||||||
|
|
||||||
# refresh
|
|
||||||
|
|
||||||
def _refresh_size(self):
|
|
||||||
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):
|
|
||||||
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):
|
|
||||||
line.x = self.x
|
|
||||||
line.x2 = self.x2
|
|
||||||
line.y = self.y + self.cell_height * row
|
|
||||||
line.y2 = line.y
|
|
||||||
|
|
||||||
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.width, self.cursor.height = self.cell_size
|
|
||||||
|
|
||||||
def hide_cursor(self):
|
|
||||||
self.cursor.width, self.cursor.height = 0, 0
|
|
||||||
|
|
||||||
# property
|
|
||||||
|
|
||||||
@property
|
|
||||||
def cell_width(self) -> float:
|
|
||||||
return self.width / self.columns
|
|
||||||
|
|
||||||
@property
|
|
||||||
def cell_height(self) -> float:
|
|
||||||
return self.height / self.rows
|
|
||||||
|
|
||||||
@property
|
|
||||||
def cell_size(self) -> tuple[float, float]:
|
|
||||||
return self.cell_width, self.cell_height
|
|
||||||
|
|
||||||
# event
|
|
||||||
|
|
||||||
def on_resize(self, width: int, height: int):
|
|
||||||
self._refresh_size()
|
|
||||||
|
|
||||||
def draw(self):
|
|
||||||
self.background.draw()
|
|
||||||
self.cursor.draw()
|
|
||||||
for line in self.lines: line.draw()
|
|
|
@ -1 +0,0 @@
|
||||||
from .GameGrid import GameGrid
|
|
Loading…
Reference in a new issue