From 344ed9d5f69eab82ce7f1903fa210b1eb79b02a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl?= Date: Sat, 6 Jan 2024 17:45:07 +0100 Subject: [PATCH 1/6] Score --- src/plugins/writing.py | 57 ++++++++++++++++++++++ src/scenes/game.py | 93 ++++++++++++++++++++++++++++-------- src/scenes/game_over.py | 81 +++++++++++++++++++++++++++++++ src/scenes/menu.py | 7 +-- src/scenes/send_to_server.py | 86 +++++++++++++++++++++++++++++++++ src/scenes/try_again.py | 73 ++++++++++++++++++++++++++++ 6 files changed, 373 insertions(+), 24 deletions(-) create mode 100644 src/plugins/writing.py create mode 100644 src/scenes/game_over.py create mode 100644 src/scenes/send_to_server.py create mode 100644 src/scenes/try_again.py diff --git a/src/plugins/writing.py b/src/plugins/writing.py new file mode 100644 index 0000000..aea5f2f --- /dev/null +++ b/src/plugins/writing.py @@ -0,0 +1,57 @@ +""" +Definit un plugin qui crée un texte avec les touches frappées +""" + +from engine import Scene, World +from plugins.inputs import Held, Pressed +from plugins.render import Text +from plugins.sound import Sound + + +class Writing: + """ + Marque une entité comme un texte qui s'ecrit en fonction du clavier + """ + + def __init__( + self, accepted_chars: str, max_chars: int = 10, base_text: str = "" + ) -> None: + self.accepted_chars = accepted_chars + self.max_chars = max_chars + self.base_text = base_text + + +def __update(world: World): + """ + Met a jour les entitées contenant le composant Typing + """ + pressed = world[Pressed] + held = world[Held] + for entity in world.query(Writing, Text): + writing = entity[Writing] + for key in pressed: + if key == "backspace" and entity[Text] != writing.base_text: + entity[Text] = entity[Text][:-1] + world.new_entity().set(Sound("click.wav")) + if entity[Text] == "": + entity[Text] = writing.base_text + if key.startswith("["): # pavé numerique + key = key[1] + if key in writing.accepted_chars and ( + entity[Text] == writing.base_text + or len(entity[Text]) < writing.max_chars + ): + if entity[Text] == writing.base_text: + entity[Text] = key + else: + entity[Text] += key + world.new_entity().set(Sound("click.wav")) + if entity[Text] == "": + entity[Text] = writing.base_text + + +PLUGIN = Scene( + [], + [__update], + [], +) diff --git a/src/scenes/game.py b/src/scenes/game.py index 6772dca..786dcb9 100644 --- a/src/scenes/game.py +++ b/src/scenes/game.py @@ -3,7 +3,7 @@ Le jeux principale. """ from enum import Enum -from engine import Plugin, Scene +from engine import CurrentScene, KeepAlive, Plugin, Scene from engine.ecs import Entity, World from engine.math import Vec2 from plugins import physics, render @@ -20,6 +20,8 @@ from plugins.render import ( from plugins.timing import Delta, Time import random +from scenes import game_over + class GameMode(Enum): """ @@ -84,7 +86,7 @@ class Speed(int): """ -class Player1Score(int): +class Player1Score(int, KeepAlive): """ Ressource qui represente le score du joueur 1. """ @@ -108,7 +110,13 @@ class StartAnimation(float): """ -def __spawn_ellements(world: World): +class Wall: + """ + Composant qui represente les mur du haut et du bas + """ + + +def __spawn_elements(world: World): """ La fonction permet de initializer les ellements de la scene. """ @@ -141,6 +149,9 @@ def __spawn_ellements(world: World): Scale(Vec2(render.WIDTH, 10)), Position(Vec2(0, render.HEIGHT)), physics.Solid(), + (Wall(), physics.CollisionHandler(__bounce_on_top_or_bot_wall)) + if world[GameMode] == GameMode.ONE + else None, ) # Mon mur du haut @@ -149,6 +160,9 @@ def __spawn_ellements(world: World): Scale(Vec2(render.WIDTH, 10)), Position(Vec2(0, 0)), physics.Solid(), + (Wall(), physics.CollisionHandler(__bounce_on_top_or_bot_wall)) + if world[GameMode] == GameMode.ONE + else None, ) # Joueur 1 @@ -188,16 +202,28 @@ def __spawn_ellements(world: World): # Initialisation des scores world.set(Player1Score(0), Player2Score(0)) - world.new_entity().set( - TextBundle( - "0 - 0", - 10, - 50, - position=Vec2(render.WIDTH / 2, 75), - origin=Vec2(0.5), - ), - Score(), - ) + if world[GameMode] == GameMode.TWO: + world.new_entity().set( + TextBundle( + "0 - 0", + 10, + 50, + position=Vec2(render.WIDTH / 2, 75), + origin=Vec2(0.5), + ), + Score(), + ) + else: + world.new_entity().set( + TextBundle( + "0", + 10, + 50, + position=Vec2(render.WIDTH / 2, 75), + origin=Vec2(0.5), + ), + Score(), + ) def __spawn_ball(world: World): @@ -238,6 +264,18 @@ def __bounce_on_player(a: Entity, b: Entity): a[physics.Velocity] = a[physics.Velocity].normalized * min( (speed * 1.1), 1000.0 ) + if Player1 in b and Ball in a: + if b.world[GameMode] == GameMode.ONE: + a.world[Player1Score] += 100 + __update_scores(a.world, b) + return True + + +def __bounce_on_top_or_bot_wall(a: Entity, b: Entity): + if Ball in b and Wall in a: + if b.world[GameMode] == GameMode.ONE: + a.world[Player1Score] += 20 + __update_scores(a.world, a) return True @@ -247,8 +285,12 @@ def __bounce_on_left_wall(a: Entity, b: Entity): """ if Ball in b: world = a.world - world[Player2Score] += 1 - __update_scores(world, b) + if world[GameMode] == GameMode.TWO: + world[Player2Score] += 1 + __update_scores(world, b) + else: + world[CurrentScene] = game_over.GAME_OVER + return False return True @@ -259,7 +301,10 @@ def __bounce_on_right_wall(a: Entity, b: Entity): """ if Ball in b: world = a.world - world[Player1Score] += 1 + if world[GameMode] == GameMode.TWO: + world[Player1Score] += 1 + else: + world[Player1Score] += 1000 __update_scores(world, b) return False return True @@ -376,11 +421,17 @@ def __update_scores(world: World, ball: Entity): La fontion permet de mettre a jour les scores. """ - # met a jour le score du joueur 1 et 2 - for panel in world.query(Score): - panel[Text] = f"{world[Player1Score]} - {world[Player2Score]}" + if world[GameMode] == GameMode.TWO: + # met a jour le score du joueur 1 et 2 + for panel in world.query(Score): + panel[Text] = f"{world[Player1Score]} - {world[Player2Score]}" - ball.destroy() + ball.destroy() + else: + for panel in world.query(Score): + panel[Text] = f"{world[Player1Score]}" + if Ball in ball: + ball.destroy() if world.query(Ball) == set(): __animation(world, 3) @@ -421,7 +472,7 @@ def __update_animation(world: World): __SCENE = Scene( - [__spawn_ellements], + [__spawn_elements], [__update_move, __update_animation], [], ) diff --git a/src/scenes/game_over.py b/src/scenes/game_over.py new file mode 100644 index 0000000..57dfc12 --- /dev/null +++ b/src/scenes/game_over.py @@ -0,0 +1,81 @@ +from engine import CurrentScene, KeepAlive, Scene +from engine.ecs import Entity, World +from engine.math import Vec2 +from plugins import render +from plugins.click import Clickable +from plugins.hover import HoveredTexture +from plugins.render import ( + SpriteBundle, + TextBundle, +) +from plugins.sound import Sound +from scenes import game, send_to_server, try_again + + +def __spawn_elements(world: World): + world.new_entity().set( + TextBundle( + "Game Over", 0, 100, position=Vec2(render.WIDTH / 2, 250), origin=Vec2(0.5) + ) + ) + world.new_entity().set( + TextBundle( + "Voulez vous enregistrer votre Score ?", + 0, + 50, + position=Vec2(render.WIDTH / 2, 350), + origin=Vec2(0.5), + ) + ) + world.new_entity().set( + TextBundle( + f"{world[game.Player1Score]}", + 0, + 50, + position=Vec2(render.WIDTH / 2, 450), + origin=Vec2(0.5), + ) + ) + button_name = ["one_player", "two_player"] + for i, name in enumerate(button_name): + __create_button(world, i, name) + + +def __create_button(world: World, i: int, name: str): + """ + Ajoute un bouton au monde. + """ + world.new_entity().set( + SpriteBundle( + f"button_{name}.png", + position=Vec2(450 + 540 * i, render.HEIGHT / 2 + render.HEIGHT / 8), + order=1, + origin=Vec2(0.5), + ), + HoveredTexture( + f"button_{name}.png", + f"button_{name}_hover.png", + ), + Clickable(lambda world, entity: __on_click_butons(world, entity, name)), + ) + + +def __on_click_butons(world: World, _entity: Entity, name: str): + """ + Fonction qui s'execute quand on clique sur un bouton. + """ + match name: + case "one_player": + world[CurrentScene] = send_to_server.SEND + case "two_player": + world[CurrentScene] = try_again.TRY_AGAIN + case _: + pass + world.new_entity().set(KeepAlive(), Sound("click.wav")) + + +GAME_OVER = Scene( + [__spawn_elements], + [], + [], +) diff --git a/src/scenes/menu.py b/src/scenes/menu.py index cd7bb9b..e39005b 100644 --- a/src/scenes/menu.py +++ b/src/scenes/menu.py @@ -11,7 +11,8 @@ from plugins import render from plugins.click import Clickable from plugins.hover import HoveredTexture from plugins.render import SpriteBundle -from scenes import game +from plugins.timing import Time +from scenes import game, send_to_server def __create_button(world: World, i: int, name: str): @@ -51,8 +52,8 @@ def __spawn_elements(world: World): """ Ajoute les éléments du menu dans le monde. """ - - world.new_entity().set(Sound("music.mp3"), KeepAlive(), Loop()) + if world[Time] < 1: + world.new_entity().set(Sound("music.mp3"), KeepAlive(), Loop()) world.new_entity().set(SpriteBundle("background_menu.png", -5)) diff --git a/src/scenes/send_to_server.py b/src/scenes/send_to_server.py new file mode 100644 index 0000000..7f9c268 --- /dev/null +++ b/src/scenes/send_to_server.py @@ -0,0 +1,86 @@ +from plugins import writing +from engine import Plugin +from engine.ecs import Entity, World +from engine.math import Vec2 +from plugins import render +from plugins.click import Clickable +from plugins.hover import HoveredTexture +from plugins.render import SpriteBundle, Text, TextBundle +from plugins.writing import Writing +import requests as rq +from scenes import game + +IP = "pong.cocosol.fr" + + +def new_score(world: World, e: Entity): + e.remove(Clickable) + name = world.query(Writing).pop() + + try: + post = {"name": name[Text], "score": world[game.Player1Score]} + print(post) + rq.post(f"https://{IP}/new_score", post) + except: + print("Error with the serveur") + + +def get_scores(): + try: + return rq.get(f"https://{IP}/data").json() + except: + print("Error with the serveur") + + +def __spawn_elements(world: World): + """ + Ajoute les éléments du menu dans le monde. + """ + + world.new_entity().set(SpriteBundle("background.jpg", -5)) + world.new_entity().set( + TextBundle( + "Quel est votre pseudo ?", + 0, + position=Vec2(render.WIDTH / 2, 350), + origin=Vec2(0.5), + ), + ) + world.new_entity().set( + TextBundle( + "...", + 0, + 50, + position=Vec2(render.WIDTH / 2, 650), + origin=Vec2(0.5), + ), + Writing( + "azertyuiopqsdfghjklmwxcvbn0123456789_-/", + 10, + "...", + ), + ) + + world.new_entity().set( + SpriteBundle( + f"button_one_player.png", + position=Vec2(render.WIDTH / 2, render.HEIGHT / 2), + order=1, + origin=Vec2(0.5), + ), + HoveredTexture( + f"button_one_player.png", + f"button_one_player_hover.png", + ), + Clickable(new_score), + ) + + +SEND = ( + Plugin( + [__spawn_elements], + [], + [], + ) + + writing.PLUGIN +) diff --git a/src/scenes/try_again.py b/src/scenes/try_again.py new file mode 100644 index 0000000..929643e --- /dev/null +++ b/src/scenes/try_again.py @@ -0,0 +1,73 @@ +""" +La scène du menu principal du jeu. + +Dans cette scène nous pouvons choisir le mode de jeu. +""" +from plugins.sound import Sound +from engine import CurrentScene, KeepAlive, Scene +from engine.ecs import Entity, World +from engine.math import Vec2 +from plugins import render +from plugins.click import Clickable +from plugins.hover import HoveredTexture +from plugins.render import SpriteBundle, TextBundle +from scenes import game, menu + + +def __create_button(world: World, i: int, name: str): + """ + Ajoute un bouton au monde. + """ + world.new_entity().set( + SpriteBundle( + f"button_{name}.png", + position=Vec2(450 + 540 * i, render.HEIGHT / 2), + order=1, + origin=Vec2(0.5), + ), + HoveredTexture( + f"button_{name}.png", + f"button_{name}_hover.png", + ), + Clickable(lambda world, entity: __on_click_butons(world, entity, name)), + ) + + +def __on_click_butons(world: World, _entity: Entity, name: str): + """ + Fonction qui s'execute quand on clique sur un bouton. + """ + match name: + case "one_player": + world[CurrentScene] = menu.MENU + case "two_player": + world[CurrentScene] = game.ONE_PLAYER + case _: + pass + world.new_entity().set(KeepAlive(), Sound("click.wav")) + + +def __spawn_elements(world: World): + """ + Ajoute les éléments du menu dans le monde. + """ + + world.new_entity().set(SpriteBundle("background.jpg", -5)) + world.new_entity().set( + TextBundle( + "Voulez vous changer\nde mode de jeu ?", + 0, + position=Vec2(render.WIDTH / 2, 350), + origin=Vec2(0.5), + ), + ) + scenes_name = ["one_player", "two_player"] + for i, name in enumerate(scenes_name): + __create_button(world, i, name) + + +TRY_AGAIN = Scene( + [__spawn_elements], + [], + [], +) -- 2.43.4 From ddc1eee65dbebb78f5097cecea590a6e80e836ee Mon Sep 17 00:00:00 2001 From: CoCoSol007 Date: Sat, 6 Jan 2024 17:55:36 +0100 Subject: [PATCH 2/6] ajout list des best dans le menu --- src/scenes/menu.py | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/scenes/menu.py b/src/scenes/menu.py index e39005b..35bfff6 100644 --- a/src/scenes/menu.py +++ b/src/scenes/menu.py @@ -10,9 +10,20 @@ from engine.math import Vec2 from plugins import render from plugins.click import Clickable from plugins.hover import HoveredTexture -from plugins.render import SpriteBundle +from plugins.render import SpriteBundle, TextBundle from plugins.timing import Time -from scenes import game, send_to_server +from scenes import game +import requests as rq + +IP = "pong.cocosol.fr" + + +def get_scores(): + try: + return rq.get(f"https://{IP}/data").json() + except: + print("Error with the serveur") + return ["", 1] def __create_button(world: World, i: int, name: str): @@ -61,6 +72,23 @@ def __spawn_elements(world: World): for i, name in enumerate(scenes_name): __create_button(world, i, name) + __spawn_score(world) + + +def __spawn_score(world: World): + """ + Ajoute le score dans le monde. + """ + for i, score in enumerate(get_scores()): + world.new_entity().set( + TextBundle( + score[1] + " : " + str(score[0]), + position=Vec2(render.WIDTH / 2, 350 + 50 * i), + origin=Vec2(0.5), + order=1, + ) + ) + MENU = Scene( [__spawn_elements], -- 2.43.4 From 6dbf73326274ea06a87876c56e2fcda075579495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl?= Date: Sat, 6 Jan 2024 18:11:50 +0100 Subject: [PATCH 3/6] Finish --- src/plugins/timing.py | 21 +++++++++++++++++++- src/plugins/writing.py | 3 +-- src/scenes/menu.py | 2 +- src/scenes/send_to_server.py | 15 +++++++++++---- src/scenes/thanks.py | 37 ++++++++++++++++++++++++++++++++++++ 5 files changed, 70 insertions(+), 8 deletions(-) create mode 100644 src/scenes/thanks.py diff --git a/src/plugins/timing.py b/src/plugins/timing.py index cfdbdcf..7be3474 100644 --- a/src/plugins/timing.py +++ b/src/plugins/timing.py @@ -5,8 +5,9 @@ lancement du jeu et le temps depuis la dernière frame. from time import time +from typing import Callable from engine import GlobalPlugin, KeepAlive -from engine.ecs import World +from engine.ecs import Entity, World class GlobalTime(KeepAlive, float): @@ -34,6 +35,16 @@ def __initialize(world: World): world.set(GlobalTime(time()), Time(0.0)) +class TimedEvent: + """ + Composant permettant d'executer un callback après un certain temps. + """ + + def __init__(self, timer: float, callback: Callable[[World, Entity], object]): + self.timer = timer + self.callback = callback + + def __update(world: World): """ Met à jour les ressources de temps. @@ -43,6 +54,14 @@ def __update(world: World): world[GlobalTime] = now world[Time] += delta + # On met à jour les `TimedEvent` + for entity in world.query(TimedEvent): + event = entity[TimedEvent] + event.timer -= delta + if event.timer <= 0: + del entity[TimedEvent] + event.callback(world, entity) + PLUGIN = GlobalPlugin( [__initialize], diff --git a/src/plugins/writing.py b/src/plugins/writing.py index aea5f2f..982193a 100644 --- a/src/plugins/writing.py +++ b/src/plugins/writing.py @@ -3,7 +3,7 @@ Definit un plugin qui crée un texte avec les touches frappées """ from engine import Scene, World -from plugins.inputs import Held, Pressed +from plugins.inputs import Pressed from plugins.render import Text from plugins.sound import Sound @@ -26,7 +26,6 @@ def __update(world: World): Met a jour les entitées contenant le composant Typing """ pressed = world[Pressed] - held = world[Held] for entity in world.query(Writing, Text): writing = entity[Writing] for key in pressed: diff --git a/src/scenes/menu.py b/src/scenes/menu.py index e39005b..2575037 100644 --- a/src/scenes/menu.py +++ b/src/scenes/menu.py @@ -12,7 +12,7 @@ from plugins.click import Clickable from plugins.hover import HoveredTexture from plugins.render import SpriteBundle from plugins.timing import Time -from scenes import game, send_to_server +from scenes import game def __create_button(world: World, i: int, name: str): diff --git a/src/scenes/send_to_server.py b/src/scenes/send_to_server.py index 7f9c268..c0868cb 100644 --- a/src/scenes/send_to_server.py +++ b/src/scenes/send_to_server.py @@ -1,14 +1,15 @@ from plugins import writing -from engine import Plugin +from engine import CurrentScene, Plugin from engine.ecs import Entity, World from engine.math import Vec2 from plugins import render from plugins.click import Clickable from plugins.hover import HoveredTexture from plugins.render import SpriteBundle, Text, TextBundle +from plugins.timing import TimedEvent from plugins.writing import Writing import requests as rq -from scenes import game +from scenes import game, thanks IP = "pong.cocosol.fr" @@ -21,6 +22,12 @@ def new_score(world: World, e: Entity): post = {"name": name[Text], "score": world[game.Player1Score]} print(post) rq.post(f"https://{IP}/new_score", post) + world.new_entity().set( + TimedEvent( + 1, + lambda world, entity: world.set(CurrentScene(thanks.THANKS)), + ) + ) except: print("Error with the serveur") @@ -51,7 +58,7 @@ def __spawn_elements(world: World): "...", 0, 50, - position=Vec2(render.WIDTH / 2, 650), + position=Vec2(render.WIDTH / 2, 475), origin=Vec2(0.5), ), Writing( @@ -64,7 +71,7 @@ def __spawn_elements(world: World): world.new_entity().set( SpriteBundle( f"button_one_player.png", - position=Vec2(render.WIDTH / 2, render.HEIGHT / 2), + position=Vec2(render.WIDTH / 2, 600), order=1, origin=Vec2(0.5), ), diff --git a/src/scenes/thanks.py b/src/scenes/thanks.py new file mode 100644 index 0000000..0d58cf5 --- /dev/null +++ b/src/scenes/thanks.py @@ -0,0 +1,37 @@ +from engine import CurrentScene, Scene +from engine.ecs import World +from engine.math import Vec2 +from plugins import render +from plugins.render import SpriteBundle, TextBundle +from plugins.timing import TimedEvent +from scenes import menu + + +def __spawn_elements(world: World): + world.new_entity().set(SpriteBundle("background.jpg", -5)) + world.new_entity().set( + TextBundle( + "Merci,", + 0, + 150, + position=Vec2(render.WIDTH / 2, render.HEIGHT / 2 - 75), + origin=Vec2(0.5), + ), + TimedEvent(3, lambda world, entity: world.set(CurrentScene(menu.MENU))), + ) + world.new_entity().set( + TextBundle( + "Votre score a bien été envoyé !", + 0, + 100, + position=Vec2(render.WIDTH / 2, render.HEIGHT / 2 + 75), + origin=Vec2(0.5), + ), + ) + + +THANKS = Scene( + [__spawn_elements], + [], + [], +) -- 2.43.4 From 8c6e5c55fa993ab8f52cd8d72faec37999b7c6f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl?= Date: Sat, 6 Jan 2024 19:02:47 +0100 Subject: [PATCH 4/6] affichage des best score --- src/plugins/writing.py | 7 +++++++ src/scenes/menu.py | 24 +++++++++++++++++------- src/scenes/send_to_server.py | 2 +- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/plugins/writing.py b/src/plugins/writing.py index 982193a..0be2540 100644 --- a/src/plugins/writing.py +++ b/src/plugins/writing.py @@ -36,6 +36,13 @@ def __update(world: World): entity[Text] = writing.base_text if key.startswith("["): # pavé numerique key = key[1] + match key: + case "6": + key = "-" + case "8": + key = "_" + case _: + pass if key in writing.accepted_chars and ( entity[Text] == writing.base_text or len(entity[Text]) < writing.max_chars diff --git a/src/scenes/menu.py b/src/scenes/menu.py index 35bfff6..0c88bd3 100644 --- a/src/scenes/menu.py +++ b/src/scenes/menu.py @@ -18,12 +18,12 @@ import requests as rq IP = "pong.cocosol.fr" -def get_scores(): +def get_scores() -> list[tuple[int, str]]: try: return rq.get(f"https://{IP}/data").json() except: print("Error with the serveur") - return ["", 1] + return [(1, "")] def __create_button(world: World, i: int, name: str): @@ -33,7 +33,7 @@ def __create_button(world: World, i: int, name: str): world.new_entity().set( SpriteBundle( f"button_{name}.png", - position=Vec2(450 + 540 * i, render.HEIGHT / 2), + position=Vec2(450 + 540 * i, 11 * render.HEIGHT / 16), order=1, origin=Vec2(0.5), ), @@ -79,12 +79,22 @@ def __spawn_score(world: World): """ Ajoute le score dans le monde. """ - for i, score in enumerate(get_scores()): + print(get_scores()) + for i, (score, name) in enumerate(get_scores()): world.new_entity().set( TextBundle( - score[1] + " : " + str(score[0]), - position=Vec2(render.WIDTH / 2, 350 + 50 * i), - origin=Vec2(0.5), + f"{name}", + position=Vec2(render.WIDTH / 2 - 350, 325 + 50 * i), + origin=Vec2(0), + order=1, + ) + ) + + world.new_entity().set( + TextBundle( + f"{score}", + position=Vec2(render.WIDTH / 2 + 350, 325 + 50 * i), + origin=Vec2(1, 0), order=1, ) ) diff --git a/src/scenes/send_to_server.py b/src/scenes/send_to_server.py index c0868cb..1929537 100644 --- a/src/scenes/send_to_server.py +++ b/src/scenes/send_to_server.py @@ -63,7 +63,7 @@ def __spawn_elements(world: World): ), Writing( "azertyuiopqsdfghjklmwxcvbn0123456789_-/", - 10, + 16, "...", ), ) -- 2.43.4 From f95c89f628b23030ab857c21560d5e3331e94319 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl?= Date: Sun, 7 Jan 2024 02:09:19 +0100 Subject: [PATCH 5/6] Nouveaux bouons + ajouts commentaires --- assets/textures/button_menu.png | Bin 0 -> 6752 bytes assets/textures/button_menu_hover.png | Bin 0 -> 6986 bytes assets/textures/button_no.png | Bin 0 -> 5681 bytes assets/textures/button_no.png~ | Bin 0 -> 5881 bytes assets/textures/button_no_hover.png | Bin 0 -> 5936 bytes assets/textures/button_one_player.png | Bin 7542 -> 8078 bytes assets/textures/button_one_player_hover.png | Bin 8430 -> 8534 bytes assets/textures/button_one_player_hover.png~ | Bin 0 -> 8430 bytes assets/textures/button_submit.png | Bin 0 -> 7627 bytes assets/textures/button_submit_hover.png | Bin 0 -> 7937 bytes assets/textures/button_two_player.png | Bin 8924 -> 8658 bytes assets/textures/button_two_player.png~ | Bin 0 -> 8924 bytes assets/textures/button_two_player_hover.png | Bin 8469 -> 9058 bytes assets/textures/button_two_player_hover.png~ | Bin 0 -> 8469 bytes assets/textures/button_yes.png | Bin 0 -> 5797 bytes assets/textures/button_yes_hover.png | Bin 0 -> 5864 bytes src/scenes/game.py | 13 +++++++++++-- src/scenes/game_over.py | 6 +++--- src/scenes/send_to_server.py | 4 ++-- src/scenes/try_again.py | 6 +++--- 20 files changed, 19 insertions(+), 10 deletions(-) create mode 100644 assets/textures/button_menu.png create mode 100644 assets/textures/button_menu_hover.png create mode 100644 assets/textures/button_no.png create mode 100644 assets/textures/button_no.png~ create mode 100644 assets/textures/button_no_hover.png create mode 100644 assets/textures/button_one_player_hover.png~ create mode 100644 assets/textures/button_submit.png create mode 100644 assets/textures/button_submit_hover.png create mode 100644 assets/textures/button_two_player.png~ create mode 100644 assets/textures/button_two_player_hover.png~ create mode 100644 assets/textures/button_yes.png create mode 100644 assets/textures/button_yes_hover.png diff --git a/assets/textures/button_menu.png b/assets/textures/button_menu.png new file mode 100644 index 0000000000000000000000000000000000000000..e84924d13f025cbea763ba4fdefcbbab072ecfe6 GIT binary patch literal 6752 zcmch5^;^?#*!F+{gDH%bZjlaY1!43M5c~q88Pe$}>D=g&mQ+-v86A?NOOzIrP7w(~ zLF)PNJpaJ^)4Su?_BnR!zV7S3;=Ir6jD4c3ahsfp90UU0*3wip0D%aEfafp>3Gi7n z_1}NM7uj=76E6@*g!|@A;P?KKF9^g$t);5`pP%KP1zEG<nWRPh6b^f=wG}Cb%{O4<6 zyUT21-S}DixR-pB*No-4MQ6jG{kC0;{QzUBG^P1^r#iL0`Gy6fa-+(H94VJpS~@zP zl#v(d#wz~Psm2Z9>6&{~9E4}dUGh#gXRSWFnSRA5jq$rXPsV*1A_d8I<%7 z4LbQTEh_0ewN1)dJ#E@ksXAF^Sf1mvJELGCz$jEre^kaTQ>v?th|E}`A>ew=$zj`I zdioB&=rD9%2lyM{+n>N#=Q^uKZKS28RmrQJS)YdZls+qN&^>chrd%}98g{b|M*s<{ z56Rda#&}$L{5#%B?wclX;a6GyKz%)>?70#;!Vo=j?t7$L?o1RAo&_V|TE=wQT+=8{U?O+ zu?M35@r>LbV`yo4WpzZnS^;ZS;v`fJgRB!0KJVSJA)P2&S>)ujPyn`&22WU^4er;0_*94+c+yWY1^1;>D>2F1bFstp;lRkdQskDA31 z)>S0+Rh|{OB@}>@ii8Ugy@qs!Xq}awAN3*J_gDUJPcA|q?At~vyfYczS#MW>;XFp3 zihv8I^cs2P9$hk#iNQjEoTRKlBwsqAL{D*zZ?G9_7HTIkO5xlb53w^5l zK|o|ZSqN76Z6)0ko{;ogZumLqD*!*TH9vcT^{@2hhBn9W$9$mr?_>=)W%iaMz z*St;0Q!(XDN5>1q0n;ablOtys2kL!sdC5)v^9Uso0G13QL1cnb7HVp-ASw5hN^0*C-v{If6!EPRSX36Ib**4GD?Xd+pNfY81pA)q#LZjFnh2JGNh?{E;R za!3KY8%!Ghmk#(vO+NsbBrH`9!(`-C6%_$X4(hi$QMaZl&1UPJCi^8_=ROZ=Eo_!o zcSr!mb;kT_)C?AW0T078ke%20|K8k;fQpEn?==;cTDAxD=NCVIWfOIa(I!*atdUI0 zdRmpE6IL?Q;-HvO*5Lq|(1R&Fif{^OBMVV!(=pHZOmMw1_1Irb;9x>yFEOb;^u z`SpFlJaDhU{`Z(nvf=jIWJQUs{1*i;xf3c7vsD%g-a8Y0k}fl&+#OgbLr!h2#C|>; zOio5XojI|$47ofp_F4`nwGR$CU5U;`^+eePUF|h3<>dR$^Ow6`UtNxo zvIoIR`{>PFSEx*vI)dwdQKkkS_A!jbP;rm$cV1g+KFf3ywgzu|8_Rb-8%TO-iyc`` zbN>8VS^ajUX@kV9#S4pmhu>S{e~Ux)Yxg_O)k8Xde|nI6xHga*a`{hf(JJYoga!*5 z!+765q0|tn(WoDzbj7WNH~4p_7nN4o)E{1d{Zd=BUDAa~)_eQO@2$d6b)&lPz6*B2 zi>*E`UQ5A$U%54QzxftQRwXJdJSMR4MuqhL^X0A!_EJ|)Dj1OBVX+vl^kv@c#>#|1JiKj!^%G5^Iqab~`gG1k{tw#E&ZnP%55UziZ?x@UtOlLEF-V z2dRZ&-XFWB-POta*P;38UHf)XeC_a}&#c9wgPB`{p{;^Wu5{%E%VgVbb>|{x|7`AA zvj3F;Mn#p3<#2$-D zB4NOaF~?jw>2il*W0c~6R^rd!FnfgVQ<6Tgzy|9BCzYsk7&jt=Vn{tz@{IlZ&_AY1 zP0*Io!Mz);S2&q^%9thPJaw;@3H%1%D!=nCtyZYs z%)NzIuw;rpCN71XoNCYk$OmE{PvuSnPXARmuE?miIhO07cy+p#Fuq!hISB85L01sa zarJL^GhVb~u(cr(S5G$<#5U+^h64I_evqG&>wC{RxG?aSTx6-`lhq4tj*7M9M~d3< zWHfhegGpS*rFm5~!C1)peZp@S6~|SZ-UHHkue;b!E`E*IKTvdm~%O1W#p}dC{GP8rE&9ozcYCX!CldOM|f5|l9=SN-iikis;e`q zYZ|y|n~h%TQ)C*T(KQajc=%DI>m~eqtIzLR9dNKmvsL!8_INk9FLE@9FtjcO~=w@Ig@0NG##pzwsQ`Fs0_mI`B!-3 zb7HyFQnp7#J6+jAFVG(_kpLQHwH)A~x22QLF_g7Aa$dzPYe^4ot&ZRXLE#O`oh-Nq z=RfPl0Id4)QX47KvQ7;^!9LHYnYenzrtiMFU(o}sbw9w1ktDa{zUQ%F?+;cRS6i~# zFL-peXXy}qgaIf;8ae%)^3jEu!mShuofbriclKrvxh2K5p`QgG9)|oZVQd66$h+F zGB3XS7!yr&w^Kc%=Mh9coQo%$xLi-u<60nacqkpfM^`T#SMfv-xVsagTuwtEv?PaY zfj?{P|9*cV1DR7(;LCd+(E>osy4XTgIYZOW{ykM5El%V zUAU##tioabx0{sRwSKPoKx#hyp@7_5H>4xjVIgYc)VvmX3%~fVaWZ_YLzGPY0$6KW$m z6J$ui-{(F!63LOlPLijHT*nhf3R@W2g?jd?8d;E`rUy+zXv8!GPDbuI(t~2-(-NlN zrfvH$L$T2Q);nTt>8@5t`V&3#$N8a@!j`}GgSvk2S@H;JC*L*U>>Xy4hDQ@eGM5{O z5PtB^Q(_o1n51|gc0G`(OxN-ec1=s)tAc$G&|5<|63DNek#3+Y&Mjh;R!g-mCiVFK zukz_ERhdkkC=gkB90aPpuAj=Y0cBg1RaTfM?1~_U+EhosWoG1D1<%@G1rbF;5(`sO zS{Qlh*ys@#dQ$_urm1Bh#u_!R%57d562hMRzjg!#@(2uFYMx&0p}txp==tWoVQ5{n z|C&But@0e3c?G??Neo24iyZkx%r2f=CfzHMRHdZHrMf+H+E%#8iu;!}HpKN+BDiRt z)tIfk5OBZ2bNFauWJoR-LeP&g3Dc2CSrZZ(3te4e6MUx6Npy;0vBUjRb z@H+jzcPge(h}b`?tRZ)h7Fsf_d}!+ds!VkWEyxJ=p@lFP(pY3qMKk6u$KBo*V!PpV z{&_p%YXvfGMnXToYYO}X5HGarxuJ$+qmEK$w`@tGzd*p>UwhtX9-Wt)cF$s{6LIGG z^Eey#&P!iIb_OVPa-BQ*p+P0o*6ufN5#hGajERHY6!wlhc*Ec)TVn)6goVR~fp{m{1-uLiCH57;?#WW@BuGK$-om)P_sENy>WVn5(~?KB@aAKe@{x3CQs8NfB>L4+gi`W@U$T_~ z`+<+ErFLekt<zNLz6Ych%xIcV1gZM?$~I zMdl6=YatO^tw>~}l2%rDmE5;CMfN^(5N+m8t<00PA9$5~o)2x6W2Ru@?Lvmk~aFAi7c z=3{ndUpW-)NUy%5En0WWjEQ>HIK&(xIeUAM>5SE9O25p9*|j+l2V0Gx!AC~0L(O1S z_e+QkQZRYFzBz1wuwyG#o8NKnsV9}6vAvC>>h!rt=bykY3FM3+2e*QtEkEI;J z8eSaqP%=<2xq6#vA;~d0J`p2snD@j?cu!CNFe&IrBU7o|iBzFJi)suXT%rR<=QNTN z*D6^)ss3p@S$6l<`31hEv7V3TQ)qO^gRMNT`jNVhWM*hIt1oiK9ShKDkLMj1y>S~u z#5_Xpxh+^Gm{pKS)`_6UB2VGWC?~o8hQw(!th%U|Mdx~o2$?JiI}~k1@E5lGfiY}Hm;ukP5iaw(rH=4ryNRLn~#CM6hcI{V8rWi9+Q&F!>nVX9A<) z25_EpsE0v6iF2=}6V<}}roGvq%G4_1akscNs#}>VM?@bS)5D9G>q^lfa?o`aOkdfN zq9=gS&^K1G1#EM=Z6BUPz>X;X9{k3(kZ|UJFVq;S?UfhZ6oA<$3)RZw5aP`HEl?#? z>@`=&(6K~B`OtbX_^-vj#Mn~t*{CZ$C!7dBSv4Z^aa22&hW2M--b4S|RyfmLB_y1P zlw#Cb@y}WJ3;Hbe!A=fGt+TWJp1;k9{mh1|+-7PwELlA&9=m~%*KhJ{pYatV`r)?N z)^Z{Vl(&C>KtbWi49&wZzd1bF&w`MDPF}zmXC$p>_GRkGVk}#n`%idOk7DyQ*@!g=Nuvfobo&0kTc5 zZfeabGC+`nE|PPy_<)(;bd>$>7D%$P-WO+idTeLqktgFgGMNieth_hy;}xsQu5Sq)%N=G@81sjpmo;Xvo4P%WP@ba8Jd~CzA15yxS0Y{n@!sLfXF=WL_%BeLW1jhUQ zw-_aO-aqNHoZs<3xM50|<(0a#60yq~9cE=}bOh)=zta7e$(28xqJxZGhb|E34JE~vFqHSFBzkhr&eo9du576D( z;*6PpiA&d502dj_aBTRkBVy4SVu>Oao7B}}O=%ZCgs?EjBo_BX^hY;ht{J^nTP&kV zaM91~;U{Qw+5rq9886p>SvbFCC5pL?`|BD-qS|HGs5-SNNBNR3M#g$!9GKYKY(r5a zut)TR-XNBmGkF0{4)1U)0e69fKsDlAyi;<<=X>GU7(*?LPw&PFys-0lLYpKvUn7}q zkJd%QV1nxZB#M9fr05(I&nNP8)Zz5h8~o~42Ddo8X8?(X`Ko?cR3 zrf|9vW=9r5B6ogCHXwgtmwkomo8(P@U*>J2Fa(sT+$z>w&kscPI@T%x=+FbP!G_nm z17@;xk)k~Ab>bDbS!7pgrw4ZI{VfM6fACuF>^QQ)SLTeL)9Pi5b=Mph3zBHaa7}*n z-btl;LEK56v|QB8tyJVWAYhD`zz=5>XqJ!`n+#Tv72dI_SeE(1HA=G>(HE=qiBkzG zxYgRL!zr6@VblA~`58Y~3I+JiOiEHnQ6?ZhL4Xre5dHs_yZ|+h}RJA8KNZ5zWa9k$65ZG1rMoUvtqG+(VTP+&5UU*g{t{1AS)}*g>^S=uL;X+d$ zzT+!Zyuh4tR}@WnJqJ#eqT}+`Q#_;7m+b#FmjbaSX;!toAHUwaJR~7(Zk8g3`*Ne? z5rn^&pt&&8{c%N$ISF^XXiu5Rk#y8$1vJ5XLf~arhT0q>BcsL&$Ia1K+IH@zc}iUe zQFta&S7E9_fA9>m0egHAJARgeoxV6yFMdd>(8%c1Uv@ekLSk&#!9>N0?FlQ>FSS;H zYF*#=&*iZa5xpllhXhjLNlzgDdRVPxwhWkA|LlAytSaHDn3$MY+IXag2=`cT=W;Mp z>I33;j|bcVMrCAW11Rfcw#JWE%TS!Rp^X`kbv8n=JT~+8fRq0Y z>v~=vy=%RW4r;DKuk}y%5p*^LHAc4m*s^3UxzV7pVPT_xt}OKR4RK%)waGkJK9jOA1}yn7?+F0y*?^Zi@$EY%+>mQx{W9gaI0NwpjRM^1?OUoJb=&JK5N6c-$-fA^HmP;tzLdIjU zEiN@RmDmP7)=lE%&xxyVY;zuRsSB;}X%hzybQT7x;Db%?9x?GfaKBq&+VF$>(4;Sw zj%m+U+y@Y%kPsJ2RA<4_qV8hu(7BQ4W#-Wf1^;UP>tycEAW)VYAm3UOQ6V3F?QU9^2%wGP*RP$uBWO@(0gWC@9R-i67UG_EWQ26xj!S|&5klC^S_n@;#%QRhKPS?1^xEB1iOI^v8)6w8UOfvDMzSXROxh5D7J+)UK+%SM1s%W)(#dqxPs-Ev5D zXYq~C_t)!l!!(;xZ166(IZN6hh+K3*zu+Vx;g(kM)OJzs< zcqZzG8>(4*HbrbDh`ZBeym}e*MuJNmb>o&2E5M|dnrEmTc0Y!?kk;PtqP=~`f9?Ea zX2Im|h3DF~--&Gdsn7h{_`Ksq;KJ$ENz43kg%_GpLoO}t+ao8wn`v|R2P0gR>>ZDsA%7(SnWK97#rhSJx3m+IU9( z95gGs;!*zMm=E;`V=Lc8)6ioD&ak3)Q3y?T05ll* zuK^?jlhb^rCc$2Qz=x7SvhrHwgR(7XIaCOvI)Yg6p}ZYb3!=>0P0cF`6I$PS=Qye z$cQ^33WO)J!yW?}dmCOCXXiIE>@0^$zLjdoM`#H}-W^ znhKP}9F%LA23L7cHRNJ#*o;=*l2t3wG1vO z%MiRJ2UhvkJFXnJF?xm|)P@_KOun|n9sC3)R-NhI>XpPCOT-b-7b4^`Z>twgG-F_%t z?h1VWSQ9tBzw|95>t>&_#(iV-As9c42QWb%LM>YvsCV4_A*MZ(K;Bc5_h{SR#JQ=k z#JKVuqUlZHx#x+~VQ&?3HD`Z`MqXiayR2x_ z$5UL$q*in*H8uU5oIbteX;FGOIYX%j0vBgqT%7yno(F~9{oy9^+0tQZP)c)cFyn*Bi#d&s9+j=xjA%X!IyY>o@BaG=jQ2`ve4?eli93TkygpFiN9@^ zgTH(a2ci{sS{4GMb6pnd%YDv9vkJ8FX&{Nn)5I#BkB53c&dNngnb)Q|FR9vDnx!FP=K*a2pe9u=clcW%6E%d$}A%746*7K3VmcQ)vMDeuh(}>&YwEu_C=I z?#X{mFY(!?nidmc`kBvn|KzDlu(5w&*O88>~te4qV_@{l6t7~%g_rv`o7VXz-uUh`TGa^&XmnbqA;t`CbbUZFKTD98`LYgpPj4gb= z{&*)PuvKG1+F7;_h(Z;ELN?#xkv?i_nMvJyA4WN7|3@QQWvKeC^>Jl%e%*Ei?NY^;d6D-rCji;&Rq=~}n=}DtR#)Ttj#H_X z6oV%;usJ!8nClGseKYWVQs|rgFS8#nM(xoTmErD-?0_DXt2u0ApTe3p_*WCw;KbEz1$%&b;bj z3)1~(LT+W&=9D3=@Kr@X45ERu?64pP{QDEh_9OXg?4bjLv*lyJ*z(s=OIjEnv#7z-fAx>H@9BL}yRs|ORVwImP!#yOXvG<(eH^);J5~{7rk3@wF zy+IJ95d_H|yMF4nRzZghIO`-Cq_Th7&+Vg|r9$6(8qO8AW5c!_LF#wU_PYZ&Hp@2G z=i6_MDMCN~p+v~f^7@&+U_J;iFh|-sv*~8uZ@~S0)-#gzhhD>cCR*gq(+(xfbE|uP zi_zUggw~zjH&>?vq34Hn?A8J81JbkUTh<~kN85%^t;rT{{ss-PKeZrf%*;j}$=P9~MhWv4EnpBP9Q{r@Nw+!8k{#fzcL0L9 zaXTUZ7$}F|k$6hn?VgnQ1<0N^k1n#HfKf8iok3~6R zRL6OV?Jydh64%pf8X{k3Ow0G%U{pZP-PfWJFb8H-$%=3>eQrdZuKD&XL z7V`+3=!@;uTFar23jUhp%V)y8$oui;;~H&(m~6--I;V}t{G?9o1+`E&0fmAn@5e(D z(gknhq8MRP#jm#E&>GIZ<;S9~C zA!RcoL4RbOe2=@K4GnxF{$=Qj&@yrNl|}j#h4B@zii<5!u_iRXPIk-yS0rm6aGmQ2 zHdKD~MFonw=AWwo9@H@ixF_K|b4P1>J|><_^efnHPt{E0SE~7#TfRcb-R*22nl7$q z*_!LsNwjJ>t<0pz36xVp2qI%xaQU^iq5T3WMDocE?LneC^Nv?447O z;C-8@F|Necx7}R(Ni2tujGs9A-j-#&5NnetMnR0!s++r(*^=?}@qwm|*GA_gTv5)#(FI zkm!khQO2f2z_Y2p$MS||l?r>!YQTOeRw#oBKqWQgi@6`X4$gt00k^Ma8kFP%%S=yq zJ1-BEvc$glkkr~A4c&7T*WWA7^(pej1e^+&zSTY#)&l3%hXZ5{5NQItu4R z!Qm1Fz(WN58UaJXl#Ql4n@70^2@7{XY?XyeWJ?fGA?15`1zu<}Eldjt( z6%ToC?#<;j2E8=Wyh8UqOcThqECi)Vm+R4tIYauv?L_S(@0NaRyG z=E9h#PMjNzOVCjCR!F?@Ap$<*?r7d2?j2E;dOt6r>Ul|4f#dLjQxilE*2U;)HzmB~ z==4&5W*96|`%YZ% zW%=ZS25-AAFw__Pf~=8uZESxb*crzd;^&^dY33CYwtR6~*y^_?dEOClT0%~tL(a4J zeR^6f(RyzwK}pqEM1-3=6VED0yZrRlU(T{xV>uNkAIpnV33r`&jUZB>-kI0e<&TmQJ#TfxxIox2Z~m)#-{z0Z~s zFb~R|B}Na-0t6#18eePir=6LrgX`+rxtQLPODBg}LYUk3YZa>)T?6w1Vkqhdp!V4T z)-l(MO}jU5cAI3sQ|2aJioynkKP*S$%K1(`azUtvZqxJpa=eIbMfKTUtrZ&GSP*)L zrAIHhsROO^`?os9{=4Ex%=xBcrIg=poiU6-J@Ss&X&=IW-?Pq%Y=)m5=rT?&B2!63 zQrA_z$)Q6kf|j6L3T>-o5qi?!)b%h;?6y*Syz$Qp|5Kk=WY)R{PM;3=xYeR3I>+l`|jT7%P@HRejcAAW04>&2k5! z<|_UMlcs*9-H^^0i z&(!-*vlT68XfpYUmWH3?ak0`Py_9^%`Nj;)kGR;#VAB<;V;C`;FOS}C=mqISD!}!} zq77tS!9N!Ul@~tm{X2}FB2GThxN$^9Xj0|6XPgx!V~w$mJ2p1gC~l7sl+;f#%iNe6 zFfVfx;U`mqW!lYMMc-vwrjudyj5}rZ3VbkbiY$-s!Y#Wd*L2#HJ9j`}DaS19LQX@+ z{xqS=iP(wX)CV2xFNz)MC<56n6z-;7h=bw&=d*&gWE|mvF}UVR znC2~OktvheQ}hFOu@Sfxl1Ks1n=z7tCC%rt)AvX&K(nqOpyyOu_Tl{TXb5}|gDxqB zRLMO2DjWZr^exMn1GZ>!`%5j;#iRp%?UBMGcpb@gg%iM&L}2K`Wj1tZvxlw>c0kyru8=IntynZ@MVw%{~L1U zE~@}F4rQ)x%Z8(BlyUZfW-toz-!A**-W% z)yE?<4d==) zxwxHxvp?e${9ocl0FEkffy43vU!3zTEXR9ia;NK}NrknV<(6%$v;hUvVkA`Hhftpj zw>Hu0d$;;je)DcvQvL=h{iENP(8&M!TgFK4YYx3RHO>JcViwieI6guPoymvFw zd)Bj_xLf|0u$(sSDr5M6kY1b65;4c?Teq&(vNSVE62(VUpvZF(z8;<*N&BYuKM2np zjrY=f&q$HoH({N6BwKM%8i{}Zta3HBjXfqHq7`aD?ab5n4HgWI|=i_ucVC-M6=2$zok!G}B1nA z2^@b;XsLsoWs@Onv44r7q64U@!Xeea{rzt!sebv1l**&_@o*m<4Si^Znq}z!0Qa!x Af&c&j literal 0 HcmV?d00001 diff --git a/assets/textures/button_no.png b/assets/textures/button_no.png new file mode 100644 index 0000000000000000000000000000000000000000..5cfdda092f450a7f81585d91cb00f655c6867c0a GIT binary patch literal 5681 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 literal 0 HcmV?d00001 diff --git a/assets/textures/button_no_hover.png b/assets/textures/button_no_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..793de3779c1627bc577c8ee5d93ff98f7e33b5d8 GIT binary patch literal 5936 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 literal 7542 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 literal 8430 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 literal 0 HcmV?d00001 diff --git a/assets/textures/button_submit_hover.png b/assets/textures/button_submit_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..b0d7a23618dec1a8015ba2c035b7c510b55d8802 GIT binary patch literal 7937 zcmcJU^;=X?*M{j*q(i!fkfEEQQyK<|LAnHyk`iGk2M|OW2I*9qVdxg5yBWGc8Ubna z8{hZ)7v3LETxYNS?Ded@uXE16?kIg-bz&kqA`A=+VvXl2U)^$TR!CB^PM0~N z-%DIc(#$1?jT1j6ulim?9Rf)TM1B5oo1KZ*_nh(x<4l-gh*SU-)Wa`jE7 zBl3@eYCloH44$U3bOj}*YHl{E^}t702Ku>d@GLy+s7!kj)`JVgrWkp>@_xT~MU6}! zhcXlg(-FfBG~2BG33HSfNngY0AW zaBXG?1Yf*Cmq3Bc$(n#vT9Uc)ajAtEB4OhAUoylv`jw8zsUdD%^!T|1qNX^>2)e^@ zr#^I#?`jH!TDvgxW0emfO?J?&^LgJ%#~f|^<oJ*y1D#RBu<=Kg=lOgUpY!&?A z(EhMPFY@Q%YNVLPk~>BI@4ZNR=i|MfnO>vL)TEha^>3Wp|NaR$zj>82b0Z?|GCShEwE~^H|JBFLYB4JvtssUqvekO)EVNlYSX!3uH7dV)LttXz z8Q!$sd{7#k6L8!#(tda1ep}g6xvr{dKbXwpI17iO((?W_)!yj zf;{coL3Mr@+0X(STmt1EE|M?{0*;%@MzcNtVv~qI;6DMn1b6i@XFOc4EP4b}sj^Up z{)EFaT&q=&YtV&gnCb94SXnlg4QzzGYWrO}5M6cu^jr38yf;ln{@0!OLknisp}4~u zXN#SYOwam!x`}6uA8uz@c$uh2kgFk>dFMqQvZC`r4|j8om4>^cj^nW)YBxOrrv(C) z2Wn(Fq)t6O+%VEE+N-eZ&;SuT#nlqpI{Vm$qXE;GUU7gv#`~LoXZ0As9OjKg^ zo!#fldem#)npI4E6?}xUmcqKFD0J(0lA854``){7}Uc`-ft-!DF|&Re|ns;E<{b`|_R zIkZ-;TU};mB5d-SFx!V@2C+|c(>w1r4Ra9qb;z17?Nd4rKGZ`sPoDMvAjzm|zkTMX z!W?`tF}y0VV4w8UF)U6r=w=)K^isPW@bLH`ZKY9>4Q*&d=6u+a_|vk`%j4$FCnwf1 zOtK5PdGldo@Hp}c8YEA9FXwmD3f@r4 z->+exuLPXrs*9}I`hpcvfgCmY3k+EsK+J6^p* z+~JX({MNrQlR?&W`?f!Jbyu4?=WE%Y^q<-tIllWj%sqV3PE3KG(lT+Y6E@g3n@X3q zE%{=^tE-3Ir$1dSGlXIY1CCrA$Udec0@FVbQ}u2)tOSbCDyAkwggf53_i_016U(Su z@DoDq3Sm@J+UdWbpVJZ1c#7?3XG7swZWg^hi~Qo7kwP8#?K)V1@(8)Gg^qt~=-?{s zk8;)Es1+IOxpHbPGOX}ZtrYwIt*@br-J{3QSn9+qRy`zxxANlbdmWO{>!o@_yBE{z z3AIA1-Bfla@I0XEEsYt??z{|-=6&83E*GkE zQa~aP)H&4uMK_OZ!2&p{9pq4i3);Tvi?C!8Ucd^O&Zq?116IllGw_ zrSp)+Ax$#lIk#m^8$+1hx?iu>-F=6#_cTMAj2Z@1=Ja+0oaj&_>ocu49A2pmxy=2+$ z%caR0(^6}>ABO1?GtW>3apKn$;+#?Gh(j7acWXIX`S$TfpO4m1W&Tx8+o7;!?@Ragd2^mG0Htnq(>=gC z+Zj2N*OI4Wbq`II8yz@Q^5yf76mm|5s9&3-c<9}>Mn*jj)85ZN6n?8j8XYe@YdI_Eo80 z4wn#5HHC-6zNwE3M{3P3D3i#`B$X2+cU)|I8WIjvkTkLM(&2BK;4-o8zn~o!8I#$G zsTt$Xc;pm^uXRbgB(HKXk? z)RUK$c$G19`28J=J-F zLqYQ?0cxTZue!67(fb1w+XnMVzvw(Y7UY63fTI>n=lf3m(2-lX+zCC z5C7~ZYepl^^v0y>Q63eQAjm>g7e2+O_In+;7 z^7^W>aM_;20vH_t4xSnj7b*1c9r!G<6u%b~pVHn16ZZv5g?)-RdcYMX0Whm)5V^;MZIT4<&zO`W%0u;1?wiPPm>ZtWcE7APnTr zL5Q;^R`0tyo7^vpy}BlDz=5MUL*urcYG36*>&2%^Cd?_sY{GlLuLo15H)I}J!;c6O zX?f(tAsbVOuhfW!YKFD#p(Hjr2i02I=e;Rwn7 zuqm1Tfc_xol|VnCsw7hf0folCQX4l|G0Jy?ZNKKv0EG9yBALT>?LgHwFd~5hmk%4e znJ)$<-z;p@WEpgTVLgiMkT8*xK_xQ*dj`pkF4(qp_F8*b97O_YV_7Xt;8COD(i6l> z&o|~P{5w^lPrj2ePH=vl+3(Y=A!XiEf^3L{4*>5mGEE~IDxj#$vdbSlZF%EDe z3+Brv7I1~%f3XwEFfo@N7bVBqz;)c6;7TC~>eb`XLrjE|r@BX`-L0{G=fu_eVHMup z_nF=#dXt?9qd*c=wyHs?K=9O#l7tNGd&l-jX(6gjcN*3+7p1X&=AePcb+N5hT|DzoC%*h3GjRT8qZz&Y#(YyQI%&=n+la-N#!t=j zgxwBNbfX{lT%dcgLXw+VIeza-mualT@vT;?8EZpEG?JXkBxAvVxDBELUlA zI4SbCU3p{U+P7WL%&h`Ojm+!RNow>vm(Kk!d5`ZRxsKzurOfC;JM;)Uy;zQ9uU4%# zxAHGg+9WpX9D_|sa-Kzm$f`xp-7Kh%QH&%iY73i+?cG@<>W9)oberx4j0!o;*7Hg0 zdXf>~2|-ySxAtv*40bV?A6?%g0zoO~n&q@wjrzZwP4ns#wt|3O=1=)h4omh^IwPFf z%Qbf06BBY47&I#tS^(U#-=7Ng%M?pmhF zgR2B8dZv&kv6pK*PnU&IZzW%+%5X0zW|QdL(lOiI)XETWUTkl>fP}bQ3HOYZQYH5O zbO@|7>{Usw97t9nhfvD3b)+v1XM4j00tfx_;|^3U^zO5i2qF%k;=21=4q4By@;=JL z%TBD*cU9f3Ohm=NcAO1A35Q~>hUkDMjER}(pEfN)BuU#^7>iM6Rhv6pFb*L|vp&ug>P^~IRO2}g|QU&cTG`v}lrm|l+Fo_0N6@O>$=ljZkz z*Dp0|^qb9%$51n?nb4EGyhOOyr?`>qzqck%hNHRH<9PMd44*C-gDc~WRDM3#RnfFX zP$`-2wSq~pL0W}Jh;T!n2qFWr8Y7j!A;pDsHagAJHD06Xm1LSx%$ue|PyaEMcwkE) zeYB7ypS@U{1{M^;|5e0p!F7G$uX3+0w*UhK+ZeKLZCPl^gADY|Dx{pu z8BN?@n5{Hjur+&By2Nyy_^D-ppsENfSRvKl#ExovXf6~68v|w8lL~& zZ+5DRWcGRSIc@-uKf>hQ&+5pe-cnchYo;`b%$!ozCY<3Ak%H6lH5@S0LarOC*7KH2 zL*(V+FCwA+w;M5hhn5cW;~(W0T~68_xd2+Ctm2L=G54-xrbxF&jn@Q&(!=$`v zG;3KY)A9IehXaXZ)sHi`5>8AtU) z+Bzc-VXappYOy2~UpOYamVV%JxR)#M7`yJe#>}bendaaZ54YBmJZE{9j`J%r1(mK# zQm@CW{HQ+~xf|}x+gaoM6rk8#)pq;(*nCi0z|&yB#qBP!8Z@{QDiANtOMUVu;Dis< zYK^NmoN+W7FB390A>6$kQa?+>H@}j`@*=wR1*;jIV`%LSh6!=ND^d^>^P|)(U-I@X ze_Dam-u7Kh5*D7qtCd$dNTKc9a}GU_7nguwknv4%$^8d~3pKy{jKD9Xr{g>Q9EX@G zoV>Xg%ko2jkj*?~ZQ1(Yo46~7?*`(_oPS3`NiU%h7M`kml7jFD;E5_i?5m~ifhVEo zXa28OTEUaTzhxc5+KD%`EPYJa@@N_p{E9$`cX0v zBU^xSxW!D3{XqI?$!Ovq%K1}`B?a>xtYfl8p3S_*>3YixSP#vhAD(%?mcdJmrqNxy za78g$oB5|8-6ufA40Q75Z3HWawq%5s=}P=02U*NzJ@xOjtT5{a(0bSi@P~G6(rgbAC|Vw= zT+X|9&|N-0dt(8hGhiFrF7(eEJu@1ul=NE|`b>x%8c5I^0N06oI_){IL4cVprpVfL z7Cd;a4x-hY5Wl`Tw%L{y3k(mwayuOv>AegnU;*aPD_Kxb zCp{A&=1;<-r$9P%1mR&Jwq?F7Im>?qoiwt~k;LeK*&_IM0VW+;lOz<=6c8aF=@j#y zvbrmL;>zCYQOWW;uv`~(v$cfdQ`@Oq@JV!@@udj63+AsZ<-ZRn!a4+*7LoZ#SQ|i9 z`m)B2Ew+il57*6^wfMnSDtDSQ0=`|yc=oLYwya7sfsT41C%5N43AB+)KS+pVDxKi) zuQkt?Gu`eNJ((<-(x|Qxgmv=_@Y{TQ24R|+uNkZlw)~1qe!cGggSwt^E%2_QVfNj; zX<~wOpBxL@o_ro72fa4)#dj@V7z%l44k5J(X4ROpp@ducLY%K$Dw9PxTReeUB;;{d z<$Qi`6LMH~f33l9pC6a@!Si@4Q)X_c&)@q^#bVc^rq7K~YZ^Pk zsU|I&lY*&TR`A@n`32%?_UFewz9Kc*k(abX7o$8S5hp3wN>a2xQnDA?Nh0Gf;nULg z<X}4<@+S1h=U$bzm|%@w5AqRR%^#Y&(tuGU>>8DT_Zqu zc7z0u3`#2nLEl(D3uYhZCisNkWOnbV-%|tgTDW|>bzixqvi66@+}proQYIB&c~oBh zYK!u=@6(FQ?-?y$iu;JuS#@RWo2&Ffrp}d=hA9<#((Y_>-zl9#ftqM5a*n=H9{c#M ziY^ULJJ$YoB*WoCoy)u$<^r`Dx&IL)NGHxU+(LRZ$i4vM)eGHW-6eVt&=>BjF0z!M zHUXyVDX&v3Gm>|C+X+eK^{%1B_}bQg^H(dkS&rh!K1fI0McM}{BclZ6oN^i=A@~u# zy|2pOm_ANPDuRkHXpXK&tQZ%t0>NibJPI>f9tPia@h5JV%xwc!BBoc> zluZNkOegIJ`pDCfpX@0s^c35y)MPS1-iM}dt*rNY$n7%&q19U2aS`C0vAioV4jnnx zL_jl_we7gQ#2Z4$AS!G*za3Y(VGOgn{jTuJ5XV+Mcf!f^vC7+A2QHxy^7b%`NIN*^ z#|kyEbkw)fODi%b6*WIb?SCZWoN1;86cg#(xJwJdi+ZQH*{cfqMCFT4$haa zl%t-m%R#5D&x_NZQid*h4!6w=kwV*Zw1s_=P>r``60GG72PfI@xzK&}afsNz6Onek z$M2$J-LC4=`HB0_GQl(n7HVET{tOQ$ra7n%{!^Y4aA1Kpr$ELH`)*qDP@24N(bcjY zJl&Q@8esRc>Byeu{|mW>HnQ9`$ekYYt=S%A8lqwUdw zu$=TrXSBfC2}<1~E&lenEF*!%RhBLbZHO~mtb?*f2 zdz^#Jx+!wwyo~a`WIPvzVqe;U@DvmUvKK}8h0!h#VR$*4ikH%EdisYDwrD^!2BX2L ziIb2)8Sr>>D-MbyQj6J)%&D0mSA*;lKax~OBrm$ygCHEif?Nv>{EI(EA7=qNpGiV9 PZ43=nU6o2D>#+X=LVG5Y literal 0 HcmV?d00001 diff --git a/assets/textures/button_two_player.png b/assets/textures/button_two_player.png index 08c7a637a4482e9ffc4a0b925f869ac91f12bf55..1f7ba88737760fc27d9efe075776c00273ff9730 100644 GIT binary patch literal 8658 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 literal 8924 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 literal 8469 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 diff --git a/assets/textures/button_two_player_hover.png~ b/assets/textures/button_two_player_hover.png~ new file mode 100644 index 0000000000000000000000000000000000000000..f9700ec0054568ddcb81741d345f42115b01a6d5 GIT binary patch literal 8469 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 literal 0 HcmV?d00001 diff --git a/assets/textures/button_yes.png b/assets/textures/button_yes.png new file mode 100644 index 0000000000000000000000000000000000000000..522747268afffcde8eed8c9612eea6681226a2b0 GIT binary patch literal 5797 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 literal 0 HcmV?d00001 diff --git a/assets/textures/button_yes_hover.png b/assets/textures/button_yes_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..ea102a0915e3333173bbafa972e0d5854dec3aa0 GIT binary patch literal 5864 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 T0b Date: Sun, 7 Jan 2024 08:32:37 +0100 Subject: [PATCH 6/6] Save unfinished work --- src/plugins/timing.py | 142 ++-- src/plugins/writing.py | 126 ++-- src/scenes/game.py | 1372 +++++++++++++++++----------------- src/scenes/game_over.py | 162 ++-- src/scenes/menu.py | 214 +++--- src/scenes/send_to_server.py | 186 ++--- src/scenes/thanks.py | 74 +- src/scenes/try_again.py | 146 ++-- 8 files changed, 1211 insertions(+), 1211 deletions(-) diff --git a/src/plugins/timing.py b/src/plugins/timing.py index 7be3474..5cf6ff9 100644 --- a/src/plugins/timing.py +++ b/src/plugins/timing.py @@ -1,71 +1,71 @@ -""" -Un plugin permettant de connaitre le temps depuis le -lancement du jeu et le temps depuis la dernière frame. -""" - - -from time import time -from typing import Callable -from engine import GlobalPlugin, KeepAlive -from engine.ecs import Entity, World - - -class GlobalTime(KeepAlive, float): - """ - Ressource qui représente le temps global de l'ordinateur sur lequel tourne le jeu. - """ - - -class Time(KeepAlive, float): - """ - Ressource qui représente le temps depuis le lancement du jeu. - """ - - -class Delta(KeepAlive, float): - """ - Ressource qui détermine le temps depuis la première frame. - """ - - -def __initialize(world: World): - """ - Initialise les ressources pour la gestion du temps. - """ - world.set(GlobalTime(time()), Time(0.0)) - - -class TimedEvent: - """ - Composant permettant d'executer un callback après un certain temps. - """ - - def __init__(self, timer: float, callback: Callable[[World, Entity], object]): - self.timer = timer - self.callback = callback - - -def __update(world: World): - """ - Met à jour les ressources de temps. - """ - now = time() - world[Delta] = delta = now - world[GlobalTime] - world[GlobalTime] = now - world[Time] += delta - - # On met à jour les `TimedEvent` - for entity in world.query(TimedEvent): - event = entity[TimedEvent] - event.timer -= delta - if event.timer <= 0: - del entity[TimedEvent] - event.callback(world, entity) - - -PLUGIN = GlobalPlugin( - [__initialize], - [__update], - [], - [], -) +""" +Un plugin permettant de connaitre le temps depuis le +lancement du jeu et le temps depuis la dernière frame. +""" + + +from time import time +from typing import Callable +from engine import GlobalPlugin, KeepAlive +from engine.ecs import Entity, World + + +class GlobalTime(KeepAlive, float): + """ + Ressource qui représente le temps global de l'ordinateur sur lequel tourne le jeu. + """ + + +class Time(KeepAlive, float): + """ + Ressource qui représente le temps depuis le lancement du jeu. + """ + + +class Delta(KeepAlive, float): + """ + Ressource qui détermine le temps depuis la première frame. + """ + + +def __initialize(world: World): + """ + Initialise les ressources pour la gestion du temps. + """ + world.set(GlobalTime(time()), Time(0.0)) + + +class TimedEvent: + """ + Composant permettant d'executer un callback après un certain temps. + """ + + def __init__(self, timer: float, callback: Callable[[World, Entity], object]): + self.timer = timer + self.callback = callback + + +def __update(world: World): + """ + Met à jour les ressources de temps. + """ + now = time() + world[Delta] = delta = now - world[GlobalTime] + world[GlobalTime] = now + world[Time] += delta + + # On met à jour les `TimedEvent` + for entity in world.query(TimedEvent): + event = entity[TimedEvent] + event.timer -= delta + if event.timer <= 0: + del entity[TimedEvent] + event.callback(world, entity) + + +PLUGIN = GlobalPlugin( + [__initialize], + [__update], + [], + [], +) diff --git a/src/plugins/writing.py b/src/plugins/writing.py index 0be2540..f9cbbbc 100644 --- a/src/plugins/writing.py +++ b/src/plugins/writing.py @@ -1,63 +1,63 @@ -""" -Definit un plugin qui crée un texte avec les touches frappées -""" - -from engine import Scene, World -from plugins.inputs import Pressed -from plugins.render import Text -from plugins.sound import Sound - - -class Writing: - """ - Marque une entité comme un texte qui s'ecrit en fonction du clavier - """ - - def __init__( - self, accepted_chars: str, max_chars: int = 10, base_text: str = "" - ) -> None: - self.accepted_chars = accepted_chars - self.max_chars = max_chars - self.base_text = base_text - - -def __update(world: World): - """ - Met a jour les entitées contenant le composant Typing - """ - pressed = world[Pressed] - for entity in world.query(Writing, Text): - writing = entity[Writing] - for key in pressed: - if key == "backspace" and entity[Text] != writing.base_text: - entity[Text] = entity[Text][:-1] - world.new_entity().set(Sound("click.wav")) - if entity[Text] == "": - entity[Text] = writing.base_text - if key.startswith("["): # pavé numerique - key = key[1] - match key: - case "6": - key = "-" - case "8": - key = "_" - case _: - pass - if key in writing.accepted_chars and ( - entity[Text] == writing.base_text - or len(entity[Text]) < writing.max_chars - ): - if entity[Text] == writing.base_text: - entity[Text] = key - else: - entity[Text] += key - world.new_entity().set(Sound("click.wav")) - if entity[Text] == "": - entity[Text] = writing.base_text - - -PLUGIN = Scene( - [], - [__update], - [], -) +""" +Definit un plugin qui crée un texte avec les touches frappées +""" + +from engine import Scene, World +from plugins.inputs import Pressed +from plugins.render import Text +from plugins.sound import Sound + + +class Writing: + """ + Marque une entité comme un texte qui s'ecrit en fonction du clavier + """ + + def __init__( + self, accepted_chars: str, max_chars: int = 10, base_text: str = "" + ) -> None: + self.accepted_chars = accepted_chars + self.max_chars = max_chars + self.base_text = base_text + + +def __update(world: World): + """ + Met a jour les entitées contenant le composant Typing + """ + pressed = world[Pressed] + for entity in world.query(Writing, Text): + writing = entity[Writing] + for key in pressed: + if key == "backspace" and entity[Text] != writing.base_text: + entity[Text] = entity[Text][:-1] + world.new_entity().set(Sound("click.wav")) + if entity[Text] == "": + entity[Text] = writing.base_text + if key.startswith("["): # pavé numerique + key = key[1] + match key: + case "6": + key = "-" + case "8": + key = "_" + case _: + pass + if key in writing.accepted_chars and ( + entity[Text] == writing.base_text + or len(entity[Text]) < writing.max_chars + ): + if entity[Text] == writing.base_text: + entity[Text] = key + else: + entity[Text] += key + world.new_entity().set(Sound("click.wav")) + if entity[Text] == "": + entity[Text] = writing.base_text + + +PLUGIN = Scene( + [], + [__update], + [], +) diff --git a/src/scenes/game.py b/src/scenes/game.py index 1e3a5e3..1a6a493 100644 --- a/src/scenes/game.py +++ b/src/scenes/game.py @@ -1,686 +1,686 @@ -""" -Le jeux principale. -""" - -from enum import Enum -from engine import CurrentScene, KeepAlive, Plugin, Scene -from engine.ecs import Entity, World -from engine.math import Vec2 -from plugins import render -from plugins import physics -from plugins.inputs import Held -from plugins.render import ( - Origin, - Position, - Scale, - SpriteBundle, - TextBundle, - Text, - TextSize, -) -from plugins.timing import Delta, Time -import random -from plugins.physics import CollisionHandler, Solid, Velocity - -from scenes import game_over - - -class GameMode(Enum): - """ - Ressource qui definit le game mode choisi par l'utilisateur. - """ - - ONE = 0 - TWO = 1 - - -class RightWall: - """ - Composant qui marque une entité comme etant le mur de droite. - """ - - -class LeftWall: - """ - Composant qui marque une entité comme etant le mur de gauche. - """ - - -class Player1: - """ - Composant qui marque une entité comme etant le joeuur 1. - """ - - -class Player2: - """ - Composant qui marque une entité comme etant le joeuur 2. - """ - - -class Ball: - """ - Composant qui marque une entité comme etant une balle. - """ - - -class Bounce: - """ - Composant qui marque une entité qui peux faire rebondir - """ - - -class UpKey(str): - """ - Composant qui indique la touche pour faire monter le joueur - """ - - -class DownKey(str): - """ - Composant qui indique la touche pour faire descender le joueur - """ - - -class Speed(int): - """ - Composant qui represente la vitesse de l'entité. - """ - - -class Player1Score(int, KeepAlive): - """ - Ressource qui represente le score du joueur 1. - """ - - -class Player2Score(int): - """ - Ressource qui represente le score du joueur 2. - """ - - -class Score: - """ - Composant qui marque l'entité comme étant l'affichage du score. - """ - - -class StartAnimation(float): - """ - Composant qui represente un le moment auxquel on a lancé l'animation du compte a rebours - """ - - -class Wall: - """ - Composant qui represente les mur du haut et du bas - """ - - -class TimeUntilBonus: - """ - ressource qui represente le temps restant avant d'avoir le bonus - """ - - def __init__(self, time: float, world: World): - self.time = time - self.started_time = int(world[Time]) - - def is_ended(self, world: World): - return world[Time] - self.started_time >= self.time - - def start(self, world: World): - self.started_time = world[Time] - - -class LastPlayerTurn: - """ - un composant qui represente le dernier joueur qui a joué. - """ - - -class HasBonus: - """ - un composant qui represente si l'entité a un bonus - """ - - def __init__(self, bonus: "Bonus", time: float, world: World): - self.bonus = bonus - self.time = time - - self.start_time = world[Time] - - def is_ended(self, world: World): - return world[Time] - self.start_time >= self.time - - def suppr_bonus_from_entity(self, entity: Entity): - match self.bonus: - case Bonus.MULTI: - pass - case Bonus.BIG: - entity[Scale] /= 2 - case Bonus.FAST: - entity[Speed] /= 1.5 - case Bonus.REVERSE: - entity[UpKey], entity[DownKey] = entity[DownKey], entity[UpKey] - - -class Bonus(Enum): - MULTI = 0 - BIG = 1 - FAST = 2 - REVERSE = 3 - - @staticmethod - def aleatoire(): - type = random.randint(0, 3) - match type: - case 0: - return Bonus.MULTI - case 1: - return Bonus.BIG - case 2: - return Bonus.FAST - case _: - return Bonus.REVERSE - - @staticmethod - def get_texture(bonus: "Bonus"): - match bonus: - case Bonus.MULTI: - return "multi.png" - case Bonus.BIG: - return "big.png" - case Bonus.FAST: - return "fast.png" - case _: - return "reverse.png" - - -def __spawn_ellements(world: World): - """ - La fonction permet de initializer les ellements de la scene. - """ - - world.new_entity().set(SpriteBundle(("background.jpg"), -5)) - - world.set( - TimeUntilBonus(5, world), - ) - - # Mon mur de gauche - world.new_entity().set( - Origin(Vec2(1, 0)), - Scale(Vec2(10, render.HEIGHT)), - Position(Vec2(70, 0)), - Solid(), - LeftWall(), - CollisionHandler(__bounce_on_left_wall), - ) - - # Mon mur du RN - world.new_entity().set( - Origin(Vec2(0, 0)), - Scale(Vec2(10, render.HEIGHT)), - Position(Vec2(render.WIDTH - 70, 0)), - Solid(), - RightWall(), - CollisionHandler(__bounce_on_right_wall), - ) - - # Mon mur du bas - world.new_entity().set( - Origin(Vec2(0, 0)), - Scale(Vec2(render.WIDTH, 10)), - Position(Vec2(0, render.HEIGHT)), - (Wall(), physics.CollisionHandler(__bounce_on_top_or_bot_wall)) - if world[GameMode] == GameMode.ONE - else None, - Solid(), - ) - - # Mon mur du haut - world.new_entity().set( - Origin(Vec2(0, 1)), - Scale(Vec2(render.WIDTH, 10)), - Position(Vec2(0, 0)), - (Wall(), physics.CollisionHandler(__bounce_on_top_or_bot_wall)) - if world[GameMode] == GameMode.ONE - else None, - Solid(), - ) - - # Joueur 1 - world.new_entity().set( - SpriteBundle( - "player_1.png", - 0, - Vec2(100, render.HEIGHT / 2), - Vec2(44, 250), - Vec2(0.5), - ), - Solid(), - Player1(), - UpKey("z"), - DownKey("s"), - Speed(1000), - LastPlayerTurn(), - ) - - # Joueur 2 - world.new_entity().set( - SpriteBundle( - "player_2.png", - 0, - Vec2(render.WIDTH - 100, render.HEIGHT / 2), - Vec2(44, 250), - Vec2(0.5), - ), - Solid(), - Player2(), - (UpKey("up"), DownKey("down"), Speed(1000)) - if world[GameMode] == GameMode.TWO - else Speed(300), - ) - - __spawn_ball(world) - - # Initialisation des scores - world.set(Player1Score(0), Player2Score(0)) - - # Creation du texte d'affichage en fonction du mode de jeu - if world[GameMode] == GameMode.TWO: - world.new_entity().set( - TextBundle( - "0 - 0", - 10, - 50, - position=Vec2(render.WIDTH / 2, 75), - origin=Vec2(0.5), - ), - Score(), - ) - else: - world.new_entity().set( - TextBundle( - "0", - 10, - 50, - position=Vec2(render.WIDTH / 2, 75), - origin=Vec2(0.5), - ), - Score(), - ) - - -def __spawn_bonus(world: World): - bonus = Bonus.aleatoire() - world.new_entity().set( - SpriteBundle( - Bonus.get_texture(bonus), - 3, - Vec2( - random.randint(200, render.WIDTH - 200), - random.randint(100, render.HEIGHT - 100), - ), - Vec2(70), - Vec2(0.5), - ), - bonus, - ) - - -def __spawn_ball(world: World): - """ - Fonction qui fait apparaitre une balle avec une velocitée aleatoire - """ - # random velocité - velocity = Vec2(2 * random.randint(100, 200), random.randint(100, 200)) - - # mouvement a droite ou a gauche - if random.randint(0, 1) == 0: - velocity.x = -velocity.x - - # Balle - world.new_entity().set( - SpriteBundle( - "ball.png", - 0, - Vec2(render.WIDTH / 2, render.HEIGHT / 2), - Vec2(40, 40), - Vec2(0.5), - ), - Ball(), - Velocity(velocity), - CollisionHandler(__collision_with_ball), - ) - - -def __collision_with_ball(a: Entity, b: Entity): - if Player1 in b or Player2 in b: - for player in a.world.query(LastPlayerTurn): - del player[LastPlayerTurn] - b.set(LastPlayerTurn()) - return __bounce_on_player(a, b) - return True - - -def __bonus_touched(ball: Entity, bonus: Entity): - player = ball.world.query(LastPlayerTurn).pop() - match bonus[Bonus]: - case Bonus.MULTI: - __spawn_ball(bonus.world) - __spawn_ball(bonus.world) - ball.world[TimeUntilBonus].start(ball.world) - case Bonus.BIG: - player[Scale] *= 2 - player.set(HasBonus(Bonus.BIG, 10, bonus.world)) - case Bonus.FAST: - player[Speed] *= 1.5 - player.set(HasBonus(Bonus.FAST, 10, bonus.world)) - case Bonus.REVERSE: - for entity in ball.world.query(UpKey): - if LastPlayerTurn in entity: - continue - entity[UpKey], entity[DownKey] = entity[DownKey], entity[UpKey] - - entity.set(HasBonus(Bonus.REVERSE, 10, bonus.world)) - - bonus.destroy() - return False - - -def __bounce_on_player(a: Entity, b: Entity): - """ - Fonction qui decrit se qui se passe lorque la ball entre en collision avec un joueur - """ - # Si l'objet rencontré est un joueur - if Player1 in b or Player2 in b: - speed = a[physics.Velocity].length - a[physics.Velocity] = a[physics.Velocity].normalized - a[physics.Velocity].y = (a[Position].y - b[Position].y) * 0.005 - a[physics.Velocity] = a[physics.Velocity].normalized * min( - (speed * 1.1), 1000.0 - ) - # Si il s'agit du joueur 1 et que l'on est dans le mode 1 joueur - if Player1 in b and Ball in a: - if b.world[GameMode] == GameMode.ONE: - # Modification du score - a.world[Player1Score] += 100 - __update_scores(a.world, b) - return True - - -def __bounce_on_top_or_bot_wall(a: Entity, b: Entity): - # Si une balle touceh un mur du haut ou du bas et que l'on est dans le mode 1 joueur - # Il est important de verifier qu'il s'agit de la balle, - # Car des simulation de balle sont faites et ont le meme - # Comportment qu'une balle mais n'ont pas le composant Ball - if Ball in b and Wall in a: - if b.world[GameMode] == GameMode.ONE: - # Modification du score - a.world[Player1Score] += 20 - __update_scores(a.world, a) - return True - - -def __bounce_on_left_wall(a: Entity, b: Entity): - """ - Fonction qui decrit se qui se passe lorque la ball entre en collision avec le mur de gauche - """ - if Ball in b: - world = a.world - if world[GameMode] == GameMode.TWO: - world[Player2Score] += 1 - __update_scores(world, b) - else: - world[CurrentScene] = game_over.GAME_OVER - - return False - return True - - -def __bounce_on_right_wall(a: Entity, b: Entity): - """ - Fonction qui decrit se qui se passe lorque la ball entre en collision avec le mur de droite - """ - if Ball in b: - world = a.world - if world[GameMode] == GameMode.TWO: - world[Player1Score] += 1 - else: - world[Player1Score] += 1000 - __update_scores(world, b) - return False - return True - - -def __move_up(world: World): - """ - La fonction permet de faire bouger les entitees qui possedent UpKey vers le haut. - """ - held = world[Held] - for entity in world.query(UpKey): - if entity[UpKey] in held: - entity[Position] = Vec2( - entity[Position].x, - (entity[Position].y - entity[Speed] * world[Delta]), - ) - - -def __move_down(world: World): - """ - La fonction permet de faire bouger les entitees qui possedent DownKey vers le bas. - """ - held = world[Held] - for entity in world.query(DownKey): - if entity[DownKey] in held: - entity[Position] = Vec2( - entity[Position].x, - (entity[Position].y + entity[Speed] * world[Delta]), - ) - - -def __update_move(world: World): - """ - La fontion permet de faire bouger les entitees vers le haut ou vers le bas. - """ - __move_down(world) - __move_up(world) - - -def __simulate_wall_position(entity: Entity, component_type: type): - """ - Simule une entité afin de trouver lorsqu'elle entrera en collision avec une entité contenant un certain composant. - """ - simulation_entity = entity.world.new_entity() - - def __collision_handler(a: Entity, b: Entity): - entity[CollisionHandler].callback(a, b) - return component_type not in b - - simulation_entity.set( - Position(entity[Position]), - Scale(entity[Scale]), - Velocity(entity[Velocity]), - Origin(entity[Origin]), - CollisionHandler(__collision_handler), - ) - physics.move_entity(simulation_entity, entity[Velocity] * 500) - return simulation_entity - - -def _update_bot(world: World): - """ - Fonction qui update les mouvement du bot - """ - # On récupère la balle la plus proche du bot - ball_query = world.query(Position, Velocity, CollisionHandler) - if ball_query == set(): - return None - ball = max(ball_query, key=lambda entity: entity[Position].y) - - # On récupère le bot et le joueur - bot = world.query(Player2).pop() - player = world.query(Player1).pop() - - # On trouve l'endroit ou la balle va arriver sur le mur de droite - bot.remove(Solid) - right_wall_ball = __simulate_wall_position(ball, RightWall) - right_touch_height = right_wall_ball[Position].y - right_wall_ball.destroy() - bot.set(Solid()) - - # On teste différentes possitions pour voir laquelle la plus éloigné du joueur - # Mais seulement si la balle vas vers la droite car sinon elle touchera le mur - # de gauche sans intervention du bot - if ball[Velocity].x > 0: - bot_base_y = bot[Position].y - target: float = right_touch_height - better_distance = None - for offset in [-100, -50, 0, 50, 100]: - bot[Position].y = right_touch_height + offset - player.remove(Solid) - left_wall_ball = __simulate_wall_position(ball, LeftWall) - player.set(Solid()) - left_touch_height = left_wall_ball[Position].y - left_wall_ball.destroy() - if ( - better_distance is None - or abs(left_touch_height - player[Position].y) > better_distance - ): - better_distance = abs(left_touch_height - player[Position].y) - target = right_touch_height + offset - bot[Position].y = bot_base_y - else: - target = right_touch_height - - # On se déplace vers la meilleure option - diff = target - bot[Position].y - if abs(diff) > 10: - bot[Position].y += (diff / abs(diff)) * bot[Speed] * world[Delta] - - -def __check_bonus_collision(world: World): - """ - Fonction qui permet de voir si un bonus est entrée en collision avec une entité. - """ - - def __collision_handler(a: Entity, b: Entity): - if Bonus in b: - __bonus_touched(a, b) - return False - return True - - for entity in world.query(Bonus): - entity.set(Solid()) - for entity in world.query(Ball): - simulated_ball = world.new_entity() - simulated_ball.set( - Position(entity[Position]), - Scale(entity[Scale]), - Velocity(entity[Velocity]), - Origin(entity[Origin]), - CollisionHandler(__collision_handler), - ) - physics.move_entity(simulated_ball, entity[Velocity] * world[Delta]) - simulated_ball.destroy() - for entity in world.query(Bonus): - entity.remove(Solid) - - -def __update_scores(world: World, ball: Entity): - """ - La fontion permet de mettre a jour les scores. - """ - - if world[GameMode] == GameMode.TWO: - # met a jour le score du joueur 1 et 2 - for panel in world.query(Score): - panel[Text] = f"{world[Player1Score]} - {world[Player2Score]}" - - ball.destroy() - else: - for panel in world.query(Score): - panel[Text] = f"{world[Player1Score]}" - if Ball in ball: - ball.destroy() - - if world.query(Ball) == set(): - __animation(world, 3) - - -def __animation(world: World, number: int): - world.new_entity().set( - TextBundle( - str(number), - 2, - 5000, - position=Vec2(render.WIDTH / 2, render.HEIGHT / 2), - origin=Vec2(0.5), - ), - StartAnimation(world[Time]), - ) - - -def __update_animation(world: World): - """ - Fonction qui permet de mettre a jour l'animation du compte a rebours. - """ - - for animation in world.query(StartAnimation): - time = world[Time] - animation[StartAnimation] - - if animation[TextSize] > 700: - animation[TextSize] = 5000 / (25 * time + 1) - else: - animation[TextSize] -= 1000 * world[Delta] - if animation[TextSize] < 0: - if int(animation[Text]) > 1 or "space" in world[Held]: - __animation(world, int(animation[Text]) - 1) - else: - # creation de la balle - __spawn_ball(world) - animation.destroy() - - -def __update_bonus_time(world: World): - """ - Fonction qui permet de mettre à jour les bonus. - """ - for player in world.query(HasBonus): - if not player[HasBonus].is_ended(world): - return None - player[HasBonus].suppr_bonus_from_entity(player) - del player[HasBonus] - world[TimeUntilBonus].start(world) - - if world.query(Bonus) == set() and world.query(HasBonus) == set(): - if world[TimeUntilBonus].is_ended(world): - __spawn_bonus(world) - - -__SCENE = Scene( - [__spawn_ellements], - [__update_move, __check_bonus_collision, __update_animation, __update_bonus_time], - [], -) - -ONE_PLAYER = ( - Plugin( - [lambda world: world.set(GameMode.ONE)], - [_update_bot], - [], - ) - + __SCENE -) - -TWO_PLAYER = ( - Plugin( - [lambda world: world.set(GameMode.TWO)], - [], - [], - ) - + __SCENE -) +""" +Le jeux principale. +""" + +from enum import Enum +from engine import CurrentScene, KeepAlive, Plugin, Scene +from engine.ecs import Entity, World +from engine.math import Vec2 +from plugins import render +from plugins import physics +from plugins.inputs import Held +from plugins.render import ( + Origin, + Position, + Scale, + SpriteBundle, + TextBundle, + Text, + TextSize, +) +from plugins.timing import Delta, Time +import random +from plugins.physics import CollisionHandler, Solid, Velocity + +from scenes import game_over + + +class GameMode(Enum): + """ + Ressource qui definit le game mode choisi par l'utilisateur. + """ + + ONE = 0 + TWO = 1 + + +class RightWall: + """ + Composant qui marque une entité comme etant le mur de droite. + """ + + +class LeftWall: + """ + Composant qui marque une entité comme etant le mur de gauche. + """ + + +class Player1: + """ + Composant qui marque une entité comme etant le joeuur 1. + """ + + +class Player2: + """ + Composant qui marque une entité comme etant le joeuur 2. + """ + + +class Ball: + """ + Composant qui marque une entité comme etant une balle. + """ + + +class Bounce: + """ + Composant qui marque une entité qui peux faire rebondir + """ + + +class UpKey(str): + """ + Composant qui indique la touche pour faire monter le joueur + """ + + +class DownKey(str): + """ + Composant qui indique la touche pour faire descender le joueur + """ + + +class Speed(int): + """ + Composant qui represente la vitesse de l'entité. + """ + + +class Player1Score(int, KeepAlive): + """ + Ressource qui represente le score du joueur 1. + """ + + +class Player2Score(int): + """ + Ressource qui represente le score du joueur 2. + """ + + +class Score: + """ + Composant qui marque l'entité comme étant l'affichage du score. + """ + + +class StartAnimation(float): + """ + Composant qui represente un le moment auxquel on a lancé l'animation du compte a rebours + """ + + +class Wall: + """ + Composant qui represente les mur du haut et du bas + """ + + +class TimeUntilBonus: + """ + ressource qui represente le temps restant avant d'avoir le bonus + """ + + def __init__(self, time: float, world: World): + self.time = time + self.started_time = int(world[Time]) + + def is_ended(self, world: World): + return world[Time] - self.started_time >= self.time + + def start(self, world: World): + self.started_time = world[Time] + + +class LastPlayerTurn: + """ + un composant qui represente le dernier joueur qui a joué. + """ + + +class HasBonus: + """ + un composant qui represente si l'entité a un bonus + """ + + def __init__(self, bonus: "Bonus", time: float, world: World): + self.bonus = bonus + self.time = time + + self.start_time = world[Time] + + def is_ended(self, world: World): + return world[Time] - self.start_time >= self.time + + def suppr_bonus_from_entity(self, entity: Entity): + match self.bonus: + case Bonus.MULTI: + pass + case Bonus.BIG: + entity[Scale] /= 2 + case Bonus.FAST: + entity[Speed] /= 1.5 + case Bonus.REVERSE: + entity[UpKey], entity[DownKey] = entity[DownKey], entity[UpKey] + + +class Bonus(Enum): + MULTI = 0 + BIG = 1 + FAST = 2 + REVERSE = 3 + + @staticmethod + def aleatoire(): + type = random.randint(0, 3) + match type: + case 0: + return Bonus.MULTI + case 1: + return Bonus.BIG + case 2: + return Bonus.FAST + case _: + return Bonus.REVERSE + + @staticmethod + def get_texture(bonus: "Bonus"): + match bonus: + case Bonus.MULTI: + return "multi.png" + case Bonus.BIG: + return "big.png" + case Bonus.FAST: + return "fast.png" + case _: + return "reverse.png" + + +def __spawn_ellements(world: World): + """ + La fonction permet de initializer les ellements de la scene. + """ + + world.new_entity().set(SpriteBundle(("background.jpg"), -5)) + + world.set( + TimeUntilBonus(5, world), + ) + + # Mon mur de gauche + world.new_entity().set( + Origin(Vec2(1, 0)), + Scale(Vec2(10, render.HEIGHT)), + Position(Vec2(70, 0)), + Solid(), + LeftWall(), + CollisionHandler(__bounce_on_left_wall), + ) + + # Mon mur du RN + world.new_entity().set( + Origin(Vec2(0, 0)), + Scale(Vec2(10, render.HEIGHT)), + Position(Vec2(render.WIDTH - 70, 0)), + Solid(), + RightWall(), + CollisionHandler(__bounce_on_right_wall), + ) + + # Mon mur du bas + world.new_entity().set( + Origin(Vec2(0, 0)), + Scale(Vec2(render.WIDTH, 10)), + Position(Vec2(0, render.HEIGHT)), + (Wall(), physics.CollisionHandler(__bounce_on_top_or_bot_wall)) + if world[GameMode] == GameMode.ONE + else None, + Solid(), + ) + + # Mon mur du haut + world.new_entity().set( + Origin(Vec2(0, 1)), + Scale(Vec2(render.WIDTH, 10)), + Position(Vec2(0, 0)), + (Wall(), physics.CollisionHandler(__bounce_on_top_or_bot_wall)) + if world[GameMode] == GameMode.ONE + else None, + Solid(), + ) + + # Joueur 1 + world.new_entity().set( + SpriteBundle( + "player_1.png", + 0, + Vec2(100, render.HEIGHT / 2), + Vec2(44, 250), + Vec2(0.5), + ), + Solid(), + Player1(), + UpKey("z"), + DownKey("s"), + Speed(1000), + LastPlayerTurn(), + ) + + # Joueur 2 + world.new_entity().set( + SpriteBundle( + "player_2.png", + 0, + Vec2(render.WIDTH - 100, render.HEIGHT / 2), + Vec2(44, 250), + Vec2(0.5), + ), + Solid(), + Player2(), + (UpKey("up"), DownKey("down"), Speed(1000)) + if world[GameMode] == GameMode.TWO + else Speed(300), + ) + + __spawn_ball(world) + + # Initialisation des scores + world.set(Player1Score(0), Player2Score(0)) + + # Creation du texte d'affichage en fonction du mode de jeu + if world[GameMode] == GameMode.TWO: + world.new_entity().set( + TextBundle( + "0 - 0", + 10, + 50, + position=Vec2(render.WIDTH / 2, 75), + origin=Vec2(0.5), + ), + Score(), + ) + else: + world.new_entity().set( + TextBundle( + "0", + 10, + 50, + position=Vec2(render.WIDTH / 2, 75), + origin=Vec2(0.5), + ), + Score(), + ) + + +def __spawn_bonus(world: World): + bonus = Bonus.aleatoire() + world.new_entity().set( + SpriteBundle( + Bonus.get_texture(bonus), + 3, + Vec2( + random.randint(200, render.WIDTH - 200), + random.randint(100, render.HEIGHT - 100), + ), + Vec2(70), + Vec2(0.5), + ), + bonus, + ) + + +def __spawn_ball(world: World): + """ + Fonction qui fait apparaitre une balle avec une velocitée aleatoire + """ + # random velocité + velocity = Vec2(2 * random.randint(100, 200), random.randint(100, 200)) + + # mouvement a droite ou a gauche + if random.randint(0, 1) == 0: + velocity.x = -velocity.x + + # Balle + world.new_entity().set( + SpriteBundle( + "ball.png", + 0, + Vec2(render.WIDTH / 2, render.HEIGHT / 2), + Vec2(40, 40), + Vec2(0.5), + ), + Ball(), + Velocity(velocity), + CollisionHandler(__collision_with_ball), + ) + + +def __collision_with_ball(a: Entity, b: Entity): + if Player1 in b or Player2 in b: + for player in a.world.query(LastPlayerTurn): + del player[LastPlayerTurn] + b.set(LastPlayerTurn()) + return __bounce_on_player(a, b) + return True + + +def __bonus_touched(ball: Entity, bonus: Entity): + player = ball.world.query(LastPlayerTurn).pop() + match bonus[Bonus]: + case Bonus.MULTI: + __spawn_ball(bonus.world) + __spawn_ball(bonus.world) + ball.world[TimeUntilBonus].start(ball.world) + case Bonus.BIG: + player[Scale] *= 2 + player.set(HasBonus(Bonus.BIG, 10, bonus.world)) + case Bonus.FAST: + player[Speed] *= 1.5 + player.set(HasBonus(Bonus.FAST, 10, bonus.world)) + case Bonus.REVERSE: + for entity in ball.world.query(UpKey): + if LastPlayerTurn in entity: + continue + entity[UpKey], entity[DownKey] = entity[DownKey], entity[UpKey] + + entity.set(HasBonus(Bonus.REVERSE, 10, bonus.world)) + + bonus.destroy() + return False + + +def __bounce_on_player(a: Entity, b: Entity): + """ + Fonction qui decrit se qui se passe lorque la ball entre en collision avec un joueur + """ + # Si l'objet rencontré est un joueur + if Player1 in b or Player2 in b: + speed = a[physics.Velocity].length + a[physics.Velocity] = a[physics.Velocity].normalized + a[physics.Velocity].y = (a[Position].y - b[Position].y) * 0.005 + a[physics.Velocity] = a[physics.Velocity].normalized * min( + (speed * 1.1), 1000.0 + ) + # Si il s'agit du joueur 1 et que l'on est dans le mode 1 joueur + if Player1 in b and Ball in a: + if b.world[GameMode] == GameMode.ONE: + # Modification du score + a.world[Player1Score] += 100 + __update_scores(a.world, b) + return True + + +def __bounce_on_top_or_bot_wall(a: Entity, b: Entity): + # Si une balle touceh un mur du haut ou du bas et que l'on est dans le mode 1 joueur + # Il est important de verifier qu'il s'agit de la balle, + # Car des simulation de balle sont faites et ont le meme + # Comportment qu'une balle mais n'ont pas le composant Ball + if Ball in b and Wall in a: + if b.world[GameMode] == GameMode.ONE: + # Modification du score + a.world[Player1Score] += 20 + __update_scores(a.world, a) + return True + + +def __bounce_on_left_wall(a: Entity, b: Entity): + """ + Fonction qui decrit se qui se passe lorque la ball entre en collision avec le mur de gauche + """ + if Ball in b: + world = a.world + if world[GameMode] == GameMode.TWO: + world[Player2Score] += 1 + __update_scores(world, b) + else: + world[CurrentScene] = game_over.GAME_OVER + + return False + return True + + +def __bounce_on_right_wall(a: Entity, b: Entity): + """ + Fonction qui decrit se qui se passe lorque la ball entre en collision avec le mur de droite + """ + if Ball in b: + world = a.world + if world[GameMode] == GameMode.TWO: + world[Player1Score] += 1 + else: + world[Player1Score] += 1000 + __update_scores(world, b) + return False + return True + + +def __move_up(world: World): + """ + La fonction permet de faire bouger les entitees qui possedent UpKey vers le haut. + """ + held = world[Held] + for entity in world.query(UpKey): + if entity[UpKey] in held: + entity[Position] = Vec2( + entity[Position].x, + (entity[Position].y - entity[Speed] * world[Delta]), + ) + + +def __move_down(world: World): + """ + La fonction permet de faire bouger les entitees qui possedent DownKey vers le bas. + """ + held = world[Held] + for entity in world.query(DownKey): + if entity[DownKey] in held: + entity[Position] = Vec2( + entity[Position].x, + (entity[Position].y + entity[Speed] * world[Delta]), + ) + + +def __update_move(world: World): + """ + La fontion permet de faire bouger les entitees vers le haut ou vers le bas. + """ + __move_down(world) + __move_up(world) + + +def __simulate_wall_position(entity: Entity, component_type: type): + """ + Simule une entité afin de trouver lorsqu'elle entrera en collision avec une entité contenant un certain composant. + """ + simulation_entity = entity.world.new_entity() + + def __collision_handler(a: Entity, b: Entity): + entity[CollisionHandler].callback(a, b) + return component_type not in b + + simulation_entity.set( + Position(entity[Position]), + Scale(entity[Scale]), + Velocity(entity[Velocity]), + Origin(entity[Origin]), + CollisionHandler(__collision_handler), + ) + physics.move_entity(simulation_entity, entity[Velocity] * 500) + return simulation_entity + + +def _update_bot(world: World): + """ + Fonction qui update les mouvement du bot + """ + # On récupère la balle la plus proche du bot + ball_query = world.query(Position, Velocity, CollisionHandler) + if ball_query == set(): + return None + ball = max(ball_query, key=lambda entity: entity[Position].y) + + # On récupère le bot et le joueur + bot = world.query(Player2).pop() + player = world.query(Player1).pop() + + # On trouve l'endroit ou la balle va arriver sur le mur de droite + bot.remove(Solid) + right_wall_ball = __simulate_wall_position(ball, RightWall) + right_touch_height = right_wall_ball[Position].y + right_wall_ball.destroy() + bot.set(Solid()) + + # On teste différentes possitions pour voir laquelle la plus éloigné du joueur + # Mais seulement si la balle vas vers la droite car sinon elle touchera le mur + # de gauche sans intervention du bot + if ball[Velocity].x > 0: + bot_base_y = bot[Position].y + target: float = right_touch_height + better_distance = None + for offset in [-100, -50, 0, 50, 100]: + bot[Position].y = right_touch_height + offset + player.remove(Solid) + left_wall_ball = __simulate_wall_position(ball, LeftWall) + player.set(Solid()) + left_touch_height = left_wall_ball[Position].y + left_wall_ball.destroy() + if ( + better_distance is None + or abs(left_touch_height - player[Position].y) > better_distance + ): + better_distance = abs(left_touch_height - player[Position].y) + target = right_touch_height + offset + bot[Position].y = bot_base_y + else: + target = right_touch_height + + # On se déplace vers la meilleure option + diff = target - bot[Position].y + if abs(diff) > 10: + bot[Position].y += (diff / abs(diff)) * bot[Speed] * world[Delta] + + +def __check_bonus_collision(world: World): + """ + Fonction qui permet de voir si un bonus est entrée en collision avec une entité. + """ + + def __collision_handler(a: Entity, b: Entity): + if Bonus in b: + __bonus_touched(a, b) + return False + return True + + for entity in world.query(Bonus): + entity.set(Solid()) + for entity in world.query(Ball): + simulated_ball = world.new_entity() + simulated_ball.set( + Position(entity[Position]), + Scale(entity[Scale]), + Velocity(entity[Velocity]), + Origin(entity[Origin]), + CollisionHandler(__collision_handler), + ) + physics.move_entity(simulated_ball, entity[Velocity] * world[Delta]) + simulated_ball.destroy() + for entity in world.query(Bonus): + entity.remove(Solid) + + +def __update_scores(world: World, ball: Entity): + """ + La fontion permet de mettre a jour les scores. + """ + + if world[GameMode] == GameMode.TWO: + # met a jour le score du joueur 1 et 2 + for panel in world.query(Score): + panel[Text] = f"{world[Player1Score]} - {world[Player2Score]}" + + ball.destroy() + else: + for panel in world.query(Score): + panel[Text] = f"{world[Player1Score]}" + if Ball in ball: + ball.destroy() + + if world.query(Ball) == set(): + __animation(world, 3) + + +def __animation(world: World, number: int): + world.new_entity().set( + TextBundle( + str(number), + 2, + 5000, + position=Vec2(render.WIDTH / 2, render.HEIGHT / 2), + origin=Vec2(0.5), + ), + StartAnimation(world[Time]), + ) + + +def __update_animation(world: World): + """ + Fonction qui permet de mettre a jour l'animation du compte a rebours. + """ + + for animation in world.query(StartAnimation): + time = world[Time] - animation[StartAnimation] + + if animation[TextSize] > 700: + animation[TextSize] = 5000 / (25 * time + 1) + else: + animation[TextSize] -= 1000 * world[Delta] + if animation[TextSize] < 0: + if int(animation[Text]) > 1 or "space" in world[Held]: + __animation(world, int(animation[Text]) - 1) + else: + # creation de la balle + __spawn_ball(world) + animation.destroy() + + +def __update_bonus_time(world: World): + """ + Fonction qui permet de mettre à jour les bonus. + """ + for player in world.query(HasBonus): + if not player[HasBonus].is_ended(world): + return None + player[HasBonus].suppr_bonus_from_entity(player) + del player[HasBonus] + world[TimeUntilBonus].start(world) + + if world.query(Bonus) == set() and world.query(HasBonus) == set(): + if world[TimeUntilBonus].is_ended(world): + __spawn_bonus(world) + + +__SCENE = Scene( + [__spawn_ellements], + [__update_move, __check_bonus_collision, __update_animation, __update_bonus_time], + [], +) + +ONE_PLAYER = ( + Plugin( + [lambda world: world.set(GameMode.ONE)], + [_update_bot], + [], + ) + + __SCENE +) + +TWO_PLAYER = ( + Plugin( + [lambda world: world.set(GameMode.TWO)], + [], + [], + ) + + __SCENE +) diff --git a/src/scenes/game_over.py b/src/scenes/game_over.py index 9f82074..d9f6409 100644 --- a/src/scenes/game_over.py +++ b/src/scenes/game_over.py @@ -1,81 +1,81 @@ -from engine import CurrentScene, KeepAlive, Scene -from engine.ecs import Entity, World -from engine.math import Vec2 -from plugins import render -from plugins.click import Clickable -from plugins.hover import HoveredTexture -from plugins.render import ( - SpriteBundle, - TextBundle, -) -from plugins.sound import Sound -from scenes import game, send_to_server, try_again - - -def __spawn_elements(world: World): - world.new_entity().set( - TextBundle( - "Game Over", 0, 100, position=Vec2(render.WIDTH / 2, 250), origin=Vec2(0.5) - ) - ) - world.new_entity().set( - TextBundle( - "Voulez vous enregistrer votre Score ?", - 0, - 50, - position=Vec2(render.WIDTH / 2, 350), - origin=Vec2(0.5), - ) - ) - world.new_entity().set( - TextBundle( - f"{world[game.Player1Score]}", - 0, - 50, - position=Vec2(render.WIDTH / 2, 450), - origin=Vec2(0.5), - ) - ) - button_name = ["yes", "no"] - for i, name in enumerate(button_name): - __create_button(world, i, name) - - -def __create_button(world: World, i: int, name: str): - """ - Ajoute un bouton au monde. - """ - world.new_entity().set( - SpriteBundle( - f"button_{name}.png", - position=Vec2(450 + 540 * i, render.HEIGHT / 2 + render.HEIGHT / 8), - order=1, - origin=Vec2(0.5), - ), - HoveredTexture( - f"button_{name}.png", - f"button_{name}_hover.png", - ), - Clickable(lambda world, entity: __on_click_butons(world, entity, name)), - ) - - -def __on_click_butons(world: World, _entity: Entity, name: str): - """ - Fonction qui s'execute quand on clique sur un bouton. - """ - match name: - case "yes": - world[CurrentScene] = send_to_server.SEND - case "no": - world[CurrentScene] = try_again.TRY_AGAIN - case _: - pass - world.new_entity().set(KeepAlive(), Sound("click.wav")) - - -GAME_OVER = Scene( - [__spawn_elements], - [], - [], -) +from engine import CurrentScene, KeepAlive, Scene +from engine.ecs import Entity, World +from engine.math import Vec2 +from plugins import render +from plugins.click import Clickable +from plugins.hover import HoveredTexture +from plugins.render import ( + SpriteBundle, + TextBundle, +) +from plugins.sound import Sound +from scenes import game, send_to_server, try_again + + +def __spawn_elements(world: World): + world.new_entity().set( + TextBundle( + "Game Over", 0, 100, position=Vec2(render.WIDTH / 2, 250), origin=Vec2(0.5) + ) + ) + world.new_entity().set( + TextBundle( + "Voulez vous enregistrer votre Score ?", + 0, + 50, + position=Vec2(render.WIDTH / 2, 350), + origin=Vec2(0.5), + ) + ) + world.new_entity().set( + TextBundle( + f"{world[game.Player1Score]}", + 0, + 50, + position=Vec2(render.WIDTH / 2, 450), + origin=Vec2(0.5), + ) + ) + button_name = ["yes", "no"] + for i, name in enumerate(button_name): + __create_button(world, i, name) + + +def __create_button(world: World, i: int, name: str): + """ + Ajoute un bouton au monde. + """ + world.new_entity().set( + SpriteBundle( + f"button_{name}.png", + position=Vec2(450 + 540 * i, render.HEIGHT / 2 + render.HEIGHT / 8), + order=1, + origin=Vec2(0.5), + ), + HoveredTexture( + f"button_{name}.png", + f"button_{name}_hover.png", + ), + Clickable(lambda world, entity: __on_click_butons(world, entity, name)), + ) + + +def __on_click_butons(world: World, _entity: Entity, name: str): + """ + Fonction qui s'execute quand on clique sur un bouton. + """ + match name: + case "yes": + world[CurrentScene] = send_to_server.SEND + case "no": + world[CurrentScene] = try_again.TRY_AGAIN + case _: + pass + world.new_entity().set(KeepAlive(), Sound("click.wav")) + + +GAME_OVER = Scene( + [__spawn_elements], + [], + [], +) diff --git a/src/scenes/menu.py b/src/scenes/menu.py index 0c88bd3..3a04447 100644 --- a/src/scenes/menu.py +++ b/src/scenes/menu.py @@ -1,107 +1,107 @@ -""" -La scène du menu principal du jeu. - -Dans cette scène nous pouvons choisir le mode de jeu. -""" -from plugins.sound import Loop, Sound -from engine import CurrentScene, KeepAlive, Scene -from engine.ecs import Entity, World -from engine.math import Vec2 -from plugins import render -from plugins.click import Clickable -from plugins.hover import HoveredTexture -from plugins.render import SpriteBundle, TextBundle -from plugins.timing import Time -from scenes import game -import requests as rq - -IP = "pong.cocosol.fr" - - -def get_scores() -> list[tuple[int, str]]: - try: - return rq.get(f"https://{IP}/data").json() - except: - print("Error with the serveur") - return [(1, "")] - - -def __create_button(world: World, i: int, name: str): - """ - Ajoute un bouton au monde. - """ - world.new_entity().set( - SpriteBundle( - f"button_{name}.png", - position=Vec2(450 + 540 * i, 11 * render.HEIGHT / 16), - order=1, - origin=Vec2(0.5), - ), - HoveredTexture( - f"button_{name}.png", - f"button_{name}_hover.png", - ), - Clickable(lambda world, entity: __on_click_butons(world, entity, name)), - ) - - -def __on_click_butons(world: World, _entity: Entity, name: str): - """ - Fonction qui s'execute quand on clique sur un bouton. - """ - match name: - case "one_player": - world[CurrentScene] = game.ONE_PLAYER - case "two_player": - world[CurrentScene] = game.TWO_PLAYER - case _: - pass - world.new_entity().set(KeepAlive(), Sound("click.wav")) - - -def __spawn_elements(world: World): - """ - Ajoute les éléments du menu dans le monde. - """ - if world[Time] < 1: - world.new_entity().set(Sound("music.mp3"), KeepAlive(), Loop()) - - world.new_entity().set(SpriteBundle("background_menu.png", -5)) - - scenes_name = ["one_player", "two_player"] - for i, name in enumerate(scenes_name): - __create_button(world, i, name) - - __spawn_score(world) - - -def __spawn_score(world: World): - """ - Ajoute le score dans le monde. - """ - print(get_scores()) - for i, (score, name) in enumerate(get_scores()): - world.new_entity().set( - TextBundle( - f"{name}", - position=Vec2(render.WIDTH / 2 - 350, 325 + 50 * i), - origin=Vec2(0), - order=1, - ) - ) - - world.new_entity().set( - TextBundle( - f"{score}", - position=Vec2(render.WIDTH / 2 + 350, 325 + 50 * i), - origin=Vec2(1, 0), - order=1, - ) - ) - - -MENU = Scene( - [__spawn_elements], - [], - [], -) +""" +La scène du menu principal du jeu. + +Dans cette scène nous pouvons choisir le mode de jeu. +""" +from plugins.sound import Loop, Sound +from engine import CurrentScene, KeepAlive, Scene +from engine.ecs import Entity, World +from engine.math import Vec2 +from plugins import render +from plugins.click import Clickable +from plugins.hover import HoveredTexture +from plugins.render import SpriteBundle, TextBundle +from plugins.timing import Time +from scenes import game +import requests as rq + +IP = "pong.cocosol.fr" + + +def get_scores() -> list[tuple[int, str]]: + try: + return rq.get(f"https://{IP}/data").json() + except: + print("Error with the serveur") + return [(1, "")] + + +def __create_button(world: World, i: int, name: str): + """ + Ajoute un bouton au monde. + """ + world.new_entity().set( + SpriteBundle( + f"button_{name}.png", + position=Vec2(450 + 540 * i, 11 * render.HEIGHT / 16), + order=1, + origin=Vec2(0.5), + ), + HoveredTexture( + f"button_{name}.png", + f"button_{name}_hover.png", + ), + Clickable(lambda world, entity: __on_click_butons(world, entity, name)), + ) + + +def __on_click_butons(world: World, _entity: Entity, name: str): + """ + Fonction qui s'execute quand on clique sur un bouton. + """ + match name: + case "one_player": + world[CurrentScene] = game.ONE_PLAYER + case "two_player": + world[CurrentScene] = game.TWO_PLAYER + case _: + pass + world.new_entity().set(KeepAlive(), Sound("click.wav")) + + +def __spawn_elements(world: World): + """ + Ajoute les éléments du menu dans le monde. + """ + if world[Time] < 1: + world.new_entity().set(Sound("music.mp3"), KeepAlive(), Loop()) + + world.new_entity().set(SpriteBundle("background_menu.png", -5)) + + scenes_name = ["one_player", "two_player"] + for i, name in enumerate(scenes_name): + __create_button(world, i, name) + + __spawn_score(world) + + +def __spawn_score(world: World): + """ + Ajoute le score dans le monde. + """ + print(get_scores()) + for i, (score, name) in enumerate(get_scores()): + world.new_entity().set( + TextBundle( + f"{name}", + position=Vec2(render.WIDTH / 2 - 350, 325 + 50 * i), + origin=Vec2(0), + order=1, + ) + ) + + world.new_entity().set( + TextBundle( + f"{score}", + position=Vec2(render.WIDTH / 2 + 350, 325 + 50 * i), + origin=Vec2(1, 0), + order=1, + ) + ) + + +MENU = Scene( + [__spawn_elements], + [], + [], +) diff --git a/src/scenes/send_to_server.py b/src/scenes/send_to_server.py index 9fb555c..50cb51c 100644 --- a/src/scenes/send_to_server.py +++ b/src/scenes/send_to_server.py @@ -1,93 +1,93 @@ -from plugins import writing -from engine import CurrentScene, Plugin -from engine.ecs import Entity, World -from engine.math import Vec2 -from plugins import render -from plugins.click import Clickable -from plugins.hover import HoveredTexture -from plugins.render import SpriteBundle, Text, TextBundle -from plugins.timing import TimedEvent -from plugins.writing import Writing -import requests as rq -from scenes import game, thanks - -IP = "pong.cocosol.fr" - - -def new_score(world: World, e: Entity): - e.remove(Clickable) - name = world.query(Writing).pop() - - try: - post = {"name": name[Text], "score": world[game.Player1Score]} - print(post) - rq.post(f"https://{IP}/new_score", post) - world.new_entity().set( - TimedEvent( - 1, - lambda world, entity: world.set(CurrentScene(thanks.THANKS)), - ) - ) - except: - print("Error with the serveur") - - -def get_scores(): - try: - return rq.get(f"https://{IP}/data").json() - except: - print("Error with the serveur") - - -def __spawn_elements(world: World): - """ - Ajoute les éléments du menu dans le monde. - """ - - world.new_entity().set(SpriteBundle("background.jpg", -5)) - world.new_entity().set( - TextBundle( - "Quel est votre pseudo ?", - 0, - position=Vec2(render.WIDTH / 2, 350), - origin=Vec2(0.5), - ), - ) - world.new_entity().set( - TextBundle( - "...", - 0, - 50, - position=Vec2(render.WIDTH / 2, 475), - origin=Vec2(0.5), - ), - Writing( - "azertyuiopqsdfghjklmwxcvbn0123456789_-/", - 16, - "...", - ), - ) - - world.new_entity().set( - SpriteBundle( - f"button_one_player.png", - position=Vec2(render.WIDTH / 2, 600), - order=1, - origin=Vec2(0.5), - ), - HoveredTexture( - f"button_submit.png", - f"button_submit_hover.png", - ), - Clickable(new_score), - ) - - -SEND = ( - Plugin( - [__spawn_elements], - [], - [], - ) - + writing.PLUGIN -) +from plugins import writing +from engine import CurrentScene, Plugin +from engine.ecs import Entity, World +from engine.math import Vec2 +from plugins import render +from plugins.click import Clickable +from plugins.hover import HoveredTexture +from plugins.render import SpriteBundle, Text, TextBundle +from plugins.timing import TimedEvent +from plugins.writing import Writing +import requests as rq +from scenes import game, thanks + +IP = "pong.cocosol.fr" + + +def new_score(world: World, e: Entity): + e.remove(Clickable) + name = world.query(Writing).pop() + + try: + post = {"name": name[Text], "score": world[game.Player1Score]} + print(post) + rq.post(f"https://{IP}/new_score", post) + world.new_entity().set( + TimedEvent( + 1, + lambda world, entity: world.set(CurrentScene(thanks.THANKS)), + ) + ) + except: + print("Error with the serveur") + + +def get_scores(): + try: + return rq.get(f"https://{IP}/data").json() + except: + print("Error with the serveur") + + +def __spawn_elements(world: World): + """ + Ajoute les éléments du menu dans le monde. + """ + + world.new_entity().set(SpriteBundle("background.jpg", -5)) + world.new_entity().set( + TextBundle( + "Quel est votre pseudo ?", + 0, + position=Vec2(render.WIDTH / 2, 350), + origin=Vec2(0.5), + ), + ) + world.new_entity().set( + TextBundle( + "...", + 0, + 50, + position=Vec2(render.WIDTH / 2, 475), + origin=Vec2(0.5), + ), + Writing( + "azertyuiopqsdfghjklmwxcvbn0123456789_-/", + 16, + "...", + ), + ) + + world.new_entity().set( + SpriteBundle( + f"button_one_player.png", + position=Vec2(render.WIDTH / 2, 600), + order=1, + origin=Vec2(0.5), + ), + HoveredTexture( + f"button_submit.png", + f"button_submit_hover.png", + ), + Clickable(new_score), + ) + + +SEND = ( + Plugin( + [__spawn_elements], + [], + [], + ) + + writing.PLUGIN +) diff --git a/src/scenes/thanks.py b/src/scenes/thanks.py index 0d58cf5..6b89809 100644 --- a/src/scenes/thanks.py +++ b/src/scenes/thanks.py @@ -1,37 +1,37 @@ -from engine import CurrentScene, Scene -from engine.ecs import World -from engine.math import Vec2 -from plugins import render -from plugins.render import SpriteBundle, TextBundle -from plugins.timing import TimedEvent -from scenes import menu - - -def __spawn_elements(world: World): - world.new_entity().set(SpriteBundle("background.jpg", -5)) - world.new_entity().set( - TextBundle( - "Merci,", - 0, - 150, - position=Vec2(render.WIDTH / 2, render.HEIGHT / 2 - 75), - origin=Vec2(0.5), - ), - TimedEvent(3, lambda world, entity: world.set(CurrentScene(menu.MENU))), - ) - world.new_entity().set( - TextBundle( - "Votre score a bien été envoyé !", - 0, - 100, - position=Vec2(render.WIDTH / 2, render.HEIGHT / 2 + 75), - origin=Vec2(0.5), - ), - ) - - -THANKS = Scene( - [__spawn_elements], - [], - [], -) +from engine import CurrentScene, Scene +from engine.ecs import World +from engine.math import Vec2 +from plugins import render +from plugins.render import SpriteBundle, TextBundle +from plugins.timing import TimedEvent +from scenes import menu + + +def __spawn_elements(world: World): + world.new_entity().set(SpriteBundle("background.jpg", -5)) + world.new_entity().set( + TextBundle( + "Merci,", + 0, + 150, + position=Vec2(render.WIDTH / 2, render.HEIGHT / 2 - 75), + origin=Vec2(0.5), + ), + TimedEvent(3, lambda world, entity: world.set(CurrentScene(menu.MENU))), + ) + world.new_entity().set( + TextBundle( + "Votre score a bien été envoyé !", + 0, + 100, + position=Vec2(render.WIDTH / 2, render.HEIGHT / 2 + 75), + origin=Vec2(0.5), + ), + ) + + +THANKS = Scene( + [__spawn_elements], + [], + [], +) diff --git a/src/scenes/try_again.py b/src/scenes/try_again.py index f1f4220..06b9768 100644 --- a/src/scenes/try_again.py +++ b/src/scenes/try_again.py @@ -1,73 +1,73 @@ -""" -La scène du menu principal du jeu. - -Dans cette scène nous pouvons choisir le mode de jeu. -""" -from plugins.sound import Sound -from engine import CurrentScene, KeepAlive, Scene -from engine.ecs import Entity, World -from engine.math import Vec2 -from plugins import render -from plugins.click import Clickable -from plugins.hover import HoveredTexture -from plugins.render import SpriteBundle, TextBundle -from scenes import game, menu - - -def __create_button(world: World, i: int, name: str): - """ - Ajoute un bouton au monde. - """ - world.new_entity().set( - SpriteBundle( - f"button_{name}.png", - position=Vec2(450 + 540 * i, render.HEIGHT / 2), - order=1, - origin=Vec2(0.5), - ), - HoveredTexture( - f"button_{name}.png", - f"button_{name}_hover.png", - ), - Clickable(lambda world, entity: __on_click_butons(world, entity, name)), - ) - - -def __on_click_butons(world: World, _entity: Entity, name: str): - """ - Fonction qui s'execute quand on clique sur un bouton. - """ - match name: - case "yes": - world[CurrentScene] = menu.MENU - case "no": - world[CurrentScene] = game.ONE_PLAYER - case _: - pass - world.new_entity().set(KeepAlive(), Sound("click.wav")) - - -def __spawn_elements(world: World): - """ - Ajoute les éléments du menu dans le monde. - """ - - world.new_entity().set(SpriteBundle("background.jpg", -5)) - world.new_entity().set( - TextBundle( - "Voulez vous changer\nde mode de jeu ?", - 0, - position=Vec2(render.WIDTH / 2, 350), - origin=Vec2(0.5), - ), - ) - scenes_name = ["yes", "no"] - for i, name in enumerate(scenes_name): - __create_button(world, i, name) - - -TRY_AGAIN = Scene( - [__spawn_elements], - [], - [], -) +""" +La scène du menu principal du jeu. + +Dans cette scène nous pouvons choisir le mode de jeu. +""" +from plugins.sound import Sound +from engine import CurrentScene, KeepAlive, Scene +from engine.ecs import Entity, World +from engine.math import Vec2 +from plugins import render +from plugins.click import Clickable +from plugins.hover import HoveredTexture +from plugins.render import SpriteBundle, TextBundle +from scenes import game, menu + + +def __create_button(world: World, i: int, name: str): + """ + Ajoute un bouton au monde. + """ + world.new_entity().set( + SpriteBundle( + f"button_{name}.png", + position=Vec2(450 + 540 * i, render.HEIGHT / 2), + order=1, + origin=Vec2(0.5), + ), + HoveredTexture( + f"button_{name}.png", + f"button_{name}_hover.png", + ), + Clickable(lambda world, entity: __on_click_butons(world, entity, name)), + ) + + +def __on_click_butons(world: World, _entity: Entity, name: str): + """ + Fonction qui s'execute quand on clique sur un bouton. + """ + match name: + case "yes": + world[CurrentScene] = menu.MENU + case "no": + world[CurrentScene] = game.ONE_PLAYER + case _: + pass + world.new_entity().set(KeepAlive(), Sound("click.wav")) + + +def __spawn_elements(world: World): + """ + Ajoute les éléments du menu dans le monde. + """ + + world.new_entity().set(SpriteBundle("background.jpg", -5)) + world.new_entity().set( + TextBundle( + "Voulez vous changer\nde mode de jeu ?", + 0, + position=Vec2(render.WIDTH / 2, 350), + origin=Vec2(0.5), + ), + ) + scenes_name = ["yes", "no"] + for i, name in enumerate(scenes_name): + __create_button(world, i, name) + + +TRY_AGAIN = Scene( + [__spawn_elements], + [], + [], +) -- 2.43.4