Ich habe viel über Designmuster gelesen, aber bei der Verwendung dieser Muster komme ich immer wieder auf eine Frage zurück. Wie sollen meine Entitäten auf Informationen über einander zugreifen?
Angenommen, ich verwende ein einfaches Muster, bei dem jedes Objekt aktualisiert und selbst gezeichnet wird:
class Monster extends GameEntity {
public void update(double delta) {}
public void draw(Graphics g) {}
}
Ich schreibe meine Update-Schleife, aber mir ist klar, dass Monster Kenntnisse darüber benötigt, wo sich der Spieler befindet, wo sich Städte auf der Hauptkarte befinden oder andere zufällige Daten.
Wie kommt Monster dazu? Initialisiere ich es mit einem Verweis auf alles Mögliche, was es braucht?
class Monster extends GameEntity {
public Monster(Player player, City[] cityList) {
this.player = player;
this.cityList = cityList;
}
}
Das sieht ziemlich chaotisch aus. Oder habe ich eine Art Hauptmanager, der Zugriff auf alles hat und das an alles weitergibt?
class Monster extends GameEntity {
public Monster(GiantGlobalManager manager) {
this.manager = manager;
}
public void update(double delta) {
cities = this.manager.getCities();
}
}
Oder vielleicht den Manager als Singleton? Wir könnten diese Manager auch in ihre Problembereiche einteilen.
class Monster extends GameEntity {
public void update(double delta) {
cities = CityManager.getInstance().getCities();
player = PlayerManager.getInstance().getPlayer();
guiManager.getInstance().createMenu();
}
}
Aber das fühlt sich immer noch nicht ganz richtig an. Jetzt muss ich all diese Manager warten, und es scheint falsch, wenn meine Objekte all diese statischen Aufrufe tätigen. Zweitens sollten viele dieser Objekte nicht auf alles zugreifen können, was von diesen Klassen bereitgestellt wird. Alles auf alles zugreifen zu lassen, fühlt sich für mich wie eine Ausrede an.
Unabhängig davon, welche Muster ich verwende - ob ich Objekte in Komponenten zerlege oder nur meine Zeichnungs- und Aktualisierungsschleifen in separate Objekte verschiebe - brauche ich immer noch eine Möglichkeit, damit sie kommunizieren können. Was ist ein guter Weg, um dies zu tun? Was fehlt mir hier?
Sollte dies alles durch Ereignisse geschehen? Aber eine Liste der Städte zu bekommen ist nicht wirklich ein Ereignis, sondern nur Daten, die das Monster benötigt.
quelle
Eine geringfügige Variante der Implementierung von jzx wäre die Verwendung einer Aktualisierungsmethode, die der Vorgehensweise beim Zeichnen ähnelt. In der architektonischen Gestaltung ist es nicht ungewöhnlich, ein Kontextobjekt zu haben, das häufig eine Vielzahl von Zustandsinformationen enthält.
Daher wird
GameEntity
Ihre Aktualisierungsmethode in einer bestimmten Implementierungsklasse möglicherweise als solche geschrieben:Sie können diesen Ansatz invertieren, wenn ein System sowohl als Factory als auch als Ort fungiert, an dem sich Ihre Aktualisierungslogik befindet. Diese Systeme werden in einer deterministischen Reihenfolge aktualisiert und führen kleine Sätze von Operationen an einem großen Eimer von Entitäten basierend auf Kriterien aus. Dies führt häufig zu schnelleren und cachefreundlicheren Vorgängen.
Im Wesentlichen könnte diese obige Aktualisierungslogik in eine Reihe solcher Systeme übertragen werden
Letztendlich ist es viel einfacher, diesen Ansatz langfristig aufrechtzuerhalten, da Sie häufig Gründungssysteme erstellen können, die Sie in komplexeren Systemen wiederverwenden, die letztendlich einige Spielanforderungen implementieren. Darüber hinaus werden durch die Verwendung der Konstruktorinjektion Abhängigkeiten in Ihrer Architektur explizit identifiziert, ohne dass Code durchsucht werden muss, um festzustellen, was was benötigt.
Sie müssen nur noch einen Kartenlader oder einen solchen haben, der versteht, wie Sie Ihre Level-Daten lesen und die verschiedenen Systeme aufrufen, um Ihre Entitäten zu erstellen. Wenn Sie Archetypen und Archetypfabriken verwenden, kann dies möglicherweise in jene Fabriken abstrahiert werden, die letztendlich mit diesen Systemen interagieren.
quelle