Ich mache ein Spiel, das komponentenbasierte Spielobjekte verwendet, und es fällt mir schwer, eine Möglichkeit für jede Komponente zu implementieren, mit ihrem Spielobjekt zu kommunizieren. Anstatt alles auf einmal zu erklären, werde ich jeden Teil des relevanten Beispielcodes erklären:
class GameObjectManager {
public:
//Updates all the game objects
void update(Time dt);
//Sends a message to all game objects
void sendMessage(Message m);
private:
//Vector of all the game objects
std::vector<GameObject> gameObjects;
//vectors of the different types of components
std::vector<InputComponent> input;
std::vector<PhysicsComponent> ai;
...
std::vector<RenderComponent> render;
}
Das GameObjectManager
enthält alle Spielobjekte und deren Komponenten. Es ist auch für die Aktualisierung der Spielobjekte verantwortlich. Dazu werden die Komponentenvektoren in einer bestimmten Reihenfolge aktualisiert. Ich verwende Vektoren anstelle von Arrays, so dass die Anzahl der Spielobjekte, die gleichzeitig existieren können, praktisch unbegrenzt ist.
class GameObject {
public:
//Sends a message to the components in this game object
void sendMessage(Message m);
private:
//id to keep track of components in the manager
const int id;
//Pointers to components in the game object manager
std::vector<Component*> components;
}
Die GameObject
Klasse kennt ihre Komponenten und kann Nachrichten an sie senden.
class Component {
public:
//Receives messages and acts accordingly
virtual void handleMessage(Message m) = 0;
virtual void update(Time dt) = 0;
protected:
//Calls GameObject's sendMessage
void sendMessageToObject(Message m);
//Calls GameObjectManager's sendMessage
void sendMessageToWorld(Message m);
}
Die Component
Klasse ist rein virtuell, sodass Klassen für die verschiedenen Komponententypen den Umgang mit Nachrichten und Aktualisierungen implementieren können. Es ist auch in der Lage, Nachrichten zu senden.
Nun stellt sich das Problem, wie die Komponenten die sendMessage
Funktionen in GameObject
und aufrufen können GameObjectManager
. Ich habe zwei mögliche Lösungen gefunden:
- Geben Sie
Component
einen Zeiger auf seineGameObject
.
Da sich die Spielobjekte jedoch in einem Vektor befinden, können die Zeiger schnell ungültig werden (das Gleiche gilt für den Vektor in GameObject
, aber hoffentlich kann die Lösung dieses Problems auch diesen lösen). Ich könnte die Spielobjekte in ein Array einfügen, aber dann müsste ich eine beliebige Zahl für die Größe eingeben, die leicht unnötig hoch sein und Speicher verschwenden könnte.
- Geben Sie
Component
einen Zeiger auf dieGameObjectManager
.
Ich möchte jedoch nicht, dass Komponenten die Aktualisierungsfunktion des Managers aufrufen können. Ich bin die einzige Person, die an diesem Projekt arbeitet, aber ich möchte nicht die Gewohnheit haben, potenziell gefährlichen Code zu schreiben.
Wie kann ich dieses Problem beheben, während mein Code sicher und cachefreundlich bleibt?