unified GameGridAlly and GameGridEnemy

This commit is contained in:
Faraphel 2023-02-23 19:05:28 +01:00
parent db21bf5e04
commit a096785c28
8 changed files with 110 additions and 209 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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