Tworzę grę, która wykorzystuje obiekty gier oparte na komponentach, i trudno mi wdrożyć sposób komunikacji każdego komponentu z jego obiektem gry. Zamiast wyjaśniać wszystko naraz, wyjaśnię każdą część odpowiedniego przykładowego kodu:
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;
}
GameObjectManager
Posiada wszystkie obiekty gry i ich komponentów. Odpowiada również za aktualizację obiektów gry. Odbywa się to poprzez aktualizację wektorów składowych w określonej kolejności. Używam wektorów zamiast tablic, więc praktycznie nie ma ograniczenia co do liczby obiektów gry, które mogą istnieć jednocześnie.
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;
}
GameObject
Klasa wie, jakie są jej składniki i może wysyłać do nich wiadomości.
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);
}
Component
Klasa jest czysto wirtualne, dzięki czemu zajęcia dla różnych typów elementów można wdrożyć jak obsługiwać wiadomości i aktualizacji. Jest również w stanie wysyłać wiadomości.
Teraz pojawia się problem, w jaki sposób komponenty mogą wywoływać sendMessage
funkcje w GameObject
i GameObjectManager
. Wymyśliłem dwa możliwe rozwiązania:
- Daj
Component
wskaźnik do tegoGameObject
.
Ponieważ jednak obiekty gry znajdują się w wektorze, wskaźniki mogą szybko zostać unieważnione (to samo można powiedzieć o wektorze w GameObject
, ale mam nadzieję, że rozwiązanie tego problemu może również rozwiązać ten problem). Mógłbym umieścić obiekty gry w tablicy, ale wtedy musiałbym podać dowolną liczbę dla wielkości, która z łatwością mogłaby być niepotrzebnie wysoka i marnować pamięć.
- Daj
Component
wskaźnik doGameObjectManager
.
Nie chcę jednak, aby komponenty mogły wywoływać funkcję aktualizacji menedżera. Jestem jedyną osobą pracującą nad tym projektem, ale nie chcę mieć zwyczaju pisania potencjalnie niebezpiecznego kodu.
Jak mogę rozwiązać ten problem, jednocześnie zachowując kod i pamięć podręczną w bezpieczny sposób?