Je me suis frayé un chemin avec les bases d'un moteur de jeu Java et j'ai atteint le point où je suis prêt à ajouter un système de gestionnaire d'événements.
Je sais, en théorie , ce qu'un gestionnaire d'événements devrait faire: permettre aux objets de "s'inscrire" pour certains événements, et chaque fois que le gestionnaire d'événements est informé d'un événement, diffuser l'événement aux auditeurs "enregistrés". Ce que je suis perplexe, c'est comment commencer à le mettre en œuvre.
Je n'ai pas pu trouver quoi que ce soit, en ligne, sur la mise en œuvre d'un système d'événements à partir de zéro, donc je cherche des informations sur les meilleures pratiques dans ce cas - ce que je dois et ne dois pas faire.
Par exemple, est-il vraiment nécessaire que chacun de mes objets de jeu ait un EventManager
champ? Étant donné que tous mes objets de jeu héritent d'une seule classe parent abstraite, je pense que je devrais pouvoir utiliser une référence statique afin qu'il n'y ait qu'une seule instance du gestionnaire d'événements, partagée entre tous les objets de jeu. Je fais quelque chose de similaire, avec l'applet, que j'utilise pour rendre chaque objet, déjà.
Je suppose que je devrais maintenir une collection quelconque pour chaque événement souscrit possible - ajouter et supprimer des objets de jeu de la liste, au besoin. Je pense qu'il devrait être possible de faire une file d'attente d'événements qui doivent être diffusés, auquel cas je pourrais simplement ajouter "EventManager.Update ()" à la boucle de jeu principale, et avoir la Update()
méthode pour diffuser les événements qui se sont produits à la fin de chaque image. Enfin, chaque objet aurait une HandleEvent(Event e)
méthode, qu'ils pourraient ensuite analyser et répondre de manière appropriée.
Cela ressemble-t-il à la direction appropriée vers la mise en œuvre d'un tel système, ou suis-je loin de la voie et / ou manque quelque chose de tout à fait évident?
Réponses:
Cela peut être aussi simple que vous le souhaitez.
N'essayez pas de déterminer ce que devrait faire un gestionnaire d'événements - déterminez ce dont vous avez besoin. Le reste devrait suivre à partir de là, ou au moins, devrait suggérer des questions plus spécifiques.
la source
Les trois méthodes essentielles dont un système d'événements a besoin sont une méthode addListener (), une méthode removeListener () et une méthode pour dispatchEvent (). C'est-à-dire, une méthode utilisée par les objets pour s'inscrire à un événement, une méthode utilisée pour se désinscrire et une méthode pour diffuser réellement un événement à tous les écouteurs. Tout le reste est de la sauce.
Comme vous le constatez, vous aurez certainement besoin d'une sorte de structure de données pour garder une trace des auditeurs enregistrés. L'approche la plus simple serait un tableau associatif (dictionnaire ou objet en JavaScript) qui associe un vecteur (ou simplement un tableau selon la langue) à un événement. Ce vecteur est une liste de tous les auditeurs enregistrés; ajoutez des écouteurs à la liste ou supprimez-les dans les méthodes add / removeListener ().
Pour diffuser un événement dans dispatchEvent (), cela peut être aussi simple que de parcourir le vecteur. Vous pouvez ajouter plus de complexité à la répartition en triant la priorité des événements ou autre chose, mais ne vous en faites pas tant que vous n'en avez pas besoin. Dans de nombreux cas, vous n'en aurez pas besoin.
Il y a une petite nuance à dispatchEvent () lorsque vous considérez les données à transmettre avec l'événement. Au niveau le plus élémentaire, vous pourriez ne pas transmettre de données supplémentaires; tout ce que l'auditeur doit savoir, c'est qu'un événement s'est produit. Cependant, la plupart des événements ont des données supplémentaires qui les accompagnent (par exemple, où l'événement s'est produit). Vous voudrez donc que dispatchEvent () accepte et transmette certains paramètres.
Il existe de nombreuses façons de donner à tous vos objets de jeu une référence à la classe EventManager. Une référence statique est certainement un moyen; un autre est avec un Singleton. Cependant, ces deux approches sont assez rigides, donc la plupart des gens ici recommandent un localisateur de services ou une injection de dépendance. J'ai fait l'injection de dépendance; cela signifie un champ EventManager distinct pour chaque objet, ce que vous semblez vouloir éviter, mais je ne sais pas pourquoi c'est un problème. Ce n'est pas comme s'il y avait beaucoup de frais généraux liés au stockage d'un tas de pointeurs.
la source
Les bases de la gestion des événements sont assez simples.
Sachant cela (mais ne sachant pas comment l'implémenter en Java), il est facile de comprendre que vous avez besoin de certains gestionnaires (fonctions pour gérer les événements) et de les ajouter à un tableau (avec des pointeurs, en C) associé à un nom d'événement. Une fois que vous avez déclenché un événement, vous stockez le nom de l'événement déclenché et ses arguments dans une pile, c'est ce qu'on appelle le pool d'événements.
Ensuite, vous avez un résumé d'événement (une boucle simple), qui affiche le premier événement de cette pile, essaie de trouver un gestionnaire pour celui-ci, et s'il y en a un, l'exécute avec les paramètres.
Bien sûr, ce résumé d'événement peut être déclenché quand vous le souhaitez, par exemple une fois par image après avoir appelé votre
Update()
fonction.la source
Pour le champ EventManager, utilisez une variable statique. Un Singleton pour EventManager serait également une excellente idée.
Votre approche semble bonne, mais n'oubliez pas de la rendre thread-safe.
Il est bon d'exécuter des IO-Events avant ou après les "GameEvent", donc dans un cadre chaque "GameEvent" traite les mêmes données.
la source