Sto realizzando un gioco che utilizza oggetti di gioco basati su componenti e non riesco a implementare un modo in cui ciascun componente può comunicare con il suo oggetto di gioco. Piuttosto che spiegare tutto in una volta, spiegherò ogni parte del codice di esempio pertinente:
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;
}
La GameObjectManager
tiene tutti gli oggetti del gioco e dei loro componenti. È anche responsabile dell'aggiornamento degli oggetti di gioco. Lo fa aggiornando i vettori dei componenti in un ordine specifico. Uso i vettori anziché gli array in modo che non vi sia praticamente alcun limite al numero di oggetti di gioco che possono esistere contemporaneamente.
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;
}
La GameObject
classe sa quali sono i suoi componenti e può inviargli messaggi.
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);
}
La Component
classe è pura virtuale in modo che le classi per i diversi tipi di componenti possano implementare come gestire i messaggi e aggiornare. Inoltre è in grado di inviare messaggi.
Ora sorge il problema su come i componenti possono chiamare le sendMessage
funzioni in GameObject
e GameObjectManager
. Ho trovato due possibili soluzioni:
- Dai
Component
un puntatore al suoGameObject
.
Tuttavia, poiché gli oggetti di gioco sono in un vettore, i puntatori potrebbero diventare rapidamente invalidati (lo stesso si potrebbe dire del vettore in GameObject
, ma si spera che la soluzione a questo problema possa anche risolverlo). Potrei mettere gli oggetti di gioco in un array, ma poi dovrei passare un numero arbitrario per la dimensione, che potrebbe facilmente essere inutilmente alta e perdere memoria.
- Dai
Component
un puntatore aGameObjectManager
.
Tuttavia, non desidero che i componenti siano in grado di chiamare la funzione di aggiornamento del gestore. Sono l'unica persona che lavora a questo progetto, ma non voglio prendere l'abitudine di scrivere codice potenzialmente pericoloso.
Come posso risolvere questo problema mantenendo il mio codice sicuro e compatibile con la cache?