Je pensais donc à la monolithicité de mes cours la plupart du temps. Par exemple, dans la méthode de la Character
classe Jump
, on peut avoir une référence à un objet d'effet sonore et le jouer. En soi, c'est bien, mais quand la physique, l'animation, les collisions, etc. sont prises en compte, la méthode Jump devient énorme et la Character
classe a beaucoup de dépendances avec beaucoup de choses différentes. Pourtant, cela peut être bien. Cependant, que se passe-t-il si nous ne voulons plus qu'un son soit joué lorsque le personnage saute? Maintenant, nous devons trouver cette ligne de code spécifique dans le désordre du Jump
code et le commenter ou quoi que ce soit.
Alors .. je pensais ..
Et si, à la place, il y avait une sorte de AudioSystem
classe et tout ce qu'elle faisait était de s'abonner à des événements aléatoires qui l'intéressaient dans d'autres classes. Par exemple, la Character
classe peut avoir un Jumped
événement (statique aussi, je suppose) qui est déclenché dans la Character
classe dans la méthode. Ensuite, la Character
classe ne saurait rien du petit effet sonore qui est joué lorsque le personnage saute. Ce AudioSystem
serait juste une énorme classe dans laquelle le programmeur pourrait se retirer pour connecter des effets sonores à certains événements qui se produisent dans le jeu grâce à l'utilisation d'événements statiques. Ensuite, si elle devenait trop grand , il pourrait être séparé en sous - classes comme EffectsAudioSystem
, BackgroundAudioSystem
, AmbientAudioSystem
et ainsi de suite.
Ensuite, dans les options du jeu, on pourrait avoir une case à cocher pour activer ou désactiver ces sortes de sons et tout ce qui devrait être fait est simplement de désactiver ce système avec un drapeau booléen simple et unique. Cette idée de systèmes pourrait également être étendue à des choses comme la physique, les animations, etc. au point où la plupart des réponses de jeu résultant des actions des joueurs sont connectées à travers ces systèmes élaborés et découplés.
D'accord, donc ma question peut être un peu vague, mais comment ce genre de chose sonne-t-il? Je n'ai jamais vraiment entendu parler de ce genre de système. Tout cela est dans ma tête en ce moment sans aucun codage fait jusqu'à présent, donc c'est peut-être une de ces transactions "bonnes en théorie mais pas en pratique". Ce type de système fonctionnerait-il avec un jeu plus grand ou finirait-il par tomber en panne et devenir encore plus un gâchis de spaghetti que le système d'origine?
la source
Réponses:
Les messages sont un enfer à déboguer et à maintenir. Cela semble bon en théorie, mais une fois mis en pratique, cela devient compliqué avec beaucoup de données en double envoyées. L'effet de son de saut nécessitera beaucoup plus de données à la fin, par exemple la position, la vitesse, le matériau sur lequel le personnage est, vous le nommez, la liste sera longue à la fin.
Donc, soit vous devrez collecter ces données et les envoyer à l'AudioManager via un événement / message très spécifique avec les données copiées, soit vous enverrez une référence au personnage du message, afin que l'AudioManager puisse accéder aux données, à la fois les façons finissent en désordre, et maintenant le gestionnaire audio doit choisir un son pour le matériau underground, etc.
Donc, à la fin, l'événement spécifique (qui est une classe très spécifique uniquement pour ce message) couplera à nouveau ces classes très profondément. Pas beaucoup gagné et à la fin, vous aurez une grande liste désordonnée d'événements / classes très spécifiques qui ne servent qu'à envoyer des données, qui existent déjà, et peuvent être obsolètes et souffriront de tous les autres problèmes de données dupliquées .
Il y aura donc une énorme liste de classes inutiles à maintenir qui introduisent un couplage profond entre le personnage et l'AudioManager, sauf que maintenant il est dispersé partout dans le code source. Pas seulement dans les classes Character- et AudioManager.
C'est toujours une bonne idée de découpler votre code, mais les messages ne sont vraiment qu'une autre façon de couplages profonds. Il suffit de coupler du code, d'utiliser le moyen le plus direct pour les coupler, ne pas trop ingénier.
la source
Je ne pense pas qu'un système de transmission de messages soit du tout sur l'ingénierie. En fait, cela peut faciliter considérablement la réalisation des tâches pendant la phase de polissage. Tu le fais bien!
Ce que vous avez décrit est exactement ce que j'ai jeté ensemble pour notre jeu Global Game Jam l'année dernière. J'étais responsable de la création et de l'édition du SFX, et de l'intégration de la musique que moi-même et un autre compositeur avons écrite dans le jeu d'une manière qui ne craignait pas.
Ce qui est génial avec cette approche d'un point de vue audio, c'est qu'elle vous permet de faire beaucoup plus de choses intéressantes avec votre son. Si vous pensez qu'un effet sonore dans un jeu est simplement un fichier son, un volume et un panoramique, vous vous trompez.
Exemple
Pour notre jeu, vous étiez un dinosaure pilotant un vaisseau spatial courant sur des planètes pour marquer des points. Nous travaillions dans Flash, donc une infrastructure basée sur les données n'était pas nécessaire. L'AudioManager était une classe composée d'un tas de méthodes statiques dont le seul but était de contrôler ce qui se passait en réponse à un événement de jeu.
Si je devais l'écrire en C ++, il aurait fallu un peu plus de temps pour résumer tous les comportements possibles des sons. Les exigences pour un message informant le système qu'une action a eu lieu ne seraient pas trop compliquées. Il aurait juste besoin du type de message, de l'objet d'origine ou de l'objet affecté, de l'accès à une sorte de contexte d'état du jeu, et pas grand-chose d'autre. Le protocole pourrait évoluer en fonction des besoins du jeu. Naturellement, si vous faites tout cela en implémentation dans du code (comme notre code GGJ de mauvaise qualité), vous avez un problème de classe monolithique pire. Mais cela est facilement atténué en créant un système basé sur les données.
Quoi qu'il en soit, voici comment notre système audio de jeu a réagi à divers messages:
Le joueur entre en collision avec la planète: Cela déclencherait un bruit d'explosion de la planète, assez basique. puis immédiatement après, il interrogerait le compteur combo en cours d'exécution. S'il était suffisamment élevé, il programmerait un effet sonore à jouer une demi-seconde environ plus tard du dinosaure faisant un rugissement de victoire. Également en arrière-plan, une valeur aléatoire de la population de la planète a été calculée (quelque chose comme 600 à 3000 - je n'ai aucune idée de la raison pour laquelle cette plage a été choisie, c'était une mécanique de gameplay abandonnée et toujours à utiliser pour rendre l'audio intéressant), et donc je l'ai utilisé pour mettre à l'échelle le volume du son lointain des cris (les citoyens planétaires rencontrant un destin inopportun).
Le joueur tient la barre d'espace pour l'accélération: À la réception de ce petit bruit de propulseur "whoosh" a été joué, mais aussi simultanément un rugissement du moteur en boucle basse a augmenté en plus de 1,5 secondes. Le système de particules a également utilisé cela pour tirer un émetteur IIRC
Le joueur lâche la barre d'espace pour la décélération: Maintenant que le joueur a lâché la barre d'espace, le système audio savait qu'il devait ralentir la boucle du moteur. Si j'avais plus de temps, j'aurais aimé superposer un autre son dessus qui était une sorte de pleurnicher type de son.
Le joueur entre en collision avec une mine spatiale maléfique: les mines spatiales sont mauvaises, donc non seulement il y a un bruit d'impact métallique combiné à une explosion (qui est juste cuit en un seul son), mais il y a aussi un son de consternation de dinosaure sélectionné au hasard qui joue. Il est plus probable de choisir des sons plus «pleurants» à mesure que la santé du joueur diminue.
Un jeu déjà amusant devient un plaisir à jouer lorsque sa bande-son est active et dynamique, même avec peu de comportements simples comme je l'ai décrit ci-dessus. Oui, il y a une logistique à régler pour s'assurer que les données correctes sont transmises. Mais bon, BFD. Ce sera loin d'être la chose la plus compliquée à écrire dans le cadre plus large du code du jeu.
En fait, FMOD et Wwise fonctionnent comme ça. Ils n'ont pas de répartiteur de messages central, mais vous postez efficacement les événements sur leurs systèmes centraux et ils réagissent en jouant un effet sonore qui a été pré-conçu par un implémenteur audio dans un outil de création. Pensez-y comme donner à votre jeu un DJ en direct. Il s'assoit et regarde ce qui se passe, et déclenche des extraits sonores au bon moment pour garder les choses intéressantes, les mixant pour qu'elles s'intègrent bien dans l'environnement audio préexistant.
[EDIT] De plus, je vois que vous avez tagué ce C #. S'agit-il de XNA, et si oui, utilisez-vous XACT? Si vous utilisez XNA, vous devez utiliser XACT.
la source
EventManager->dispatch("Sound:PlayerJump")
etsoundSystem->playFMODEvent("/MyGame/Player/Jump")
.Je suis d'accord avec Maik Semder, qu'un système de transmission de messages peut être une ingénierie excessive (pour l'instant de toute façon).
D'après ce que je comprends, votre classe ressemble actuellement à la "classe monolithique" de Bjorn, comme on peut le voir dans "Une classe monolithique" ici .
Je vous suggère de lire cet article et, même si un système complet de composants serait excessif pour l'instant, si vous lisez "Répartir le reste", cela devrait vous donner un bon moyen d'abstraire vos comportements et éventuellement de passer à un système plus complexe. Solution. Cela vous donnera une bonne base pour commencer de toute façon.
la source