diff --git a/assets/dialogs/failed.json b/assets/dialogs/failed.json new file mode 100644 index 0000000..a13dfa1 --- /dev/null +++ b/assets/dialogs/failed.json @@ -0,0 +1,6 @@ +[ + "Ah te voila !", + "Aller hop ! A la corbeille !", + "La cavale est finit !", + "On fais moins le malin sans son bouclier hein !" +] \ No newline at end of file diff --git a/assets/waiting.mp3 b/assets/waiting.mp3 new file mode 100644 index 0000000..f80c643 Binary files /dev/null and b/assets/waiting.mp3 differ diff --git a/src/plugins/assets.py b/src/plugins/assets.py index 188357d..e56176e 100644 --- a/src/plugins/assets.py +++ b/src/plugins/assets.py @@ -8,6 +8,7 @@ import pygame from engine import CurrentScene, GlobalPlugin, KeepAlive, Scene from engine.ecs import World from plugins import render +from plugins.sound import Sound class Assets(KeepAlive): @@ -25,6 +26,7 @@ class Assets(KeepAlive): # Chragement du son d'erreur self.__error_sound = pygame.mixer.Sound("assets/error.mp3") + self.__waiting_sound = pygame.mixer.Sound("assets/waiting.mp3") # Chargement des textures de chargement self.__unloaded_texture = pygame.image.load("assets/unloaded.png").convert() @@ -54,6 +56,13 @@ class Assets(KeepAlive): """ return self.__error_sound + @property + def waiting_sound(self) -> pygame.mixer.Sound: + """ + Le son de chargement. + """ + return self.__waiting_sound + @property def unloaded_texture(self) -> pygame.Surface: """ @@ -207,6 +216,7 @@ def loading_scene(target: Scene, name: str, clear_cache: bool = True): order=1000000001, area=(0, 0, 0, render.HEIGHT), ), + Sound(assets.waiting_sound, loop=True, fade_ms=10000), ) @staticmethod diff --git a/src/plugins/defaults.py b/src/plugins/defaults.py index 6865776..8545e55 100644 --- a/src/plugins/defaults.py +++ b/src/plugins/defaults.py @@ -10,6 +10,7 @@ from plugins import ( display, hover, inputs, + multisound, render, sound, text, @@ -25,6 +26,7 @@ PLUGIN = ( + hover.PLUGIN + click.PLUGIN + coroutine.PLUGIN + + multisound.PLUGIN + sound.PLUGIN + text.PLUGIN + animation.PLUGIN diff --git a/src/plugins/dialog.py b/src/plugins/dialog.py new file mode 100644 index 0000000..35aba36 --- /dev/null +++ b/src/plugins/dialog.py @@ -0,0 +1,42 @@ +""" +Un plugin permettant de gérer l'affichage et l'audio des dialogues. +""" + + +import json +import random +import threading + +import pygame +from engine.ecs import World +from engine.math import Vec2 +from plugins import render + +# from plugins.assets import Assets +from plugins.sound import Sound +from plugins.text import Text +import pyttsx3 + + +engine = pyttsx3.init() + + +def spawn_dialog(world: World, name: str, height: float = 900): + """ + Fait apparaitre un dialogue dans le monde. + """ + global engine + texts: list[str] = json.load( + open(f"assets/dialogs/{name}.json", "r", encoding="utf-8") + ) + text = random.choice(texts) + # engine.say(text) + engine.save_to_file(text, "voice.mp3") + engine.runAndWait() + world.new_entity().set( + Sound( + pygame.mixer.Sound("voice.mp3"), + callback=lambda world, entity: entity.destroy(), + ), + Text(text, position=Vec2(render.WIDTH / 2, height), origin=Vec2(0.5)), + ) diff --git a/src/plugins/multisound.py b/src/plugins/multisound.py new file mode 100644 index 0000000..f42e44b --- /dev/null +++ b/src/plugins/multisound.py @@ -0,0 +1,65 @@ +""" +Plugin pour les sons multiples. +""" + + +import random +from typing import Callable +from engine import GlobalPlugin + +from engine.ecs import Entity, World +from plugins.assets import Assets +from plugins.sound import Sound + + +class MultiSound: + """ + Composant qui quand il est ajouté a une entité, il joue un son aléatoire + parmis la liste de ses sons, il est ensuite retiré de l'entité. + + Ce composant est fait pour être définis en tant que constante + puis utilisé ensuite, pour cela il prend seulement le nom des + sons au lieu des sons eux memes. Les sons seront donc récupérés + a l'aide de `Assets`. + """ + + def __init__( + self, + *sound_names: str, + loop: bool = False, + volume: float = 1.0, + fade_ms: int = 0, + callback: Callable[[World, Entity], object] = lambda _w, _e: None, + ): + self.sound_names = sound_names + self.loop = loop + self.volume = volume + self.fade_ms = fade_ms + self.callback = callback + + +def __update_sounds(world: World): + """ + Met à jour les sons du jeu. + """ + # Ajout des sons aléatoires + assets = world[Assets] + for entity in world.query(MultiSound): + multi_sound = entity[MultiSound] + sound = assets.get_sound(random.choice(multi_sound.sound_names)) + entity[Sound] = Sound( + sound, + multi_sound.loop, + multi_sound.volume, + multi_sound.fade_ms, + multi_sound.callback, + ) + del entity[MultiSound] + + +PLUGIN = GlobalPlugin( + [], + [], + [__update_sounds], + [], +) diff --git a/src/plugins/sound.py b/src/plugins/sound.py index 6bc76b8..06597d7 100644 --- a/src/plugins/sound.py +++ b/src/plugins/sound.py @@ -3,12 +3,10 @@ Un plugin permettant de jouer des sons. """ -import random from typing import Callable import pygame from engine import GlobalPlugin, KeepAlive from engine.ecs import Entity, World -from plugins.assets import Assets class Channels(KeepAlive, dict[Entity, pygame.mixer.Channel]): @@ -37,32 +35,6 @@ class Sound: self.callback = callback -class MultiSound: - """ - Composant qui quand il est ajouté a une entité, il joue un son aléatoire - parmis la liste de ses sons, il est ensuite retiré de l'entité. - - Ce composant est fait pour être définis en tant que constante - puis utilisé ensuite, pour cela il prend seulement le nom des - sons au lieu des sons eux memes. Les sons seront donc récupérés - a l'aide de `Assets`. - """ - - def __init__( - self, - *sound_names: str, - loop: bool = False, - volume: float = 1.0, - fade_ms: int = 0, - callback: Callable[[World, Entity], object] = lambda _w, _e: None, - ): - self.sound_names = sound_names - self.loop = loop - self.volume = volume - self.fade_ms = fade_ms - self.callback = callback - - def __initialize(world: World): """ Ajoute les ressources utiles pour le plugin. @@ -74,20 +46,6 @@ def __update_sounds(world: World): """ Met à jour les sons du jeu. """ - # Ajout des sons aléatoires - assets = world[Assets] - for entity in world.query(MultiSound): - multi_sound = entity[MultiSound] - sound = assets.get_sound(random.choice(multi_sound.sound_names)) - entity[Sound] = Sound( - sound, - multi_sound.loop, - multi_sound.volume, - multi_sound.fade_ms, - multi_sound.callback, - ) - del entity[MultiSound] - # Ajout des sons non gérés channels = world[Channels] sound_entities = world.query(Sound) diff --git a/src/scenes/__init__.py b/src/scenes/__init__.py index 83db103..e3b14b0 100644 --- a/src/scenes/__init__.py +++ b/src/scenes/__init__.py @@ -2,7 +2,7 @@ Module contenant toutes les scènes du jeu. """ -from plugins.sound import MultiSound +from plugins.multisound import MultiSound CLICK_SOUND = MultiSound("click/0", "click/1", "click/2") diff --git a/src/scenes/menu.py b/src/scenes/menu.py index d3f6917..aa550c4 100644 --- a/src/scenes/menu.py +++ b/src/scenes/menu.py @@ -13,7 +13,7 @@ from plugins.assets import Assets from plugins.click import Clickable from plugins.hover import HoveredTexture from plugins.render import Sprite -from scenes.story import boss_fight +from scenes.story import boss_fight, directory_search def __create_button(world: World, assets: Assets, i: int, name: str): @@ -48,7 +48,7 @@ def __on_click_butons(world: World, _entity: Entity, name: str): case "tricheur": world[CurrentScene] = base_game.CHEATER case "histoire": - world[CurrentScene] = boss_fight.SCENE + world[CurrentScene] = directory_search.SCENE case _: pass diff --git a/src/scenes/story/directory_search.py b/src/scenes/story/directory_search.py index 14bb2dd..1fb58b8 100644 --- a/src/scenes/story/directory_search.py +++ b/src/scenes/story/directory_search.py @@ -6,7 +6,7 @@ import random from engine import CurrentScene, Scene from engine.ecs import Entity, World from engine.math import Vec2 -from plugins import assets as plugin_assets, render, smooth +from plugins import assets as plugin_assets, dialog, render, smooth from plugins.animation import Animation from plugins.coroutine import Coroutine, wait from plugins.click import Clickable, Clicked @@ -254,6 +254,7 @@ def __spawn_search_directory(world: World): ), ), ) + dialog.spawn_dialog(world, "failed") entity[Sprite].order = 5 for entity in world.query(Coroutine): # On arrete la boucle de jeu entity.destroy() diff --git a/voice.mp3 b/voice.mp3 new file mode 100644 index 0000000..4723f31 Binary files /dev/null and b/voice.mp3 differ