From c47cae3967b448db29aaf68907e953784271500f Mon Sep 17 00:00:00 2001 From: Tipragot Date: Fri, 3 Nov 2023 10:54:20 +0100 Subject: [PATCH] =?UTF-8?q?Ajout=20du=20d=C3=A9placement=20des=20dossiers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../story/directory_search/move_directory.wav | Bin src/plugins/text.py | 16 +- src/scenes/story/directory_search.py | 215 +++++++++++++++++- 3 files changed, 218 insertions(+), 13 deletions(-) rename assets save/sounds/slide.wav => assets/story/directory_search/move_directory.wav (100%) diff --git a/assets save/sounds/slide.wav b/assets/story/directory_search/move_directory.wav similarity index 100% rename from assets save/sounds/slide.wav rename to assets/story/directory_search/move_directory.wav diff --git a/src/plugins/text.py b/src/plugins/text.py index 92e602f..8d08c5c 100644 --- a/src/plugins/text.py +++ b/src/plugins/text.py @@ -3,6 +3,7 @@ Un plugin permettant d'afficher du texte à l'écran. """ +from typing import Optional import pygame from engine import GlobalPlugin @@ -22,9 +23,9 @@ class Text: text: str, size: int = 50, color: pygame.Color = pygame.Color(255, 255, 255), - position: Vec2 = Vec2(0), - order: float = -1.0, - origin: Vec2 = Vec2(0), + position: Optional[Vec2] = None, + order: Optional[float] = None, + origin: Optional[Vec2] = None, ): self.text = text self.size = size @@ -48,9 +49,12 @@ def __render_texts(world: World): entity[Sprite].texture = texture else: entity[Sprite] = Sprite(texture) - entity[Sprite].position = text.position - entity[Sprite].order = text.order - entity[Sprite].origin = text.origin + if text.position is not None: + entity[Sprite].position = text.position + if text.order is not None: + entity[Sprite].order = text.order + if text.origin is not None: + entity[Sprite].origin = text.origin PLUGIN = GlobalPlugin( diff --git a/src/scenes/story/directory_search.py b/src/scenes/story/directory_search.py index 2d6ca26..97f171e 100644 --- a/src/scenes/story/directory_search.py +++ b/src/scenes/story/directory_search.py @@ -3,15 +3,92 @@ Scène du jeu dans lequel Windows Defender se cache de Edmond dans les dossiers. """ from engine import Scene -from engine.ecs import Entity +from engine.ecs import Entity, World from engine.math import Vec2 -from plugins import assets as plugin_assets, render +from plugins import assets as plugin_assets, render, smooth +from plugins.click import Clicked +from plugins.inputs import Held, MousePosition +from plugins.assets import Assets +from plugins.render import Sprite +from plugins.sound import Sound +from plugins.text import Text LINES = 3 COLUMNS = 5 SPACING = 200 +NAMES = [ + "Classique", + "Menteur", + "Tricheur", + "Histoire", + "Je t'aime", + "Hello", + "Cheval", + "Defender", + "Dansons", + "Secrets", + "Edmond", + "Mon Amour", + "Melatonin", + "Films", + "Cinéma", +] + +POSITIONS = [ + Vec2(1348, 903), + Vec2(988, 903), + Vec2(808, 737), + Vec2(628, 903), + Vec2(268, 903), + Vec2(1168, 405), + Vec2(988, 571), + Vec2(808, 405), + Vec2(448, 737), + Vec2(268, 405), + Vec2(1348, 239), + Vec2(988, 239), + Vec2(628, 73), + Vec2(448, 239), + Vec2(88, 239), +] + + +class Directory: + """ + Composant marquand une entité comme étant un dossier. + """ + + +class DefenderDirectory: + """ + Composant marquant une entité comme étant le dossier de Windows Defender. + """ + + +class BlockedDirectory: + """ + Composant marquant une entité comme etant un dossier bloqué. + """ + + +class SearchingDirectory: + """ + Composant marquant une entité comme etant un dossier en train de être fouillé. + """ + + +class DirectoryName: + """ + Composant marquant une entité comme étant le nom d'un dossier. + + Ce composant contient l'entité auquel il est lie. + """ + + def __init__(self, entity: Entity): + self.entity = entity + class DirectoryPosition(Vec2): """ @@ -37,16 +114,140 @@ class SelectedDirectory: de la souris lors du clic. """ - def __init__(self, entity: Entity, position: Vec2): + def __init__(self, entity: Entity, mouse_position: Vec2): self.entity = entity - self.position = position + self.mouse_position = mouse_position + + +def __initialize(world: World): + """ + Prépare le monde pour le lancement de la scène. + + Cette fonction fait apparaitre tous les dossiers et lance la boucle de jeu. + """ + assets = world[Assets] + + # Ajout du fond + world.new_entity().set(Sprite(assets.get_texture("background"))) + + # Ajout des dossiers et des noms + directory_texture = assets.get_texture("directory") + for y in range(LINES): + for x in range(COLUMNS): + # Récupération du nom et de la position + position = POSITIONS.pop() + name = NAMES.pop() + + # Création de l'entité du dossier + entity = world.new_entity() + entity.set( + Sprite(directory_texture, position, 1, origin=Vec2(0.5)), + DirectoryPosition(x, y), + Directory(), + ) + if name == "Defender": + entity.set(DefenderDirectory()) + entity[Sprite].texture = assets.get_texture("defender_directory") + + # Création de l'entité du nom + world.new_entity().set( + Sprite(directory_texture, position + Vec2(0, 75)), + Text(name, 40, order=1, origin=Vec2(0.5)), + DirectoryName(entity), + ) + + +def __control_directories(world: World): + """ + Ce système gère les déplacements de dossiers fais par l'utilisateur. + """ + # Si aucuns dossier n'est séléctioné, on attend que l'utilisateur clique sur un dossier, si + # le dossier cliqué est en train de être fouillé ou que le dossier est bloqué, on ignore + if SelectedDirectory not in world: + entities = world.query( + Clicked, Directory, without=(SearchingDirectory, BlockedDirectory) + ) + if len(entities) > 0: + world.set(SelectedDirectory(entities.pop(), Vec2(world[MousePosition]))) + else: + return + selected = world[SelectedDirectory] + + # Si le boutton de la souris a été relaché entre temps, on supprime le dossier selectionné. + if "button_1" not in world[Held]: + del world[SelectedDirectory] + return + + # Ensuite on vérifie de combien la souris a été déplacé depuis la selection du dossier, + # si cette valeur est en dessous d'un certain seuil, on ne fais rien + mouse_delta = world[MousePosition] - selected.mouse_position + if mouse_delta.length < 40: + return + + # On récupère le mouvement voulu, pour cela on compare la valeur absolue du déplacement + # de la souris sur l'axe des x et de la souris sur l'axe des y pour savoir lequel + # est le plus grand, puis on en deduit le mouvement voulu. + if abs(mouse_delta.x) >= abs(mouse_delta.y): + movement = Vec2(mouse_delta.x / abs(mouse_delta.x), 0) + else: + movement = Vec2(0, mouse_delta.y / abs(mouse_delta.y)) + + # On vérifie que le mouvement ne fait pas sortir le dossier de la grille. + new_position = selected.entity[DirectoryPosition] + movement + if ( + new_position.x < 0 + or new_position.x >= COLUMNS + or new_position.y < 0 + or new_position.y >= LINES + ): + return + + # On trouve le dossier vers lequel on souhaite se diriger, si le dossier + # est en train de être fouillé ou que le dossier est bloqué, on ne fait rien + for entity in world.query( + Directory, without=(SearchingDirectory, BlockedDirectory) + ): + if entity[DirectoryPosition] == new_position: + other_directory = entity + break + else: + return + + # On inverse la position des deux dossiers + selected_directory = selected.entity + other_directory[DirectoryPosition], selected_directory[DirectoryPosition] = ( + selected_directory[DirectoryPosition], + other_directory[DirectoryPosition], + ) + + # On joue un son de déplacement + world.new_entity().set(Sound(world[Assets].get_sound("move_directory"))) + + # On supprime le dossier selectionné + del world[SelectedDirectory] + + +def __update_graphics(world: World): + """ + Met à jour tous ce qui est relatif au graphismes de la scène. + """ + # On met à jour la position des dossiers + for entity in world.query(Directory, DirectoryPosition): + entity.set(smooth.Target(entity[DirectoryPosition].screen_position())) + + # On met à jour la position des noms des dossiers + for entity in world.query(DirectoryName): + entity[smooth.Target] = entity[DirectoryName].entity[smooth.Target] + Vec2( + 0, 75 + ) SCENE = plugin_assets.loading_scene( Scene( + [__initialize], + [__control_directories, __update_graphics], [], - [], - [], - ), + ) + + smooth.PLUGIN, "story/directory_search", )