added the possibility to view in replay a previous game
This commit is contained in:
parent
15353991f6
commit
b386fc03fa
9 changed files with 287 additions and 134 deletions
2
NOTE.md
2
NOTE.md
|
@ -2,7 +2,6 @@ A faire :
|
||||||
|
|
||||||
|
|
||||||
1. Principal :
|
1. Principal :
|
||||||
- Historique
|
|
||||||
- Paramètres (contenu : fps, volume dans le jeu, plein écran, ...) (bouton dans le jeu)
|
- Paramètres (contenu : fps, volume dans le jeu, plein écran, ...) (bouton dans le jeu)
|
||||||
- Documenter (Docstring, README, ...)
|
- Documenter (Docstring, README, ...)
|
||||||
|
|
||||||
|
@ -17,6 +16,7 @@ A faire :
|
||||||
Bug :
|
Bug :
|
||||||
- (incertain) Dans de rare cas (souvent en fermant brutalement la fenêtre) le processus ne s'arrête pas
|
- (incertain) Dans de rare cas (souvent en fermant brutalement la fenêtre) le processus ne s'arrête pas
|
||||||
- Quitter pendant que l'on décide de si l'on doit charger ou non une ancienne sauvegarde fait crash l'adversaire
|
- Quitter pendant que l'on décide de si l'on doit charger ou non une ancienne sauvegarde fait crash l'adversaire
|
||||||
|
- Les champs invalides n'empêchent pas de faire l'action
|
||||||
|
|
||||||
Autre :
|
Autre :
|
||||||
- Tester sur Linux
|
- Tester sur Linux
|
||||||
|
|
|
@ -113,6 +113,20 @@ class Board:
|
||||||
# if the boat have been touched, but without sinking
|
# if the boat have been touched, but without sinking
|
||||||
return BombState.TOUCHED
|
return BombState.TOUCHED
|
||||||
|
|
||||||
|
def remove_bomb(self, cell: Point2D):
|
||||||
|
"""
|
||||||
|
Retire une bombe de la matrice
|
||||||
|
:param cell: cellule de la bombe
|
||||||
|
"""
|
||||||
|
x, y = cell
|
||||||
|
self.bombs[y, x] = True
|
||||||
|
|
||||||
|
def clear_bombs(self):
|
||||||
|
"""
|
||||||
|
Retire toutes les bombes de la planche
|
||||||
|
"""
|
||||||
|
self.bombs = np.ones(self.bombs.shape)
|
||||||
|
|
||||||
def get_matrice(self) -> np.array:
|
def get_matrice(self) -> np.array:
|
||||||
"""
|
"""
|
||||||
:return: the boats and bombs represented as a matrice
|
:return: the boats and bombs represented as a matrice
|
||||||
|
|
37
source/gui/position.py
Normal file
37
source/gui/position.py
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
|
|
||||||
|
# pourcentage
|
||||||
|
|
||||||
|
|
||||||
|
def w_percent(value: int) -> Callable: # positionne en pourcentage la largeur
|
||||||
|
return lambda widget: int(widget.scene.window.width * (value / 100))
|
||||||
|
|
||||||
|
|
||||||
|
def h_percent(value: int) -> Callable: # positionne en pourcentage la hauteur
|
||||||
|
return lambda widget: int(widget.scene.window.height * (value / 100))
|
||||||
|
|
||||||
|
|
||||||
|
# pixel
|
||||||
|
|
||||||
|
|
||||||
|
def right(px: int) -> Callable: # positionne depuis la droite
|
||||||
|
return lambda widget: widget.scene.window.width - px
|
||||||
|
|
||||||
|
|
||||||
|
def up(px: int) -> Callable: # positionne depuis le haut
|
||||||
|
return lambda widget: widget.scene.window.height - px
|
||||||
|
|
||||||
|
|
||||||
|
def right_content(px: int) -> Callable: # positionne depuis la droite avec la taille du widget compris
|
||||||
|
return lambda widget: widget.scene.window.width - widget.width - px
|
||||||
|
|
||||||
|
|
||||||
|
def up_content(px: int) -> Callable: # positionne depuis le haut avec la taille du widget compris
|
||||||
|
return lambda widget: widget.scene.window.height - widget.height - px
|
||||||
|
|
||||||
|
|
||||||
|
# raccourci
|
||||||
|
|
||||||
|
w_full = w_percent(100)
|
||||||
|
h_full = h_percent(100)
|
|
@ -8,10 +8,9 @@ from source.path import path_save, path_history
|
||||||
from source.core.enums import BombState
|
from source.core.enums import BombState
|
||||||
from source.core.error import InvalidBombPosition, PositionAlreadyShot
|
from source.core.error import InvalidBombPosition, PositionAlreadyShot
|
||||||
from source.gui.scene import GameResult
|
from source.gui.scene import GameResult
|
||||||
from source.gui.scene.abc import Scene
|
from source.gui.scene.abc import BaseGame
|
||||||
from source.gui import widget, texture, scene
|
from source.gui import widget, texture, scene
|
||||||
from source.network.packet import PacketChat, PacketBombPlaced, PacketBoatPlaced, PacketBombState, PacketQuit, \
|
from source.network.packet import *
|
||||||
PacketAskSave, PacketResponseSave, PacketBoatsData
|
|
||||||
from source.type import Point2D
|
from source.type import Point2D
|
||||||
from source.utils import StoppableThread
|
from source.utils import StoppableThread
|
||||||
|
|
||||||
|
@ -19,55 +18,18 @@ if TYPE_CHECKING:
|
||||||
from source.gui.window import Window
|
from source.gui.window import Window
|
||||||
|
|
||||||
|
|
||||||
class Game(Scene):
|
class Game(BaseGame):
|
||||||
def __init__(self, window: "Window",
|
def __init__(self, window: "Window",
|
||||||
thread: StoppableThread,
|
thread: StoppableThread,
|
||||||
connection: socket.socket,
|
connection: socket.socket,
|
||||||
|
|
||||||
boats_length: list,
|
|
||||||
name_ally: str,
|
|
||||||
name_enemy: str,
|
|
||||||
my_turn: bool,
|
my_turn: bool,
|
||||||
|
|
||||||
grid_width: int = None,
|
|
||||||
grid_height: int = None,
|
|
||||||
board_ally_data: dict = None,
|
|
||||||
board_enemy_data: dict = None,
|
|
||||||
|
|
||||||
history: list[bool, Point2D] = None,
|
|
||||||
|
|
||||||
**kwargs):
|
**kwargs):
|
||||||
super().__init__(window, **kwargs)
|
super().__init__(window, **kwargs)
|
||||||
|
|
||||||
self.thread = thread
|
self.thread = thread
|
||||||
self.connection = connection
|
self.connection = connection
|
||||||
self.boats_length = boats_length
|
|
||||||
self.name_ally = name_ally
|
|
||||||
self.name_enemy = name_enemy
|
|
||||||
self.grid_width = grid_width
|
|
||||||
self.grid_height = grid_height
|
|
||||||
|
|
||||||
self.background = self.add_widget(
|
|
||||||
widget.Image,
|
|
||||||
|
|
||||||
x=0, y=0, width=1.0, height=1.0,
|
|
||||||
|
|
||||||
image=texture.Background.game,
|
|
||||||
)
|
|
||||||
|
|
||||||
self.grid_ally = self.add_widget(
|
|
||||||
widget.GameGrid,
|
|
||||||
|
|
||||||
x=75, y=0.25, width=0.35, height=0.5,
|
|
||||||
|
|
||||||
boats_length=self.boats_length,
|
|
||||||
|
|
||||||
grid_style=texture.Grid.Style1,
|
|
||||||
boat_style=texture.Grid.Boat.Style1,
|
|
||||||
rows=self.grid_height, columns=self.grid_width,
|
|
||||||
|
|
||||||
board_data=board_ally_data
|
|
||||||
)
|
|
||||||
|
|
||||||
def board_ally_ready(widget):
|
def board_ally_ready(widget):
|
||||||
self.boat_ready_ally = True
|
self.boat_ready_ally = True
|
||||||
|
@ -75,18 +37,6 @@ 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(
|
|
||||||
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,
|
|
||||||
rows=self.grid_height, columns=self.grid_width,
|
|
||||||
|
|
||||||
board_data=board_enemy_data
|
|
||||||
)
|
|
||||||
|
|
||||||
def board_enemy_bomb(widget, cell: Point2D):
|
def board_enemy_bomb(widget, cell: Point2D):
|
||||||
if not (self.boat_ready_ally and self.boat_ready_enemy): return
|
if not (self.boat_ready_ally and self.boat_ready_enemy): return
|
||||||
if not self.my_turn: return
|
if not self.my_turn: return
|
||||||
|
@ -96,46 +46,6 @@ class Game(Scene):
|
||||||
|
|
||||||
self.grid_enemy.add_listener("on_request_place_bomb", board_enemy_bomb)
|
self.grid_enemy.add_listener("on_request_place_bomb", board_enemy_bomb)
|
||||||
|
|
||||||
self.add_widget(
|
|
||||||
widget.Text,
|
|
||||||
|
|
||||||
x=0.27, y=0.995,
|
|
||||||
|
|
||||||
text=self.name_ally,
|
|
||||||
font_size=20,
|
|
||||||
anchor_x="center", anchor_y="center"
|
|
||||||
)
|
|
||||||
|
|
||||||
self.add_widget(
|
|
||||||
widget.Text,
|
|
||||||
|
|
||||||
x=0.73, y=0.995,
|
|
||||||
|
|
||||||
text=self.name_enemy,
|
|
||||||
font_size=20,
|
|
||||||
anchor_x="center", anchor_y="center"
|
|
||||||
)
|
|
||||||
|
|
||||||
self.score_ally = self.add_widget(
|
|
||||||
widget.Text,
|
|
||||||
|
|
||||||
x=0.44, y=0.995,
|
|
||||||
|
|
||||||
text="0",
|
|
||||||
font_size=25,
|
|
||||||
anchor_x="center", anchor_y="center"
|
|
||||||
)
|
|
||||||
|
|
||||||
self.score_enemy = self.add_widget(
|
|
||||||
widget.Text,
|
|
||||||
|
|
||||||
x=0.56, y=0.995,
|
|
||||||
|
|
||||||
text="0",
|
|
||||||
font_size=25,
|
|
||||||
anchor_x="center", anchor_y="center"
|
|
||||||
)
|
|
||||||
|
|
||||||
self.chat_log = self.add_widget(
|
self.chat_log = self.add_widget(
|
||||||
widget.Text,
|
widget.Text,
|
||||||
|
|
||||||
|
@ -185,19 +95,11 @@ class Game(Scene):
|
||||||
|
|
||||||
self.button_save.add_listener("on_click_release", ask_save)
|
self.button_save.add_listener("on_click_release", ask_save)
|
||||||
|
|
||||||
self.button_quit = self.add_widget(
|
self.button_quit.add_listener(
|
||||||
widget.Button,
|
"on_click_release",
|
||||||
|
lambda *_: self.window.add_scene(scene.GameQuit, game_scene=self)
|
||||||
x=0.85, y=0, width=0.15, height=0.1,
|
|
||||||
|
|
||||||
label_text="Quitter",
|
|
||||||
|
|
||||||
style=texture.Button.Style1
|
|
||||||
)
|
)
|
||||||
|
|
||||||
self.button_quit.add_listener("on_click_release",
|
|
||||||
lambda *_: self.window.add_scene(scene.GameQuit, game_scene=self))
|
|
||||||
|
|
||||||
self.label_state = self.add_widget(
|
self.label_state = self.add_widget(
|
||||||
widget.Text,
|
widget.Text,
|
||||||
|
|
||||||
|
@ -212,9 +114,7 @@ class Game(Scene):
|
||||||
self._boat_ready_ally: bool = False # does the player finished placing his boat ?
|
self._boat_ready_ally: bool = False # does the player finished placing his boat ?
|
||||||
self._boat_ready_enemy: bool = False # does the opponent finished placing his boat ?
|
self._boat_ready_enemy: bool = False # does the opponent finished placing his boat ?
|
||||||
|
|
||||||
self.history: list[tuple[bool, Point2D]] = [] if history is None else history # liste des bombes posées
|
if len(self.boats_length) == 0: # s'il n'y a pas de bateau à placé
|
||||||
|
|
||||||
if len(boats_length) == 0: # s'il n'y a pas de bateau à placé
|
|
||||||
self._boat_ready_ally = True # défini l'état de notre planche comme prête
|
self._boat_ready_ally = True # défini l'état de notre planche comme prête
|
||||||
PacketBoatPlaced().send_connection(connection) # indique à l'adversaire que notre planche est prête
|
PacketBoatPlaced().send_connection(connection) # indique à l'adversaire que notre planche est prête
|
||||||
|
|
||||||
|
@ -242,10 +142,6 @@ class Game(Scene):
|
||||||
"L'adversaire place ses bombes..."
|
"L'adversaire place ses bombes..."
|
||||||
)
|
)
|
||||||
|
|
||||||
def _refresh_score_text(self):
|
|
||||||
self.score_ally.text = str(self.grid_enemy.board.get_score())
|
|
||||||
self.score_enemy.text = str(self.grid_ally.board.get_score())
|
|
||||||
|
|
||||||
# property
|
# property
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -312,15 +208,19 @@ class Game(Scene):
|
||||||
history=data["history"]
|
history=data["history"]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def get_save_suffix(self) -> str:
|
||||||
|
# Le suffix est un entier indiquant si c'est à notre tour ou non.
|
||||||
|
# Cet entier permet aux localhost de toujours pouvoir sauvegarder et charger sans problème.
|
||||||
|
ip_address, port = self.connection.getpeername()
|
||||||
|
return f"-{int(self.my_turn)}" if ip_address == "127.0.0.1" else ""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def save_path(self) -> Path:
|
def save_path(self) -> Path:
|
||||||
ip_address, port = self.connection.getpeername()
|
ip_address, port = self.connection.getpeername()
|
||||||
|
|
||||||
# Le nom du fichier est l'IP de l'opposent, suivi d'un entier indiquant si c'est à notre tour ou non.
|
|
||||||
# Cet entier permet aux localhost de toujours pouvoir sauvegarder et charger sans problème.
|
|
||||||
return path_save / (
|
return path_save / (
|
||||||
ip_address +
|
ip_address +
|
||||||
(f"-{int(self.my_turn)}" if ip_address == "127.0.0.1" else "") +
|
self.get_save_suffix() +
|
||||||
".bn-save"
|
".bn-save"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -328,6 +228,7 @@ class Game(Scene):
|
||||||
def history_path(self):
|
def history_path(self):
|
||||||
return path_history / (
|
return path_history / (
|
||||||
datetime.now().strftime("%Y-%m-%d_%H-%M-%S") +
|
datetime.now().strftime("%Y-%m-%d_%H-%M-%S") +
|
||||||
|
self.get_save_suffix() +
|
||||||
".bn-history"
|
".bn-history"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -387,13 +288,12 @@ class Game(Scene):
|
||||||
else:
|
else:
|
||||||
# c'est à notre tour si l'opposant à loupé sa bombe
|
# c'est à notre tour si l'opposant à loupé sa bombe
|
||||||
self.my_turn = not bomb_state.success
|
self.my_turn = not bomb_state.success
|
||||||
|
# sauvegarde la bombe dans l'historique
|
||||||
|
self.history.append((False, packet.position))
|
||||||
|
|
||||||
# envoie le résultat à l'autre joueur
|
# envoie le résultat à l'autre joueur
|
||||||
PacketBombState(position=packet.position, bomb_state=bomb_state).send_connection(self.connection)
|
PacketBombState(position=packet.position, bomb_state=bomb_state).send_connection(self.connection)
|
||||||
|
|
||||||
# sauvegarde la bombe dans l'historique
|
|
||||||
self.history.append((False, packet.position))
|
|
||||||
|
|
||||||
self._refresh_score_text() # le score a changé, donc rafraichi son texte
|
self._refresh_score_text() # le score a changé, donc rafraichi son texte
|
||||||
|
|
||||||
if bomb_state is BombState.WON:
|
if bomb_state is BombState.WON:
|
||||||
|
|
|
@ -1,26 +1,96 @@
|
||||||
|
import json
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from source.gui import widget
|
from source.gui import widget, texture
|
||||||
from source.gui.scene.abc import Scene
|
from source.gui.position import h_percent, w_percent
|
||||||
|
from source.gui.scene.abc import BaseGame
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from source.gui.window import Window
|
from source.gui.window import Window
|
||||||
|
|
||||||
|
|
||||||
class HistoryGame(Scene):
|
class HistoryGame(BaseGame):
|
||||||
def __init__(self, window: "Window", history_path: Path, **kwargs):
|
def __init__(self, window: "Window", history_path: Path, **kwargs):
|
||||||
super().__init__(window, **kwargs)
|
|
||||||
|
with open(history_path, "r", encoding="utf8") as file:
|
||||||
|
history_data = json.load(file)
|
||||||
|
|
||||||
|
super().__init__(
|
||||||
|
window,
|
||||||
|
boats_length=[],
|
||||||
|
name_ally=history_data["name_ally"],
|
||||||
|
name_enemy=history_data["name_enemy"],
|
||||||
|
board_ally_data=history_data["grid_ally"],
|
||||||
|
board_enemy_data=history_data["grid_enemy"],
|
||||||
|
history=history_data["history"],
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
|
||||||
self.history_path = history_path
|
self.history_path = history_path
|
||||||
|
|
||||||
self.add_widget(
|
from source.gui.scene import MainMenu
|
||||||
widget.Text,
|
self.button_quit.add_listener("on_click_release", lambda *_: window.set_scene(MainMenu))
|
||||||
|
|
||||||
x=0.5, y=0.5,
|
self.move_number: int = 0 # numéro du mouvement en cours
|
||||||
|
|
||||||
anchor_x="center", anchor_y="center",
|
self.grid_ally.board.clear_bombs()
|
||||||
|
self.grid_ally.refresh_board()
|
||||||
|
self.grid_enemy.board.clear_bombs()
|
||||||
|
self.grid_enemy.refresh_board()
|
||||||
|
|
||||||
text=str(history_path)
|
self.previous = self.add_widget(
|
||||||
|
widget.Button,
|
||||||
|
x=w_percent(20), y=h_percent(10), width=w_percent(20), height=h_percent(10),
|
||||||
|
|
||||||
|
label_text="Précédent",
|
||||||
|
|
||||||
|
style=texture.Button.Style1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.previous.add_listener("on_click_release", lambda *_: self.previous_move())
|
||||||
|
|
||||||
|
self.next = self.add_widget(
|
||||||
|
widget.Button,
|
||||||
|
x=w_percent(60), y=h_percent(10), width=w_percent(20), height=h_percent(10),
|
||||||
|
|
||||||
|
label_text="Suivant",
|
||||||
|
|
||||||
|
style=texture.Button.Style1
|
||||||
|
)
|
||||||
|
|
||||||
|
self.next.add_listener("on_click_release", lambda *_: self.next_move())
|
||||||
|
|
||||||
|
self.text_move = self.add_widget(
|
||||||
|
widget.Text,
|
||||||
|
x=w_percent(50), y=h_percent(12),
|
||||||
|
|
||||||
|
anchor_x="center",
|
||||||
|
|
||||||
|
font_size=28,
|
||||||
|
)
|
||||||
|
self._refresh_move_text()
|
||||||
|
|
||||||
|
def _refresh_move_text(self):
|
||||||
|
self.text_move.text = f"{self.move_number} / {len(self.history)}"
|
||||||
|
self._refresh_score_text()
|
||||||
|
|
||||||
|
def previous_move(self):
|
||||||
|
# si le mouvement est au minimum, ignore
|
||||||
|
if self.move_number <= 0: return
|
||||||
|
|
||||||
|
self.move_number -= 1
|
||||||
|
turn, cell = self.history[self.move_number]
|
||||||
|
(self.grid_enemy if turn else self.grid_ally).remove_bomb(cell)
|
||||||
|
|
||||||
|
self._refresh_move_text()
|
||||||
|
|
||||||
|
def next_move(self):
|
||||||
|
# si le mouvement est au maximum, ignore
|
||||||
|
if self.move_number >= len(self.history): return
|
||||||
|
|
||||||
|
self.move_number += 1
|
||||||
|
turn, cell = self.history[self.move_number-1]
|
||||||
|
(self.grid_enemy if turn else self.grid_ally).place_bomb(cell)
|
||||||
|
|
||||||
|
self._refresh_move_text()
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
from source.gui.position import w_full, h_full, h_percent
|
||||||
from source.gui.scene.abc import Scene
|
from source.gui.scene.abc import Scene
|
||||||
from source.gui import widget, scene, texture
|
from source.gui import widget, scene, texture
|
||||||
|
|
||||||
|
@ -14,7 +15,7 @@ class MainMenu(Scene):
|
||||||
self.background = self.add_widget(
|
self.background = self.add_widget(
|
||||||
widget.Image,
|
widget.Image,
|
||||||
|
|
||||||
x=0.0, y=0.0, width=1.0, height=1.0,
|
x=0, y=0, width=w_full, height=h_full,
|
||||||
|
|
||||||
image=texture.Background.main
|
image=texture.Background.main
|
||||||
)
|
)
|
||||||
|
@ -22,7 +23,7 @@ class MainMenu(Scene):
|
||||||
self.title = self.add_widget(
|
self.title = self.add_widget(
|
||||||
widget.Text,
|
widget.Text,
|
||||||
|
|
||||||
x=50, y=0.85,
|
x=50, y=h_percent(85),
|
||||||
|
|
||||||
text="Bataille Navale",
|
text="Bataille Navale",
|
||||||
font_size=50
|
font_size=50
|
||||||
|
|
121
source/gui/scene/abc/BaseGame.py
Normal file
121
source/gui/scene/abc/BaseGame.py
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
from abc import ABC
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
from source.gui import widget, texture
|
||||||
|
from source.gui.position import right_content, h_percent, w_percent, w_full, h_full
|
||||||
|
from source.gui.scene.abc import Scene
|
||||||
|
from source.type import Point2D
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from source.gui.window import Window
|
||||||
|
|
||||||
|
|
||||||
|
class BaseGame(Scene, ABC):
|
||||||
|
def __init__(self, window: "Window",
|
||||||
|
boats_length: list,
|
||||||
|
name_ally: str,
|
||||||
|
name_enemy: str,
|
||||||
|
|
||||||
|
grid_width: int = None,
|
||||||
|
grid_height: int = None,
|
||||||
|
board_ally_data: dict = None,
|
||||||
|
board_enemy_data: dict = None,
|
||||||
|
|
||||||
|
history: list[bool, Point2D] = None,
|
||||||
|
|
||||||
|
**kwargs):
|
||||||
|
|
||||||
|
super().__init__(window, **kwargs)
|
||||||
|
|
||||||
|
self.boats_length = boats_length
|
||||||
|
self.name_ally = name_ally
|
||||||
|
self.name_enemy = name_enemy
|
||||||
|
self.history: list[tuple[bool, Point2D]] = [] if history is None else history # liste des bombes posées
|
||||||
|
|
||||||
|
self.background = self.add_widget(
|
||||||
|
widget.Image,
|
||||||
|
|
||||||
|
x=0, y=0, width=w_full, height=h_full,
|
||||||
|
|
||||||
|
image=texture.Background.game,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.grid_ally = self.add_widget(
|
||||||
|
widget.GameGrid,
|
||||||
|
|
||||||
|
x=75, y=0.25, width=0.35, height=0.5,
|
||||||
|
|
||||||
|
boats_length=self.boats_length,
|
||||||
|
|
||||||
|
grid_style=texture.Grid.Style1,
|
||||||
|
boat_style=texture.Grid.Boat.Style1,
|
||||||
|
|
||||||
|
rows=grid_height, columns=grid_width,
|
||||||
|
board_data=board_ally_data
|
||||||
|
)
|
||||||
|
|
||||||
|
self.grid_enemy = self.add_widget(
|
||||||
|
widget.GameGrid,
|
||||||
|
|
||||||
|
x=right_content(75), y=h_percent(25), width=w_percent(35), height=h_percent(50),
|
||||||
|
|
||||||
|
grid_style=texture.Grid.Style1,
|
||||||
|
boat_style=texture.Grid.Boat.Style1,
|
||||||
|
|
||||||
|
rows=grid_height, columns=grid_width,
|
||||||
|
board_data=board_enemy_data
|
||||||
|
)
|
||||||
|
|
||||||
|
self.add_widget(
|
||||||
|
widget.Text,
|
||||||
|
|
||||||
|
x=0.27, y=0.995,
|
||||||
|
|
||||||
|
text=self.name_ally,
|
||||||
|
font_size=20,
|
||||||
|
anchor_x="center", anchor_y="center"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.add_widget(
|
||||||
|
widget.Text,
|
||||||
|
|
||||||
|
x=0.73, y=0.995,
|
||||||
|
|
||||||
|
text=self.name_enemy,
|
||||||
|
font_size=20,
|
||||||
|
anchor_x="center", anchor_y="center"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.score_ally = self.add_widget(
|
||||||
|
widget.Text,
|
||||||
|
|
||||||
|
x=0.44, y=0.995,
|
||||||
|
|
||||||
|
text="0",
|
||||||
|
font_size=25,
|
||||||
|
anchor_x="center", anchor_y="center"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.score_enemy = self.add_widget(
|
||||||
|
widget.Text,
|
||||||
|
|
||||||
|
x=0.56, y=0.995,
|
||||||
|
|
||||||
|
text="0",
|
||||||
|
font_size=25,
|
||||||
|
anchor_x="center", anchor_y="center"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.button_quit = self.add_widget(
|
||||||
|
widget.Button,
|
||||||
|
|
||||||
|
x=0.85, y=0, width=0.15, height=0.1,
|
||||||
|
|
||||||
|
label_text="Quitter",
|
||||||
|
|
||||||
|
style=texture.Button.Style1
|
||||||
|
)
|
||||||
|
|
||||||
|
def _refresh_score_text(self):
|
||||||
|
self.score_ally.text = str(self.grid_enemy.board.get_score())
|
||||||
|
self.score_enemy.text = str(self.grid_ally.board.get_score())
|
|
@ -1 +1,2 @@
|
||||||
from .Scene import Scene
|
from .Scene import Scene
|
||||||
|
from .BaseGame import BaseGame
|
||||||
|
|
|
@ -94,7 +94,7 @@ class GameGrid(BoxWidget):
|
||||||
self.add_listener("on_hover", lambda _, *args: self._refresh_cursor(*args))
|
self.add_listener("on_hover", lambda _, *args: self._refresh_cursor(*args))
|
||||||
|
|
||||||
self._refresh_size()
|
self._refresh_size()
|
||||||
self.display_board(self.board)
|
self.refresh_board()
|
||||||
|
|
||||||
def get_cell_from_rel(self, rel_x: int, rel_y: int) -> tuple[int, int]:
|
def get_cell_from_rel(self, rel_x: int, rel_y: int) -> tuple[int, int]:
|
||||||
"""
|
"""
|
||||||
|
@ -158,6 +158,10 @@ class GameGrid(BoxWidget):
|
||||||
def hide_cursor(self):
|
def hide_cursor(self):
|
||||||
self.cursor.width, self.cursor.height = 0, 0
|
self.cursor.width, self.cursor.height = 0, 0
|
||||||
|
|
||||||
|
def refresh_board(self):
|
||||||
|
# rafraichi l'affichage de la grille
|
||||||
|
self.display_board(self.board)
|
||||||
|
|
||||||
def display_board(self, board: Board, preview: bool = False):
|
def display_board(self, board: Board, preview: bool = False):
|
||||||
# remplacer par l'utilisation de board.boats ?
|
# remplacer par l'utilisation de board.boats ?
|
||||||
|
|
||||||
|
@ -239,7 +243,7 @@ class GameGrid(BoxWidget):
|
||||||
if len(self.boats_length) == 0:
|
if len(self.boats_length) == 0:
|
||||||
self.trigger_event("on_all_boats_placed")
|
self.trigger_event("on_all_boats_placed")
|
||||||
|
|
||||||
self.display_board(self.board) # rafraichi l'affichage
|
self.refresh_board() # rafraichi l'affichage
|
||||||
|
|
||||||
def preview_boat(self, cell: Point2D):
|
def preview_boat(self, cell: Point2D):
|
||||||
if len(self.boats_length) == 0: return
|
if len(self.boats_length) == 0: return
|
||||||
|
@ -251,7 +255,7 @@ class GameGrid(BoxWidget):
|
||||||
cell
|
cell
|
||||||
)
|
)
|
||||||
except InvalidBoatPosition:
|
except InvalidBoatPosition:
|
||||||
self.display_board(self.board) # if the boat can't be placed, ignore
|
self.refresh_board() # if the boat can't be placed, ignore
|
||||||
|
|
||||||
else: self.display_board(preview_board, preview=True)
|
else: self.display_board(preview_board, preview=True)
|
||||||
|
|
||||||
|
@ -262,9 +266,14 @@ class GameGrid(BoxWidget):
|
||||||
x, y = cell
|
x, y = cell
|
||||||
self.board.boats[y, x] = int(force_touched)
|
self.board.boats[y, x] = int(force_touched)
|
||||||
|
|
||||||
self.display_board(self.board)
|
self.refresh_board()
|
||||||
return bomb_state
|
return bomb_state
|
||||||
|
|
||||||
|
def remove_bomb(self, cell: Point2D):
|
||||||
|
# retire une bombe de la planche
|
||||||
|
self.board.remove_bomb(cell)
|
||||||
|
self.refresh_board()
|
||||||
|
|
||||||
def on_click_release(self, rel_x: int, rel_y: int, button: int, modifiers: int):
|
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)
|
cell = self.get_cell_from_rel(rel_x, rel_y)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue