Hallo alle zusammen,
Ich habe eine Frage bezüglich der Verwaltung von Spielobjekten. Ich programmiere zur Zeit einen Dune II Clone, also ein RTS (aber mit realistischer Umsetzungsmöglichkeit in absehbarer Zeit für eine Person).
Ich habe bereits eine Lösung zur Verwaltung der Spielobjekte, wollte aber mal Fragen wie ihr das evtl. handhabt bzw. welche Möglichkeiten ihr noch kennt.
Anforderungen sind:
- Durchlaufen aller Objekte zum Updaten / Rendern.
- Zugriff auf Objekte via Koordinate und Ebene.
- Besonders schneller Zugriff auf Objekte via Koordinate (für Pfadfindung).
- Finden eines bestimmten Objektes innerhalb eines bestimmten Radius / Rechtecks.
- Nach Möglichkeit speicherschonend. (Ist eigentlich keine wichtige Anforderung)
Möglichkeiten die ich in Betracht gezogen habe:
- Tiles als 2D Array. Jedes Tile speichert in einem Array die Objekte aller möglichen Ebenen.
- Tiles als 2D Array. Jedes Tile hat (nur wenn nötig) eine Referenz auf ein Objekt welches die eigentlichen Spielobjekte referenziert.
- Tiles als 2D Array. Ein Quadtree für die Spielobjekte.
- Tiles als 2D Array. Hashtable (bzw. Dictonary, da C#) zum Speichern der Objekte (Index wird einfach berechnet nach der Formal: x + (y * width) + (level * (width * height))).
Ich benutze die letzte Variante. Wobei ich mir noch ein spezielles System ausgedacht habe um je nach Bedarf an die benötigten Spielobjekte zu gelangen ohne jedes mal alle Objekte in einer Schleife durch zu gehen.
Ich habe eine extra Klasse (GameEntityStore) die die Spielobjekte in einem Dictonary speichert. Wenn man eine neue Instanz der Klasse macht, kann man ihr eine andere als Elternliste übergeben. Dadurch sind die Listen in einer Baumstruktur angeordnet und synchronisieren sich gegenseitig. Da es schwer ist das zu erklären hier mal ein Beispiel:
|
C#-Quelltext
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
// World erbt von der Liste
public class World : GameEntityStore<GameEntity>
{
}
// Jeder Spieler hat z.B. eine eigene Liste:
public class Player
{
public Player(World world)
{
// PlayerGameEntityStore (das auch von GameEntityStore erbt) filtert alle Objekte die nicht von diesem Spieler sind raus.
this.entities = new PlayerGameEntityStore<GameEntity>(world, this);
}
}
// woanders kann man z.B. eine Liste aller Harvester des blauen Spielers haben indem man schreibt:
this.harvesters = new GameEntityStore<Harvester>(this.player.Entities);
|
Wird jetzt in einer der Listen ein Objekt hinzugefügt, wird dieses an die darüber liegende Liste sowie an alle darunterliegenden Listen gemeldet. Die Synchronisation wird also nur beim Ändern einer der Listen angestoßen. Der Vorteil ist, dass ich Listen habe, die meistens nur die Objekte beinhalten die mich an der Stelle interessieren.
Ok wie Ihr seht, habe ich mir bereits viele Gedanken gemacht und habe auch bereits eine Lösung gefunden die mir gefällt. Dennoch wollte ich fragen, wie Ihr so etwas gelöst habt oder lösen würdet.