Mit C # und XNA 4 habe ich mich nach dem Lesen von Beiträgen wie diesem und jenem für ein auf Entitäten basierendes Design für mein Spiel entschieden , aber ich habe jetzt Schwierigkeiten, herauszufinden, wie Komponenten abgerufen werden können, sobald sie vorhanden sind zu einer Entität hinzugefügt.
Einige Artikel, die ich gelesen habe, besagen, dass beim Erstellen einer Komponente diese mithilfe eines Nachrichtensystems bei dem System registriert wird, das darauf reagiert. Ein Nachteil, den ich hier sehe, ist, dass wenn ein System 2 Komponenten benötigt, um zu handeln (z. B. CollideComponent und PositionComponent), dies kompliziert wird (und ich kann mir nicht vorstellen, wie es funktionieren würde).
Die andere Möglichkeit, die ich derzeit verfolge, besteht darin, ein System fragen zu lassen, ob eine Entität eine bestimmte Komponente hat, wenn sie diese benötigt. Allerdings habe ich keine Codebeispiele gesehen, nur die Theorie im Netz, also habe ich versucht, sie durcheinander zu bringen. Ein Code hier könnte erklären, wie weit ich gekommen bin:
Zuerst a System:
public class RenderingSystem : IGameSystem
{
public void PerformAction(IQueryable<IGameObject> gameObjects)
{
foreach (var gameObject in gameObjects)
{
RenderableGameComponent renderableGameComponent = gameObject.GetComponent<RenderableGameComponent>(ComponentType.Renderable);
if (renderableGameComponent != null)
{
this.spriteBatch.Draw(renderableGameComponent.Texture, renderableGameComponent.DrawablePosition, Color.White);
}
}
}
}
Nun das eigentliche GameObject:
public class GameObject : IGameObject
{
private List<IGameComponent> gameComponents;
private ComponentType componentTypes;
public void AddComponent(IGameComponent component)
{
this.gameComponents.Add(component);
this.componentTypes = this.componentTypes | component.ComponentType;
}
public T GetComponent<T>(ComponentType componentType)
{
return (T)this.gameComponents.FirstOrDefault(gc => gc.ComponentType == componentType);
}
}
Und schließlich die Componentund ComponentTypeAufzählung:
public class RenderableGameComponent : IGameComponent
{
public Texture2D Texture { get; set; }
public Vector2 DrawablePosition { get; set; }
public ComponentType ComponentType
{
get { return ComponentType.Renderable; }
}
}
[Flags]
public enum ComponentType
{
Renderable = 1,
Updateable = 2,
Position = 4,
}
Wie Sie vielleicht sehen können, versuche ich, bitweise Operationen für die ComponentTypeAufzählung zu verwenden, die jeder Componentvon ihnen GameObjecthat. Der Grund dafür ist, dass ich dachte, dies wäre ein viel saubererer Ansatz, wenn ich versuche, das Erforderliche Componentaus dem herauszuholen, GameObjectwenn ich von a gefragt werde System(siehe auch Link 1 oben).
Ich versuche, nicht an einem Typ vorbeizukommen und eine Iteration über alle Components von a durchzuführen GameObject. z.B:
foreach (var component in this.GameComponents)
{
if (component.GetType() == requestedType) { return component; }
}
Dies liegt daran, dass wenn ein paar hundert Kugeln auf dem Bildschirm angezeigt werden und eine CollidableSystemerstellt wird, das Spiel die Überprüfung aller Typen massiv verlangsamt. Ich habe Erfahrung damit, als ich ein vorheriges Spiel erstellt habe, aber zugegebenermaßen wurde ein vererbungsbasiertes Designsystem verwendet.
Es macht mir Sorgen, dass es für jedes Systemerstellte Element GameObjectjedes Mal durchlaufen muss, wenn jedes Mal dieselbe Frage gestellt wird: "Haben Sie die Komponente, nach der ich suche?" und immer noch viel Casting und Null-Checks.
Nun ist meine Frage dies. Ich möchte wissen, ob es ein De-facto-Entwurfsmuster gibt, um Components von GameObjects zu erhalten, für die keine Nullprüfungen oder Castings erforderlich sind. Irgendwann wird ein SystemWille sagen "Gib mir diese Komponente, ich weiß, dass du sie hast" und keine Zeit damit verschwenden, diejenigen zu fragen, die GameObjectdie nicht haben Component. Sag, frag nicht.