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
|
||||
- Documenter
|
||||
- Ajouter plus d'event sur les widgets
|
||||
|
||||
- Ecran de victoire
|
||||
- Affichage des coups de l'opposant
|
||||
- Faire marcher le tchat
|
||||
- Sauvegarde / Quitter
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ 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
|
||||
from source.network.packet import PacketChat, PacketBombPlaced, PacketBoatPlaced
|
||||
from source.type import Point2D
|
||||
|
@ -38,7 +37,7 @@ class Game(Scene):
|
|||
)
|
||||
|
||||
self.grid_ally = self.add_widget(
|
||||
GameGridAlly,
|
||||
widget.GameGrid,
|
||||
|
||||
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_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,
|
||||
|
||||
grid_style=texture.Grid.Style1,
|
||||
boat_style=texture.Grid.Boat.Style1,
|
||||
bomb_style=texture.Grid.Bomb.Style1,
|
||||
rows=8, columns=8,
|
||||
|
||||
background_batch=self.batch_grid_background,
|
||||
line_batch=self.batch_grid_line,
|
||||
cursor_batch=self.batch_grid_cursor,
|
||||
boat_batch=self.batch_grid_boat,
|
||||
bomb_batch=self.batch_grid_bomb
|
||||
)
|
||||
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
from copy import copy
|
||||
from typing import TYPE_CHECKING, Type
|
||||
|
||||
import pyglet
|
||||
import numpy as np
|
||||
import pyglet.shapes
|
||||
|
||||
from source.core import Board, Boat
|
||||
from source.core.enums import Orientation
|
||||
from source.core.error import InvalidBoatPosition
|
||||
from source.gui.sprite import Sprite
|
||||
from source.gui.texture.abc import Style
|
||||
from source.gui.widget.grid.abc import GameGrid
|
||||
from source.core import Board, Boat
|
||||
from source.type import Point2D, ColorRGB
|
||||
from source.gui.widget.abc import BoxWidget
|
||||
from source.type import Distance, ColorRGB, Point2D
|
||||
from source.utils import dict_filter_prefix
|
||||
|
||||
if TYPE_CHECKING:
|
||||
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",
|
||||
|
@ -31,15 +31,23 @@ class GameGridAlly(GameGrid):
|
|||
boat_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),
|
||||
boats_length: list[int] = None,
|
||||
|
||||
**kwargs):
|
||||
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.board = Board(rows=self.rows, columns=self.columns)
|
||||
|
@ -47,19 +55,69 @@ class GameGridAlly(GameGrid):
|
|||
|
||||
self._boat_kwargs = dict_filter_prefix("boat_", kwargs)
|
||||
self._bomb_kwargs = dict_filter_prefix("bomb_", kwargs)
|
||||
self.grid_style = grid_style
|
||||
self.boat_style = boat_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_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
|
||||
|
||||
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():
|
||||
|
||||
# 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
|
||||
|
@ -75,6 +133,20 @@ class GameGridAlly(GameGrid):
|
|||
sprite.width = width
|
||||
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):
|
||||
self.cell_sprites: dict[Point2D, "Sprite"] = {}
|
||||
|
||||
|
@ -151,7 +223,6 @@ class GameGridAlly(GameGrid):
|
|||
else: self.display_board(preview_board, preview=True)
|
||||
|
||||
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
|
||||
|
@ -169,6 +240,26 @@ class GameGridAlly(GameGrid):
|
|||
|
||||
case pyglet.window.mouse.LEFT:
|
||||
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):
|
||||
self.background.draw()
|
|
@ -4,3 +4,4 @@ from .Input import Input
|
|||
from .Image import Image
|
||||
from .Checkbox import Checkbox
|
||||
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