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 Component
und ComponentType
Aufzä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 ComponentType
Aufzählung zu verwenden, die jeder Component
von ihnen GameObject
hat. Der Grund dafür ist, dass ich dachte, dies wäre ein viel saubererer Ansatz, wenn ich versuche, das Erforderliche Component
aus dem herauszuholen, GameObject
wenn ich von a gefragt werde System
(siehe auch Link 1 oben).
Ich versuche, nicht an einem Typ vorbeizukommen und eine Iteration über alle Component
s 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 CollidableSystem
erstellt 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 System
erstellte Element GameObject
jedes 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 Component
s von GameObject
s zu erhalten, für die keine Nullprüfungen oder Castings erforderlich sind. Irgendwann wird ein System
Wille sagen "Gib mir diese Komponente, ich weiß, dass du sie hast" und keine Zeit damit verschwenden, diejenigen zu fragen, die GameObject
die nicht haben Component
. Sag, frag nicht.