|
JustAnotherDnDGame 0.1.0
Jeu de rôle tactique au d20, vue de dessus, en C++/Qt
|
Cette page explique comment le jeu produit du son : le socle de lecture (hmi::AudioEngine), le catalogue qui associe un nom d'événement à un fichier (hmi::SoundCatalog), la détection des transitions qui déclenchent un son (hmi::GameEvents) et la table qui les relie (hmi::SoundTriggers). Ajouté en LOT-60, après le durcissement (LOT-58) et la boucle de jeu complète (LOT-59, Écrans, navigation et boucle de jeu) dont les écrans de pause et de fin de niveau donnent enfin un moment où un son de victoire ou de navigation peut exister.
Core expose des transitions d'état ; c'est HMI qui décide qu'une transition fait du bruit. Exactement la même séparation que pour le rendu (Rendu 2D : de l'ECS à l'écran, hmi::MechanismVisuals) — et pour la même raison : la simulation reste pure, déterministe et testable sans périphérique audio (EX-NFR-010, EX-ARCH-012). Aucun fichier de Core/ n'inclut Qt, ni ne sait qu'un son existe.
Source/HMI/Audio/AudioEngine.h enveloppe QSoundEffect (Qt Multimedia), le composant Qt conçu précisément pour des échantillons courts à faible latence — le cas d'usage exact d'un bruitage de saut, par opposition à QMediaPlayer (pensé pour la musique, latence et coût plus élevés).
Source/HMI/Audio/SoundCatalog.h résout un identifiant d'événement ("saut", "atterrissage"…) vers un nom de fichier relatif à Source/Elements/Audio/, lu depuis sounds.json. Le patron est identique à hmi::SkinCatalog (Rendu 2D : de l'ECS à l'écran, LOT-42) et hmi::AnimationCatalog (LOT-46) :
Le repli d'un événement sans entrée ou d'un fichier manquant est le silence, jamais un son de remplacement — contrairement au damier magenta d'une texture manquante (Rendu 2D : de l'ECS à l'écran), un bip de repli serait insupportable en jeu.
Source/HMI/Game/GameEvents.h détecte, une fois par pas de simulation fixe (jamais par image de rendu, EX-REN-021 — le piège que le LOT-33 a déjà traité pour les entrées, Entrées et actions logiques), les transitions qui produisent un événement (hmi::GameEvent) :
hmi::GameSession::lastStepEvents() (Écrans, navigation et boucle de jeu) expose les événements du dernier update() — capturés avant reload() : sur un échec, le rechargement remet aussitôt le personnage et les mécanismes à l'état d'entrée, et une implémentation naïve qui viderait la liste d'événements à cette occasion effacerait Died avant que l'appelant ne l'ait jamais vu (mort et rechargement se suivent dans le même pas).
Les événements d'interface (MenuNavigate, MenuConfirm, PauseOpened, SequenceCompleted…) partagent la même énumération mais ne sont pas détectés par diffusion d'état : les écrans du LOT-59 les exposent déjà comme des signaux Qt discrets (GameViewport::levelSucceeded, la navigation manette des menus) — MainWindow y joue le son associé directement, sans détection supplémentaire.
hmi::soundForEvent (Source/HMI/Audio/SoundTriggers.h) associe chaque hmi::GameEvent à un identifiant de hmi::SoundCatalog, en un switch exhaustif sans default : un événement ajouté sans entrée casse la compilation. Certains événements (WallContactEnter, BlockPushed, PauseOpened) résolvent délibérément vers std::nullopt — silence documenté, pas un oubli, faute de bruitage dédié dans ce lot.
Détection et association sont deux questions séparées (« qu'est-ce qui est arrivé » vs. « qu'est-ce que ça produit ») précisément pour qu'un futur système de particules (LOT-53, EX-REN-008) puisse brancher un effet visuel sur la même détection sans la dupliquer ni la modifier.
Qt6::Multimedia est un composant additionnel de Qt, pas une bibliothèque tierce : ajouté à find_package(Qt6 ... COMPONENTS Multimedia) dans Source/HMI/CMakeLists.txt, avec la même garde que Widgets/Gui (absent → cible JustAnotherDnDGame ignorée, configuration jamais cassée, EX-BUILD-010). Provisionné en CI via modules: qtmultimedia sur les six points install-qt-action (ci.yml, release.yml) ; en local, via le composant Multimedia de l'installateur Qt officiel ou aqtinstall -m qtmultimedia.
windeployqt (POST_BUILD) déploie Qt6Multimedia.dll et ses greffons (multimedia/) à côté de l'exécutable — vérifié explicitement en CI (job build-test-coverage), puisqu'un build local réussi ne prouve rien sur le zip publié.