Je commence mon premier projet de jeu «approprié» et j'ai inévitablement heurté un bloc en essayant de décider comment les composants du jeu dans XNA devraient communiquer.
À partir des événements de programmation GUI (Java) précédents, les gestionnaires et les écouteurs semblaient être la voie à suivre. J'aurais donc une sorte de bus d'événements qui accepte les inscriptions d'événements et les classes abonnées à ces événements, avec des gestionnaires pour les gérer. Par exemple (pseudocode):
class SpriteManager
Update(){
if(player.collidesWith(enemy)
// create new 'PlayerCollisionEvent'
}
class HUDManager
onPlayerCollisionEvent(){
// Update the HUD (reduce lives etc)
}
Cependant, je ne suis pas sûr de la configuration du code (en C #) qui serait nécessaire pour accomplir pleinement cela. Qu'est-ce qui garde la trace des événements (une sorte de bus?), Et comment est-il structuré?
Il semble également y avoir beaucoup de choses sur les services de jeu, où vous pouvez enregistrer un GameComponent dans votre classe Game.cs principale, puis le récupérer de n'importe où dans votre code qui a une référence à l'objet principal `` Game ''. J'ai essayé cela avec mon objet SpriteBatch et cela semble très facile .. cependant, je ne vois pas que cela soit aussi flexible qu'un modèle d'événement.
Prenez par exemple quand un ennemi meurt. Nous voulons mettre à jour le score du match. En utilisant les services, je peux obtenir une référence à mon objet StateManager créé dans Game1 et ajouté en tant que service, puis définir «score» sur la nouvelle valeur. J'aurais pensé qu'un événement `` onEnemyDeath '', qui peut être géré différemment par une multitude de classes, mais initié par 1 ligne de code dans la section `` détection de mort ennemie '', serait mieux que de lancer individuellement chaque GameComponent requis puis d'appeler ce que des méthodes sont nécessaires.
Ou ces stratégies sont-elles inférieures à autre chose?
Je me rends compte que c'est en partie ma mauvaise connaissance de C # autant que les paradigmes de communication de jeu, mais j'aimerais vraiment bien comprendre cette chose fondamentale.
Mise à jour
Ayant examiné les services est plus détaillé, je suis moins convaincu - il s'agit essentiellement de passer une variable globale (d'après ce que je comprends).
Mise à jour 2
Après avoir regardé ce didacticiel de base sur la gestion des événements et le test de l'exemple de code, il semble que les événements seraient un choix logique pour ce dont je discute. Mais je ne peux pas en utiliser beaucoup dans les échantillons que j'ai vus. Y a-t-il une raison évidente pour laquelle on ne devrait pas?
la source
Réponses:
La raison pour laquelle vous ne trouverez pas grand-chose sur les bus d'événements en C # est parce que je ne pense pas que quiconque en dehors de Java appelle une telle chose un «bus», selon mon expérience. Les termes les plus courants peuvent être file d'attente de messages, gestionnaire d'événements, signaux / emplacements, publication / abonnement, etc.
Vous n'avez besoin d'aucun de ceux-ci pour faire un jeu fonctionnel, mais si c'est le type de système avec lequel vous êtes à l'aise, il vous sera également utile ici. Malheureusement, personne ne peut vous dire exactement comment en faire un car tout le monde les roule un peu différemment, s’ils les utilisent même du tout. (Je ne le fais pas, par exemple.) Vous pouvez commencer avec un simple
System.Collections.Generic.List<Event>
pour la file d'attente, avec vos différents événements étant des sous-classes d'Evénement, et une liste d'abonnés pour chaque type d'événement. Pour chaque événement de la file d'attente, obtenez la liste des abonnés et pour chaque abonné, appelez-handle(this_event)
le. Retirez-le ensuite de la file d'attente. Répéter.Ce n'est probablement pas aussi flexible, mais c'est plus facile à déboguer. Les événements et les messages sont délicats car ils dissocient la fonction appelante de la fonction appelée, ce qui signifie que vos piles d'appels ne sont pas très utiles lors du débogage, les actions intermédiaires peuvent provoquer la rupture de quelque chose qui fonctionne normalement, les choses peuvent échouer silencieusement lorsqu'elles ne sont pas correctement connectées , etc. La méthode explicite de «saisir un composant et appeler ce dont vous avez besoin» fonctionne bien quand il s'agit de détecter les erreurs tôt et d'avoir un code clair et explicite. Cela a tendance à conduire à un code étroitement couplé et à de nombreuses dépendances complexes.
C # est à peu près un langage identique à Java. Tout ce que vous avez fait en Java peut être fait en C #, juste avec une syntaxe différente. Si vous avez du mal à traduire un concept, c'est probablement parce que vous ne connaissez que son nom spécifique à Java.
la source
Avez-vous essayé d'utiliser simplement des événements statiques simples? Par exemple, si vous vouliez que votre classe de score sache quand un ennemi est mort, vous feriez quelque chose comme ceci:
Score.cs
EnemySpaceship.cs
SpaceshipDeathEventArgs.cs
la source
Si vous vous sentez mal à l'aise avec l'approche basée sur les événements, essayez Artemis C #, c'est un framework Entity System basé sur http://t-machine.org/index.php/2007/09/03/entity-systems-are -le-futur-du-développement-mmog-partie-1 /
Source: https://github.com/thelinuxlich/artemis_CSharp Exemple de jeu: https://github.com/thelinuxlich/starwarrior_CSharp
la source
essayez d'utiliser l'agrégateur d'événements comme celui-ci
la source