Ma question est:
Comment puis-je gérer les états de jeu dans mon système d'entités, sans recourir à la conservation d'une pile d'objets d'état de jeu?
Ainsi, la conception de mon système d'entités signifie que lorsqu'une entité doit s'enregistrer pour des événements d'entrée par exemple, le composant d'entrée appelle le système d'entrée et dit "enregistrer cette entité pour cette entrée". C'est très bien, mais si vous ajoutez à cela le concept d'états de jeu (par exemple un écran de pause), il devient difficile de déterminer si une entité est dans l'état actuel et doit recevoir l'entrée.
Je pourrais augmenter le composant / système d'entrée pour qu'il dise, "enregistrer cette entité pour cette entrée dans ces états de jeu", mais cela nécessite que chaque entité sache dans quels états elle va être utilisée, et cela peut ne pas être évident. De plus, conserver une liste des états du jeu par entrée enregistrée (et d'autres systèmes qui utilisent des rappels) ne semble pas trop efficace.
Une autre idée que j'ai eue est qu'il y aura une entité qui représente l'état du jeu, marquez-la comme étant désactivée, puis lors de la génération de l'événement d'entrée, vérifiez que l'entité n'est pas un descendant d'une entité d'état de jeu désactivée. Semble coûteux de déterminer le parent pour chaque rappel.
Une autre idée est que tous les systèmes stockent leurs données par rapport à l'état actuel, de cette façon lors de la génération de l'entrée, l'entité cible ne sera même pas candidate. Cependant, cela nuit vraiment à la possibilité d'autoriser la communication entre des entités dans des états différents (pas vraiment un problème pour les écrans de pause, mais pensez à la sélection des verrous dans Oblivion / Skyrim).
La seule autre idée que j'ai eue est que tous les composants gèrent les événements de changement d'état et communiquent avec leur système pertinent pour désactiver tout ce qu'ils ont enregistré et le réactiver lors du retour à cet état.
Les deuxièmes (marquer un objet comme désactivé) et les autres (demander à chaque composant de gérer les changements d'état) semblent être les meilleures de mes idées, mais aucune d'entre elles ne me semble particulièrement intéressante.
Quelqu'un d'autre a-t-il d'autres idées sur la façon de procéder?
modifier Bien que je parle d'entrée spécifiquement dans cette question, cela peut signifier tout système capable d'envoyer des messages / événements à des entités, comme des collisions, des événements de minuterie, etc.
la source
Réponses:
Ce qui est souvent utilisé est un intermédiaire
Intent System
qui résume l'entrée et garde une trace du contexte et des gamestates pertinents.Le système d'intention arrêtera de transmettre des entrées lorsque la simulation est interrompue par exemple. Il gère également le mappage entre les événements du contrôleur et les intentions (se déplacer dans la direction, courir, tirer, recharger ...).
De cette façon, vos autres composants ne dépendent pas de manettes / entrées spécifiques (BUTTON_A, BUTTON_B vs BUTTON_X, BUTTON_O ...) mais ils réagissent tous aux mêmes intentions (IntentRun, IntentReload ...).
Un autre avantage est que le système d'intention peut être conscient que des contrôleurs disponibles sont ajoutés / supprimés, car il peut envoyer des intentions à n'importe quel abonné même en dehors de la simulation, vous pouvez gérer des intentions comme
AddPlayer(controllerID)
.La quantité d'informations sur l'état du jeu que vous fournissez au système via des événements / messages ou directement dépend de vous. Mais le temps investi dans le système Intent en vaut généralement la peine.
Vous pouvez gérer les contextes d'intention qui généreront des intentions lorsqu'ils seront connectés au système.
Le contexte peut être hiérarchisé, c'est-à-dire:
De cette façon, vous pouvez ajouter et supprimer les contextes qui sont actuellement pertinents.
Et une chose à propos de l'ensemble des systèmes d'intention est qu'il doit s'exécuter pendant la pause de la simulation.
Une façon qui est souvent utilisée pour jouer / mettre en pause la simulation de jeu sans interrompre les mises à jour non liées à la simulation est d'utiliser un ensemble d'heures différent. ie
GenericSystem::onTime(Long time, Long deltaTime, Long simTime, Long simDeltaTime)
.Avec cette approche, votre moteur peut simplement bloquer les incréments sur le simTime du jeu qui à son tour bloquera les mises à jour sur les moteurs d'animation et de physique pertinents qui utilisent
simTime and simDeltaTime
tout en permettant des mises à jour continues de l'effet ressort de votre caméra s'il doit se déplacer même pendant la pause, l'animation de l'effet de chargement sur un panneau d'affichage virtuel dans le jeu pendant le téléchargement des données ...la source
Que diriez-vous de créer un système d'événement global, puis d'avoir un composant écouteur d'événement pour chaque entité? Après un événement "Game State Change", vous pouvez jouer avec les composants individuellement pour chaque entité particulière.
Disons que vous avez un composant d'entrée. Une fois que le composant écouteur d'événements a reçu l'événement de changement d'état du jeu, il modifie des valeurs très spécifiques pour ce composant d'entrée particulier, de sorte qu'il ne recevrait aucun appel d'entrée ou ne ferait aucun appel de mouvement ou de réponse au système ou à son propriétaire.
Cela fonctionne pour moi car la plupart de mes composants sont scriptés (via Lua). C'est-à-dire que j'ai un composant d'entrée, qui est déclenché une fois lorsqu'une touche est enfoncée et il se déclenche d'un mouvement + direction, puis il est déclenché lorsque la touche est relâchée et il se déclenche d'un arrêt + direction. Il existe également un composant écouteur d'événements qui contacte le composant d'entrée (si le jeu est en pause) pour arrêter le déclenchement de toute fonction et l'arrêter si nécessaire. Je pourrais facilement ensuite ajouter une autre entité avec une réaction différente aux mêmes événements et pressions de touches en utilisant un autre script. De cette façon, vous enregistrez l'interaction entre différentes entités dans différents états et la rendez même beaucoup plus personnalisable. De plus, certaines entités peuvent même ne pas avoir le composant écouteur d'événements en eux.
Ce que je viens d'expliquer est essentiellement un exemple pratique de votre quatrième solution.
la source