diff --git a/NOTE.md b/NOTE.md index d374ced..1ee7307 100644 --- a/NOTE.md +++ b/NOTE.md @@ -10,7 +10,7 @@ A faire : - Changer les images, rajouter les fonds, ... -- 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 pratiques que l'event propagation (?) - Faire une scène incluant par défaut les boutons "Retour" (?) diff --git a/source/gui/scene/Game.py b/source/gui/scene/Game.py index b65d7a0..e33b3ec 100644 --- a/source/gui/scene/Game.py +++ b/source/gui/scene/Game.py @@ -7,7 +7,7 @@ from source.gui.scene import GameResult from source.gui.scene.abc import Scene from source.gui import widget, texture, scene from source import core -from source.network.packet import PacketChat, PacketBombPlaced, PacketBoatPlaced, PacketBombState +from source.network.packet import PacketChat, PacketBombPlaced, PacketBoatPlaced, PacketBombState, PacketQuit from source.type import Point2D from source.utils import StoppableThread @@ -218,12 +218,14 @@ class Game(Scene): ) def quit(self): + PacketQuit().send_connection(self.connection) + self.thread.stop() from source.gui.scene import MainMenu self.window.set_scene(MainMenu) def game_end(self, won: bool): - self.window.add_scene(GameResult, won=won) + self.window.add_scene(GameResult, game_scene=self, won=won) def chat_new_message(self, author: str, content: str): message: str = f"[{author}] - {content}" @@ -280,13 +282,13 @@ class Game(Scene): # network - def network_on_chat(self, connection: socket.socket, packet: PacketChat): + def network_on_chat(self, packet: PacketChat): self.chat_new_message(self.name_enemy, packet.message) - def network_on_boat_placed(self, connection: socket.socket, packet: PacketBoatPlaced): + def network_on_boat_placed(self, packet: PacketBoatPlaced): self.boat_ready_enemy = True - def network_on_bomb_placed(self, connection: socket.socket, packet: PacketBombPlaced): + def network_on_bomb_placed(self, packet: PacketBombPlaced): try: # essaye de poser la bombe sur la grille alliée bomb_state = self.grid_ally.board.bomb(packet.position) @@ -302,7 +304,7 @@ class Game(Scene): self.my_turn = not bomb_state.success # envoie le résultat à l'autre joueur - PacketBombState(position=packet.position, bomb_state=bomb_state).send_connection(connection) + PacketBombState(position=packet.position, bomb_state=bomb_state).send_connection(self.connection) if bomb_state.success: # si la bombe a touché un bateau, incrémente le score @@ -313,7 +315,7 @@ class Game(Scene): self.game_end(won=False) return True # coupe la connexion - def network_on_bomb_state(self, connection: socket.socket, packet: PacketBombState): + def network_on_bomb_state(self, packet: PacketBombState): if packet.bomb_state is BombState.ERROR: # si une erreur est survenue, on rejoue self.my_turn = True @@ -334,6 +336,11 @@ class Game(Scene): self.game_end(won=True) return True # coupe la connexion + def network_on_quit(self, packet: PacketQuit): + self.thread.stop() + from source.gui.scene import GameError + self.window.set_scene(GameError, text="L'adversaire a quitté la partie.") + # event def on_resize_after(self, width: int, height: int): diff --git a/source/gui/scene/GameError.py b/source/gui/scene/GameError.py new file mode 100644 index 0000000..0d38bff --- /dev/null +++ b/source/gui/scene/GameError.py @@ -0,0 +1,37 @@ +from typing import TYPE_CHECKING + +from source.gui import widget, texture +from source.gui.scene.abc import Scene + + +if TYPE_CHECKING: + from source.gui.window import Window + + +class GameError(Scene): + def __init__(self, window: "Window", text: str, **kwargs): + super().__init__(window, **kwargs) + + self.label = self.add_widget( + widget.Text, + + x=0.5, y=0.5, width=1.0, + + anchor_x="center", + + text=text, + font_size=28, + ) + + self.back = self.add_widget( + widget.Button, + + x=lambda widget: widget.scene.window.width - 20 - widget.width, y=20, width=0.2, height=0.1, + + label_text="Retour", + + style=texture.Button.Style1 + ) + + from source.gui.scene import MainMenu + self.back.add_listener("on_click_release", lambda *_: self.window.set_scene(MainMenu)) diff --git a/source/gui/scene/GameResult.py b/source/gui/scene/GameResult.py index 73b69cb..35b39b6 100644 --- a/source/gui/scene/GameResult.py +++ b/source/gui/scene/GameResult.py @@ -25,4 +25,4 @@ class GameResult(Popup): # TODO: rendre l'image transparente si possible - pyglet.clock.schedule_once(lambda dt: self.game_scene.quit, 5.0) + pyglet.clock.schedule_once(lambda dt: self.game_scene.quit(), 5.0) diff --git a/source/gui/scene/__init__.py b/source/gui/scene/__init__.py index 3f5d5d0..0aac951 100644 --- a/source/gui/scene/__init__.py +++ b/source/gui/scene/__init__.py @@ -1,6 +1,7 @@ from .GameResult import GameResult from .Game import Game from .GameQuit import GameQuit +from .GameError import GameError from .Settings import Settings from .RoomHost import RoomHost from .RoomJoin import RoomJoin diff --git a/source/network/game_network.py b/source/network/game_network.py index e2445c0..e879d72 100644 --- a/source/network/game_network.py +++ b/source/network/game_network.py @@ -26,6 +26,7 @@ def game_network( packet.PacketBoatPlaced: game_scene.network_on_boat_placed, packet.PacketBombPlaced: game_scene.network_on_bomb_placed, packet.PacketBombState: game_scene.network_on_bomb_state, + packet.PacketQuit: game_scene.network_on_quit, } while True: @@ -38,6 +39,5 @@ def game_network( data = data_type.from_connection(connection) if in_pyglet_context( - game_methods[data_type], # récupère la methode relié ce type de donnée - connection, data + game_methods[data_type], data # récupère la methode relié ce type de donnée ): return # Appelle la méthode. Si elle renvoie True, arrête le thread diff --git a/source/network/packet/PacketBoatPlaced.py b/source/network/packet/PacketBoatPlaced.py index f3864f9..3d66813 100644 --- a/source/network/packet/PacketBoatPlaced.py +++ b/source/network/packet/PacketBoatPlaced.py @@ -1,17 +1,7 @@ -from dataclasses import dataclass - -from source.network.packet.abc import SimplePacket +from source.network.packet.abc import SignalPacket -@dataclass -class PacketBoatPlaced(SimplePacket): +class PacketBoatPlaced(SignalPacket): """ A packet that signal that all the boat of the player have been placed """ - - def to_bytes(self) -> bytes: - return b"" - - @classmethod - def from_bytes(cls, data: bytes) -> "PacketBoatPlaced": - return cls() diff --git a/source/network/packet/PacketQuit.py b/source/network/packet/PacketQuit.py new file mode 100644 index 0000000..462be95 --- /dev/null +++ b/source/network/packet/PacketQuit.py @@ -0,0 +1,7 @@ +from source.network.packet.abc import SignalPacket + + +class PacketQuit(SignalPacket): + """ + A packet that is sent when the player wish to quit a game. + """ diff --git a/source/network/packet/__init__.py b/source/network/packet/__init__.py index c74e280..a6f4745 100644 --- a/source/network/packet/__init__.py +++ b/source/network/packet/__init__.py @@ -4,3 +4,4 @@ from .PacketBombState import PacketBombState from .PacketBoatPlaced import PacketBoatPlaced from .PacketSettings import PacketSettings from .PacketUsername import PacketUsername +from .PacketQuit import PacketQuit diff --git a/source/network/packet/abc/SignalPacket.py b/source/network/packet/abc/SignalPacket.py new file mode 100644 index 0000000..60c5098 --- /dev/null +++ b/source/network/packet/abc/SignalPacket.py @@ -0,0 +1,18 @@ +from abc import ABC +import socket + +from source.network.packet.abc import Packet + + +class SignalPacket(Packet, ABC): + """ + A packet that has for only usage to send a signal thanks to the type of the class. + It does not hold any other data. + """ + + def to_bytes(self) -> bytes: + return b"" + + @classmethod + def from_connection(cls, connection: socket.socket) -> "SignalPacket": + return cls() diff --git a/source/network/packet/abc/__init__.py b/source/network/packet/abc/__init__.py index cea164c..2676067 100644 --- a/source/network/packet/abc/__init__.py +++ b/source/network/packet/abc/__init__.py @@ -1,4 +1,5 @@ from .Packet import Packet +from .SignalPacket import SignalPacket from .SimplePacket import SimplePacket from .VariableLengthBytesPacket import VariableLengthBytesPacket