Я створюю гру, яка використовує ігрові об'єкти на основі компонентів, і мені важко реалізувати спосіб для кожного компонента спілкуватися зі своїм ігровим об’єктом. Замість того, щоб пояснити все відразу, я поясню кожну частину відповідного зразкового коду:
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
Містить всі ігрові об'єкти і їх компоненти. Він також відповідає за оновлення ігрових об'єктів. Це робиться шляхом оновлення компонентів векторів у визначеному порядку. Я використовую вектори замість масивів, так що практично немає обмеження кількості ігрових об'єктів, які можуть існувати одночасно.
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
Клас знає , що його компоненти і відправляти їм повідомлення.
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
Клас чисто віртуальні , так що класи для різних типів компонентів можуть здійснювати обробку повідомлень і оновлення. Він також здатний надсилати повідомлення.
Тепер проблема виникає в тому, як компоненти можуть викликати sendMessage
функції в GameObject
і GameObjectManager
. Я придумав два можливі рішення:
- Дайте
Component
покажчик на йогоGameObject
.
Однак, оскільки ігрові об’єкти знаходяться у векторі, вказівники можуть швидко бути визнані недійсними (те саме можна сказати про вектор у GameObject
, але, сподіваємось, рішення цієї проблеми також може вирішити цю). Я міг би помістити ігрові об’єкти в масив, але тоді мені довелося б передати довільну кількість за розміром, який легко міг би бути зайвим і витрачати пам'ять.
- Дайте
Component
вказівник наGameObjectManager
.
Однак я не хочу, щоб компоненти могли викликати функцію оновлення менеджера. Я єдина людина, яка працює над цим проектом, але не хочу впадати в звичку писати потенційно небезпечний код.
Як я можу вирішити цю проблему, зберігаючи код і зберігаючи кеш?