Le titre est un peu déroutant, mais je n'ai pas pensé à expliquer ma question en une courte phrase. Voici donc:
Chaque fois que j'écris des moteurs de jeu, qu'ils soient basés sur la physique / les tuiles, etc., j'arrive toujours au point où je ne sais pas comment je dois gérer les choses. Les entités dans le monde devraient-elles se débrouiller seules, ou un système mondial devrait-il les gérer?
Voici un exemple simple: déplacer des objets. Si chaque objet voit le monde autour de lui (vérifiez les collisions) et se déplace en fonction de cela.
[Remarque, il s'agit d'un jeu basé sur des tuiles où l'objet se déplace par tuile, donc je n'utilise pas la physique pour passer d'une tuile à une autre]
public class Actor : GameObject
{
private void MoveTo(Vector2 location)
{
if (world.getTile(location) != solid && world.objAtTile(location) == null)
{
Tweener.addTween(this, location);
}
}
}
Ou le mouvement de chaque objet doit-il être manipulé dans le monde, où le monde vérifie tout?
public class Actor : GameObject
{
private void MoveTo(Vector2 location)
{
world.moveTo(location);
}
}
public class World
{
public void moveObject(GameObject obj, Vector2 location)
{
//called from object
if (getTile(location) != solid && objAtTile(location) == null)
{
Tweener.addTween(obj, location);
}
}
}
Cela n'a pas vraiment d'importance pour cet exemple, je suppose, mais je peux me voir avoir des ennuis plus tard. Merci d'avance.
la source
Actor
savoirworld
du tout?Réponses:
Je vois que vos exemples sont en Java, mais vos balises ne spécifient aucune langue. En C ++, la réponse n'est ni l'un ni l'autre - vous ne devriez pas utiliser de fonction membre pour cela!
la source
Il n'y a pas de réponse simple.
Comme avec la plupart des choses dans la programmation, c'est un compromis. Donner plus de puissance aux objets individuels les rend plus grands - et donc plus lents - mais rend le moteur plus facile à comprendre et à étendre. Avoir une méga-classe qui peut tout gérer ensemble pourrait être plus rapide, mais au prix d'avoir une méga-classe; c'est-à-dire qu'il est généralement considéré comme une mauvaise forme de créer des classes supermassives.
J'ai lu quelques articles sur la conception pilotée par les composants et les données, où vous avez une seule classe qui représente tous les objets d'un certain type, stockant leurs données dans des listes et ne faisant circuler que les index pour obtenir les propriétés d'un objet individuel. Bien que je puisse voir cela comme un type d'architecture viable, je le sens plutôt vis à vis du point entier d'orientation de l'objet, qui a également obtenu sa juste part de critiques.
Je recommande personnellement de donner plus de puissance aux objets. Cela a plus de sens dans un langage orienté objet et (j'imagine) plus facile à comprendre et à maintenir au fil du temps.
la source
Je mets à jour ma réponse parce que beaucoup de choses n'étaient pas claires avant les commentaires. Veuillez me dévoiler pendant que j'explique mes pensées.
En général, deux aspects clés à considérer dans toute conception sont la cohésion et le couplage . Nous savons tous que nous avons besoin d'une forte cohésion et d'un faible couplage pour pouvoir réaliser une conception plus réutilisable et extensible.
Donc, si le monde doit tout gérer, cela signifie qu'il a une faible cohésion et un couplage étroit (car il doit tout savoir et tout faire). Cependant, c'est également le cas lorsqu'une entité de jeu doit tout faire. Mettre à jour son emplacement, rendre sa texture, etc. etc.
Ce qui vous intéresse vraiment, c'est de créer des systèmes qui se concentrent sur un aspect de l'entité. Par exemple, une entité de jeu pourrait avoir une texture, mais un rendu serait responsable de rendre cette texture à l'écran. Le Renderer ne se soucie pas des autres propriétés de l'entité.
En allant un peu plus loin, une entité de jeu est simplement un sac de propriétés. Ces propriétés sont manipulées par des systèmes qui se concentrent sur des propriétés spécifiques. Et c'est là qu'interviennent les systèmes d'entités basés sur les composants (CBES), où propriétés = composants.
Plus précisément, CBES avec des systèmes (ou sous- systèmes ). Cette conception a tendance à avoir quelques systèmes qui se concentrent sur des composants spécifiques d'une entité sans se soucier des autres composants de l'entité. De plus, les systèmes sont couplés uniquement avec les informations dont ils ont besoin pour traiter ces composants.
Prenons votre exemple. Étant donné que l'entrée de l'endroit où déplacer l'entité est basée sur le contrôleur du joueur, vous auriez probablement un PlayerControllerSystem. Ce système contrôlerait, à part bien d'autres choses, le composant de position de l'entité. Dans ce cas, le PlayerControllerSystem aurait besoin de connaître le Level et le PositionComponent. Si plus tard vous décidez d'ajouter la détection de collision, vous créeriez un CollisionSystem qui utiliserait à nouveau la position des entités, mais cette fois pour calculer les boîtes englobantes (ou vous pourriez avoir un BoundingBoxComponent, votre appel). Le fait est que vous pouvez facilement activer ou désactiver le comportement (même à la volée) en ajoutant / supprimant simplement des composants. Ainsi, plus de comportement signifie que plus de systèmes manipulent les composants d'une entité, mais ils sont tous dans une classe bien définie avec un faible couplage. Vous voulez des scripts? Ajoutez un composant ScriptComponent. BAM! Vous venez d'ajouter des capacités de script avec 2 classes. La physique? Du son? Encore le même.
Donc, la raison pour laquelle je préconise CBES avec les sous-systèmes est qu'il est parfaitement OO et un système global facilement maintenable / extensible. L'ajout d'un comportement à une entité est aussi simple que de décider quelles données ce comportement a besoin et quelles entités en ont besoin.
Pour plus d'informations sur les systèmes d'entités basés sur des composants avec des sous-systèmes, il existe une excellente série de billets de blog par T = Machine chez Entity Systems qui sont l'avenir du développement MMOG . L'auteur est même allé jusqu'à créer un wiki pour collecter diverses implémentations nommé Entity Systems Project
Un poste général (et bien connu) sur les systèmes d'entités basés sur les composants en général est Evolve your hierarchy qui a créé le système pour Tony Hawk Pro.
Enfin, si vous cherchez une bibliothèque avec un exemple de code, n'allez pas plus loin que la bibliothèque Artemis . Artemis est principalement en Java mais voici un port en C # (que j'utilise actuellement dans mon projet XNA).
la source
Je vais généralement avec un design où les objets se gèrent eux-mêmes (c'est à cela que servent les méthodes, après tout) mais le monde de base a des listes de tous les objets et il utilise ces listes pour les coordonner. Donc quelque chose comme:
la source
Gardez-le au sec, timide et dites à l'autre gars.
Il vaut mieux demander au monde de déplacer votre acteur que de demander au monde si vous pouvez vous déplacer où vous voulez aller. De cette façon, vous pouvez changer facilement l'algorithme de recherche de chemin dans la classe mondiale et autres. Bien sûr, vous pouvez simplement laisser cela à une classe de base pour l'acteur, mais c'est la direction que je prendrais et la raison.
la source
EDIT: Réécrit en raison de commentaires indiquant que je n'avais pas tracé la ligne assez clairement pour cette réponse à la question d'origine.
J'aimerais clarifier un peu plus la question si possible. La logique qui agit sur un objet doit-elle être interne ou externe à cet objet? La dernière partie de l'article mentionne spécifiquement la longévité du design comme base pour poser la question, afin d'éviter des problèmes plus tard.
Ma réponse simple de haut niveau est de garder toute la logique qui agit sur un objet dans cet objet.
Vous n'avez pas besoin du monde pour déplacer un objet, tout ce dont vous avez besoin est de l'objet à déplacer et du vecteur représentant l'emplacement pour y accéder. Le monde peut entrer en jeu lorsqu'une destination est choisie ou lorsqu'une réaction à l'environnement est requise en raison d'une collision, mais celles-ci sont en dehors de l'exemple donné pour travailler.
Pour répondre à la partie sous-jacente de la question et atteindre la longévité de la conception, je suggère une architecture orientée composants. Les architectures de composants décomposent un objet en ensembles discrets de données et de fonctionnalités (en supposant que vous allez avec ma réponse ci-dessus qui indique de garder la logique avec les données). Si votre structure ressemble à CEntity-> CHuman-> CSoldier-> CPlayerCharacter, vous rencontrerez invariablement des problèmes où vous devrez modifier une logique et en fonction de son emplacement dans cet arbre (combien d'autres types d'humains y a-t-il par exemple?) il peut avoir des effets de balayage sur plusieurs types d'objets.
Un système de composants aurait à la place un ensemble d'interfaces qui définissent ce que l'objet CEntity est composé comme ICompRenderable, ICompMoveable, ICompHealth, ICompInventory et ainsi de suite. Où vous auriez CCompMoveableHuman et éventuellement un CCompMoveableSoldier et CCompMoveablePlayer pour garder leurs modèles de mouvement individuels séparés. Disons que le soldat est modifié pour fonctionner en formations. Cette modification n'affectera que les entités créées à l'aide de ce composant.
Donc, pour résumer, je vous suggère de contenir la logique avec les données auxquelles la logique s'applique. Je recommande également de diviser les objets en composants discrets pour réduire le "Où dois-je mettre cela?" questions et assurer la stabilité dans l'avenir avec la facilité de maintenance et son extensible.
J'espère que cela t'aides.
la source
Je vous recommande d'essayer de lire sur les architectures basées sur les composants. Il y a pas mal de billets de blog, de présentations et d'écrits à leur sujet qui peuvent faire un meilleur travail que jamais.
AltDevBlogADay a pas mal de messages à ce sujet, un très bon étant cette série sur les entités de jeu: http://altdevblogaday.com/2011/07/10/the-game-entity-–-part-ia-retrospect/ Il y a plusieurs parties qui se concentrent sur le problème que vous essayez de résoudre.
la source