diff --git a/assets/krita/blue_directory.kra b/assets/krita/blue_directory.kra new file mode 100644 index 0000000..c1b78cb Binary files /dev/null and b/assets/krita/blue_directory.kra differ diff --git a/assets/krita/loupe.kra b/assets/krita/loupe.kra new file mode 100644 index 0000000..394ed00 Binary files /dev/null and b/assets/krita/loupe.kra differ diff --git a/assets/sounds/slide.wav b/assets/sounds/slide.wav new file mode 100644 index 0000000..446772d Binary files /dev/null and b/assets/sounds/slide.wav differ diff --git a/assets/textures/animations/fade_desktop/0000.png b/assets/textures/animations/fade_desktop/0000.png new file mode 100644 index 0000000..86a7d08 Binary files /dev/null and b/assets/textures/animations/fade_desktop/0000.png differ diff --git a/assets/textures/animations/fade_desktop/0001.png b/assets/textures/animations/fade_desktop/0001.png new file mode 100644 index 0000000..d694b19 Binary files /dev/null and b/assets/textures/animations/fade_desktop/0001.png differ diff --git a/assets/textures/animations/fade_desktop/0002.png b/assets/textures/animations/fade_desktop/0002.png new file mode 100644 index 0000000..0b41b31 Binary files /dev/null and b/assets/textures/animations/fade_desktop/0002.png differ diff --git a/assets/textures/animations/fade_desktop/0003.png b/assets/textures/animations/fade_desktop/0003.png new file mode 100644 index 0000000..6a3cf50 Binary files /dev/null and b/assets/textures/animations/fade_desktop/0003.png differ diff --git a/assets/textures/animations/fade_desktop/0004.png b/assets/textures/animations/fade_desktop/0004.png new file mode 100644 index 0000000..16efdff Binary files /dev/null and b/assets/textures/animations/fade_desktop/0004.png differ diff --git a/assets/textures/animations/fade_desktop/0005.png b/assets/textures/animations/fade_desktop/0005.png new file mode 100644 index 0000000..c53eacb Binary files /dev/null and b/assets/textures/animations/fade_desktop/0005.png differ diff --git a/assets/textures/animations/fade_desktop/0006.png b/assets/textures/animations/fade_desktop/0006.png new file mode 100644 index 0000000..045c404 Binary files /dev/null and b/assets/textures/animations/fade_desktop/0006.png differ diff --git a/assets/textures/animations/fade_desktop/0007.png b/assets/textures/animations/fade_desktop/0007.png new file mode 100644 index 0000000..9ece0a9 Binary files /dev/null and b/assets/textures/animations/fade_desktop/0007.png differ diff --git a/assets/textures/animations/fade_desktop/0008.png b/assets/textures/animations/fade_desktop/0008.png new file mode 100644 index 0000000..e9c93a3 Binary files /dev/null and b/assets/textures/animations/fade_desktop/0008.png differ diff --git a/assets/textures/animations/fade_desktop/0009.png b/assets/textures/animations/fade_desktop/0009.png new file mode 100644 index 0000000..3906dea Binary files /dev/null and b/assets/textures/animations/fade_desktop/0009.png differ diff --git a/assets/textures/animations/fade_desktop/0010.png b/assets/textures/animations/fade_desktop/0010.png new file mode 100644 index 0000000..0ad2fcc Binary files /dev/null and b/assets/textures/animations/fade_desktop/0010.png differ diff --git a/assets/textures/animations/fade_desktop/0011.png b/assets/textures/animations/fade_desktop/0011.png new file mode 100644 index 0000000..74c5ef6 Binary files /dev/null and b/assets/textures/animations/fade_desktop/0011.png differ diff --git a/assets/textures/animations/fade_desktop/0012.png b/assets/textures/animations/fade_desktop/0012.png new file mode 100644 index 0000000..4ddb12d Binary files /dev/null and b/assets/textures/animations/fade_desktop/0012.png differ diff --git a/assets/textures/animations/fade_desktop/0013.png b/assets/textures/animations/fade_desktop/0013.png new file mode 100644 index 0000000..973fdc0 Binary files /dev/null and b/assets/textures/animations/fade_desktop/0013.png differ diff --git a/assets/textures/animations/fade_desktop/0014.png b/assets/textures/animations/fade_desktop/0014.png new file mode 100644 index 0000000..823301b Binary files /dev/null and b/assets/textures/animations/fade_desktop/0014.png differ diff --git a/assets/textures/animations/fade_desktop/0015.png b/assets/textures/animations/fade_desktop/0015.png new file mode 100644 index 0000000..cc7f6ad Binary files /dev/null and b/assets/textures/animations/fade_desktop/0015.png differ diff --git a/assets/textures/animations/fade_desktop/0016.png b/assets/textures/animations/fade_desktop/0016.png new file mode 100644 index 0000000..9f8d07f Binary files /dev/null and b/assets/textures/animations/fade_desktop/0016.png differ diff --git a/assets/textures/animations/fade_desktop/0017.png b/assets/textures/animations/fade_desktop/0017.png new file mode 100644 index 0000000..51ec70e Binary files /dev/null and b/assets/textures/animations/fade_desktop/0017.png differ diff --git a/assets/textures/animations/fade_desktop/0018.png b/assets/textures/animations/fade_desktop/0018.png new file mode 100644 index 0000000..46d7aac Binary files /dev/null and b/assets/textures/animations/fade_desktop/0018.png differ diff --git a/assets/textures/animations/fade_desktop/0019.png b/assets/textures/animations/fade_desktop/0019.png new file mode 100644 index 0000000..f7ddab4 Binary files /dev/null and b/assets/textures/animations/fade_desktop/0019.png differ diff --git a/assets/textures/animations/fade_desktop/0020.png b/assets/textures/animations/fade_desktop/0020.png new file mode 100644 index 0000000..2c20471 Binary files /dev/null and b/assets/textures/animations/fade_desktop/0020.png differ diff --git a/assets/textures/animations/fade_desktop/0021.png b/assets/textures/animations/fade_desktop/0021.png new file mode 100644 index 0000000..52c1cc7 Binary files /dev/null and b/assets/textures/animations/fade_desktop/0021.png differ diff --git a/assets/textures/animations/fade_desktop/0022.png b/assets/textures/animations/fade_desktop/0022.png new file mode 100644 index 0000000..6d583b7 Binary files /dev/null and b/assets/textures/animations/fade_desktop/0022.png differ diff --git a/assets/textures/animations/fade_desktop/0023.png b/assets/textures/animations/fade_desktop/0023.png new file mode 100644 index 0000000..d8b77ec Binary files /dev/null and b/assets/textures/animations/fade_desktop/0023.png differ diff --git a/assets/textures/animations/fade_desktop/0024.png b/assets/textures/animations/fade_desktop/0024.png new file mode 100644 index 0000000..7180bd3 Binary files /dev/null and b/assets/textures/animations/fade_desktop/0024.png differ diff --git a/assets/textures/animations/fade_desktop/0025.png b/assets/textures/animations/fade_desktop/0025.png new file mode 100644 index 0000000..c29681d Binary files /dev/null and b/assets/textures/animations/fade_desktop/0025.png differ diff --git a/assets/textures/animations/fade_desktop/0026.png b/assets/textures/animations/fade_desktop/0026.png new file mode 100644 index 0000000..a82d5c8 Binary files /dev/null and b/assets/textures/animations/fade_desktop/0026.png differ diff --git a/assets/textures/animations/fade_desktop/0027.png b/assets/textures/animations/fade_desktop/0027.png new file mode 100644 index 0000000..553c413 Binary files /dev/null and b/assets/textures/animations/fade_desktop/0027.png differ diff --git a/assets/textures/animations/fade_desktop/0028.png b/assets/textures/animations/fade_desktop/0028.png new file mode 100644 index 0000000..efa3309 Binary files /dev/null and b/assets/textures/animations/fade_desktop/0028.png differ diff --git a/assets/textures/animations/fade_desktop/0029.png b/assets/textures/animations/fade_desktop/0029.png new file mode 100644 index 0000000..f39883f Binary files /dev/null and b/assets/textures/animations/fade_desktop/0029.png differ diff --git a/assets/textures/animations/fade_desktop/0030.png b/assets/textures/animations/fade_desktop/0030.png new file mode 100644 index 0000000..f26ba7f Binary files /dev/null and b/assets/textures/animations/fade_desktop/0030.png differ diff --git a/assets/textures/animations/fade_desktop/info.json b/assets/textures/animations/fade_desktop/info.json new file mode 100644 index 0000000..9be05ca --- /dev/null +++ b/assets/textures/animations/fade_desktop/info.json @@ -0,0 +1,9 @@ +{ + "end_image": "dark_desktop.png", + "offset": { + "x": 0, + "y": 0 + }, + "frame_count": 31, + "fps": 60 +} \ No newline at end of file diff --git a/assets/textures/animations/search_directory/info.json b/assets/textures/animations/search_directory/info.json index 10627ba..ff880c4 100644 --- a/assets/textures/animations/search_directory/info.json +++ b/assets/textures/animations/search_directory/info.json @@ -1,8 +1,7 @@ { - "end_image": "directory.png", "offset": { - "x": -48, - "y": -176 + "x": 8, + "y": -83 }, "frame_count": 268, "fps": 60 diff --git a/assets/textures/animations/search_directory_failed/info.json b/assets/textures/animations/search_directory_failed/info.json new file mode 100644 index 0000000..ff880c4 --- /dev/null +++ b/assets/textures/animations/search_directory_failed/info.json @@ -0,0 +1,8 @@ +{ + "offset": { + "x": 8, + "y": -83 + }, + "frame_count": 268, + "fps": 60 +} \ No newline at end of file diff --git a/assets/textures/attack_point.png b/assets/textures/attack_point.png new file mode 100644 index 0000000..81f7329 Binary files /dev/null and b/assets/textures/attack_point.png differ diff --git a/assets/textures/dark_desktop.png b/assets/textures/dark_desktop.png new file mode 100644 index 0000000..f26ba7f Binary files /dev/null and b/assets/textures/dark_desktop.png differ diff --git a/assets/textures/user_directory.png b/assets/textures/user_directory.png new file mode 100644 index 0000000..87e7ca8 Binary files /dev/null and b/assets/textures/user_directory.png differ diff --git a/src/engine.py b/src/engine.py index 718595b..c604f32 100644 --- a/src/engine.py +++ b/src/engine.py @@ -434,6 +434,7 @@ class Mouse: self.pressed: set[int] = set() self.released: set[int] = set() self.position: Vec2 = Vec2(0.0, 0.0) + self.delta: Vec2 = Vec2(0.0, 0.0) def is_button_pressed(self, button: int) -> bool: """ @@ -677,6 +678,7 @@ def start_game( keyboard.released.clear() mouse.pressed.clear() mouse.released.clear() + last_position = Vec2(mouse.position) for event in pygame.event.get(): if event.type == pygame.QUIT: world[Game].stop() @@ -704,6 +706,7 @@ def start_game( ((event.pos[0] - rect[0]) / rect[2]) * Display.WIDTH, ((event.pos[1] - rect[1]) / rect[3]) * Display.HEIGHT, ) + mouse.delta = mouse.position - last_position # On vérifie le survol des textures et textes for entity in world.query(Position, Texture): diff --git a/src/main.py b/src/main.py index 007c2f8..249f751 100644 --- a/src/main.py +++ b/src/main.py @@ -4,13 +4,14 @@ Example de l'utilisation du moteur de jeu. from engine import start_game -from scenes import classique, menu +from scenes import directory_search, menu, classique start_game( { "menu": menu.SCENE, - "classique": classique.SCENE + "classique": classique.SCENE, + "histoire": directory_search.SCENE, }, "menu", title="Guess The Number", diff --git a/src/plugins/smooth.py b/src/plugins/smooth.py new file mode 100644 index 0000000..0f9681e --- /dev/null +++ b/src/plugins/smooth.py @@ -0,0 +1,37 @@ +""" +Un plugin permettant de faire des déplacements fluides des entités. +""" + +from engine import Delta, Position, Scene, Vec2, World + + +class Target(Vec2): + """ + Composant donnant la position voulue de l'entité. + """ + + +class Speed(float): + """ + Composant donnant la vittesse de déplacement de l'entité. + """ + + +def __update_positions(world: World): + """ + Met à jour la position des entités pour se rapprocher de la position voulue. + """ + for entity in world.query(Position, Target): + position = entity[Position] + target = entity[Target] + speed = entity[Speed] if Speed in entity else Speed(10) + entity[Position] = Position( + position + (target - position) * world[Delta] * speed + ) + + +PLUGIN = Scene( + [], + [__update_positions], + [], +) diff --git a/src/scenes/directory_search.py b/src/scenes/directory_search.py new file mode 100644 index 0000000..cd50f94 --- /dev/null +++ b/src/scenes/directory_search.py @@ -0,0 +1,378 @@ +""" +Scène du jeu dans lequel on se cache de Edmond dans les dossiers. +""" + +from enum import Enum +import random +from engine import ( + Animation, + Centered, + Delta, + Display, + Entity, + Hovered, + Mouse, + Order, + Position, + Scene, + Sound, + Text, + TextSize, + Texture, + Vec2, + World, +) +from plugins import smooth + + +LINES = 3 +COLUMNS = 5 +SPACING = 200 + + +class State(Enum): + """ + Etat de la scène. + """ + + MOVING = 0 + SEARCHING = 1 + GAME_OVER = 2 + + +class SelectedDirectory: + """ + Une ressource qui stoque le dossier selectionné pour le déplacement. + """ + + def __init__(self, entity: Entity, start_position: Vec2): + self.entity = entity + self.position = start_position + + +class AttackTimer(float): + """ + Ressource qui stoque un timer pour l'attaque. + """ + + +class AttackSpeed(float): + """ + Ressource qui dit le temps de l'attaque. + """ + + +class DirectoryPosition: + """ + La position d'un dossier dans la grille. + """ + + def __init__(self, x: int, y: int): + self.x = x + self.y = y + + def __eq__(self, value: object) -> bool: + if isinstance(value, DirectoryPosition): + return self.x == value.x and self.y == value.y + return False + + def screen_position(self) -> Vec2: + """ + Calcule la position de l'entité sur l'ecran. + """ + size = Vec2(SPACING) + offset = -(size * Vec2(COLUMNS - 1, LINES - 1) / 2) + first_position = Vec2(Display.WIDTH / 2, Display.HEIGHT / 2) + offset + return first_position + Vec2(self.x, self.y) * size + + +class AttackPoint(DirectoryPosition): + """ + Composant qui marque un point d'attaque. + """ + + +class DirectoryName: + """ + Composant qui marque une entité comme étant le nom d'un dossier. + """ + + def __init__(self, entity: Entity): + self.entity = entity + + +class UserDirectory: + """ + Composant qui marque le dossier que l'utilisateur doit protéger. + """ + + +class GameStarted: + """ + Une ressource qui permet de savoir que le jeu commence. + """ + + +def __change_folders_speeds(world: World, _e: Entity): + """ + Change les vitesses des dossiers. + """ + for entity in world.query(DirectoryPosition, smooth.Speed): + entity[smooth.Speed] = smooth.Speed(random.uniform(2.0, 2.5)) + for entity in world.query(TextSize): + entity[TextSize] = TextSize(40) + + +def __remove_folders_speeds(world: World): + """ + Supprime les vitesses des dossiers. + """ + if GameStarted not in world and world[AttackTimer] >= 3.0: + for entity in world.query(DirectoryPosition, smooth.Speed): + del entity[smooth.Speed] + world[GameStarted] = GameStarted() + + +def __initialize_world(world: World): + """ + Initialise le monde de la scène. + """ + world[State] = State.MOVING + world[AttackTimer] = AttackTimer(0.0) + world[AttackSpeed] = AttackSpeed(5.0) + + world.create_entity( + Position(), + Order(0), + Animation("fade_desktop", __change_folders_speeds), + ) + + names = [ + "Classique", + "Menteur", + "Tricheur", + "Histoire", + "Je t'aime", + "Hello", + "Cheval", + "Defender", + "Dansons", + "Secrets", + "Edmond", + "Mon Amour", + "Melatonin", + "Films", + "Cinéma", + ] + + positions = [ + Position(40 + (7 * 180) + 48, 35 + (5 * 166) + 38), + Position(40 + (5 * 180) + 48, 35 + (5 * 166) + 38), + Position(40 + (4 * 180) + 48, 35 + (4 * 166) + 38), + Position(40 + (3 * 180) + 48, 35 + (5 * 166) + 38), + Position(40 + (1 * 180) + 48, 35 + (5 * 166) + 38), + Position(40 + (6 * 180) + 48, 35 + (2 * 166) + 38), + Position(40 + (5 * 180) + 48, 35 + (3 * 166) + 38), + Position(40 + (4 * 180) + 48, 35 + (2 * 166) + 38), + Position(40 + (2 * 180) + 48, 35 + (4 * 166) + 38), + Position(40 + (1 * 180) + 48, 35 + (2 * 166) + 38), + Position(40 + (7 * 180) + 48, 35 + (1 * 166) + 38), + Position(40 + (5 * 180) + 48, 35 + (1 * 166) + 38), + Position(40 + (3 * 180) + 48, 35 + (0 * 166) + 38), + Position(40 + (2 * 180) + 48, 35 + (1 * 166) + 38), + Position(40 + (0 * 180) + 48, 35 + (1 * 166) + 38), + ] + + for y in range(LINES): + for x in range(COLUMNS): + position = DirectoryPosition(x, y) + entity = world.create_entity( + positions.pop(), + smooth.Speed(0), + Order(1), + Centered(), + Texture("directory.png"), + position, + ) + + if x == 2 and y == 1: + entity[UserDirectory] = UserDirectory() + entity[Texture] = Texture("user_directory.png") + + world.create_entity( + Position(0, 0), + Order(1), + Centered(), + Text(names.pop()), + TextSize(0), + DirectoryName(entity), + ) + + +def __attacks(world: World): + """ + Déclenche les attaques de Edmond. + """ + if world[State] == State.GAME_OVER: + return + world[AttackTimer] = AttackTimer(world[AttackTimer] + world[Delta]) + timer = world[AttackTimer] + if timer >= world[AttackSpeed] and world[State] == State.MOVING: + world[State] = State.SEARCHING + for entity in world.query(AttackPoint): + position = entity[AttackPoint] + for directory_entity in world.query(DirectoryPosition): + if directory_entity[DirectoryPosition] == position: + if UserDirectory in directory_entity: + directory_entity[Animation] = Animation( + "search_directory_failed" + ) + world[State] = State.GAME_OVER + else: + directory_entity[Animation] = Animation("search_directory") + del entity[AttackPoint] + del entity[Position] + del entity[Order] + del entity[Centered] + del entity[Texture] + elif timer >= world[AttackSpeed] + 4.5 and world[State] == State.SEARCHING: + world[State] = State.MOVING + for _ in range(10): + position = AttackPoint( + random.randint(0, COLUMNS - 1), + random.randint(0, LINES - 1), + ) + world.create_entity( + position, + Position(position.screen_position()), + Order(50), + Centered(), + Texture("attack_point.png"), + ) + world[AttackTimer] = AttackTimer(0.0) + world[AttackSpeed] = AttackSpeed(world[AttackSpeed] * 0.9) + + +def __move_directories(world: World): + """ + Permet de déplacer les dossiers avec la souris. + """ + # Si on n'est pas dans le bon state on annule + if GameStarted not in world or world[State] == State.GAME_OVER: + return + + # On met à jour la séléction + mouse = world[Mouse] + for entity in world.query(Hovered, DirectoryPosition): + if Animation in entity: + continue + if mouse.is_button_pressed(1): + world[SelectedDirectory] = SelectedDirectory(entity, Vec2(mouse.position)) + break + + # Si un dossier est séléctionné + if SelectedDirectory in world: + selected_directory = world[SelectedDirectory] + selected_entity = selected_directory.entity + directory_position = selected_entity[DirectoryPosition] + + # Vérification du relachement de la souris + if not mouse.is_button(1): + del world[SelectedDirectory] + return + + # On calcule le déplacement de la souris + mouse_delta = mouse.position - selected_directory.position + + # On annule si il y a pas eu de déplacement significatif de la souris + if mouse_delta.length < 40: + return + + # Récupération du mouvement voulu + if abs(mouse_delta.x) >= abs(mouse_delta.y): + movement = (int(mouse_delta.x / abs(mouse_delta.x)), 0) + else: + movement = (0, int(mouse_delta.y / abs(mouse_delta.y))) + + # Récupération des mouvements possible du dossier + movements: list[tuple[int, int]] = [] + if directory_position.x != 0: + movements.append((-1, 0)) + if directory_position.x != COLUMNS - 1: + movements.append((1, 0)) + if directory_position.y != 0: + movements.append((0, -1)) + if directory_position.y != LINES - 1: + movements.append((0, 1)) + if len(movements) == 0: + return + + # Si le mouvement n'est pas possible, on annule + if movement not in movements: + return + + # Si l'entité est animé on annule + if Animation in selected_entity: + return + + # On trouve l'autre dossier + for entity in world.query(DirectoryPosition, without=(Animation,)): + if entity != selected_entity and entity[ + DirectoryPosition + ] == DirectoryPosition( + directory_position.x + movement[0], + directory_position.y + movement[1], + ): + other_directory = entity + break + else: + return + + # On actualise la position de l'autre dossier + other_directory[DirectoryPosition].x -= movement[0] + other_directory[DirectoryPosition].y -= movement[1] + + # On actualise la position du dossier + selected_entity[DirectoryPosition].x += movement[0] + selected_entity[DirectoryPosition].y += movement[1] + + # On joue un son + world.create_entity(Sound("slide.wav")) + + # On retire le dossier selectionné + del world[SelectedDirectory] + + +def __update_positions(world: World): + """ + Met à jour la position cible des dossiers. + """ + for entity in world.query(DirectoryPosition): + position = entity[DirectoryPosition] + entity[smooth.Target] = smooth.Target(position.screen_position()) + entity[Order] = Order(position.y + 1) + + +def __update_directory_names(world: World): + """ + Met à jour la position des noms des dossiers. + """ + for entity in world.query(DirectoryName): + directory_entity = entity[DirectoryName].entity + entity[Position] = Position(directory_entity[Position] + Vec2(0, 75)) + entity[Order] = directory_entity[Order] + + +SCENE = ( + Scene( + [__initialize_world], + [__attacks, __move_directories, __update_positions, __remove_folders_speeds], + [], + ) + + smooth.PLUGIN + + Scene( + [], + [__update_directory_names], + [], + ) +)