Как правильно организовать взаимодействия объектов в игре, что бы не нужно было узнавать тип объекта(с++, ООП)? У меня есть класс LevelLoader. Он возвращает вектор объектов BaseObject Я передаю его в GameField. Игрок побеждает, тогда, когда в GameField не остается ни одной Point. Но как мне это определять? Первое что приходит в голово - при добавлении объектов в GameField, проверяем, если добавляем Point, то увеличиваем pointsCount на 1 (с уменьшением при удалении Point проблем нет). Но проверять тип объектов - это очень не хорошо. Поэтому нужно как-то по-другому. Может быть лучше считать количество созданных точек в LevelLoader и передавать в GameField? Но это тоже не кажется лучшим решением. p.s. ну и static поле в Point - тоже не вариант в принципе, так как меня интересует количество точек в GameField, а не вообще (хоть в практически всегда оно и будет совпадать).
В данной ситуации рекомендуется использовать паттерн Observer.
Вы можете добавить объект Observer в классы Point и GameField. Когда объект Point создается или уничтожается, он будет уведомлять объект GameField об этом. Таким образом, GameField всегда будет в курсе количества объектов Point на поле.
Примерно таким образом вы можете реализовать данный механизм:
#include <iostream> #include <vector> // Interface for Observer class Observer { public: virtual void update() = 0; }; // Base class for all objects class BaseObject { public: virtual ~BaseObject() {} virtual void notifyObservers() = 0; // Notify observers when the state changes }; // Class representing the Point object class Point : public BaseObject { public: Point() { notifyObservers(); } void notifyObservers() override { for (Observer* observer : observers) { observer->update(); } } void addObserver(Observer* observer) { observers.push_back(observer); } private: std::vector<Observer*> observers; }; // Class representing the GameField object class GameField : public Observer { public: void update() override { // Check the number of Point objects on the field int pointsCount = 0; for (BaseObject* object : objects) { if (dynamic_cast<Point*>(object)) { pointsCount++; } } // Check win condition if (pointsCount == 0) { std::cout << "Game over, player wins!" << std::endl; } } void addObject(BaseObject* object) { objects.push_back(object); object->addObserver(this); } private: std::vector<BaseObject*> objects; }; int main() { LevelLoader loader; std::vector<BaseObject*> objects = loader.loadLevel(); GameField field; for (BaseObject* object : objects) { field.addObject(object); } // Game loop // Add game logic here return 0; }
Таким образом, при добавлении объектов в GameField, GameField будет уведомляться об изменениях и самостоятельно проверять количество объектов Point на поле, не требуя от объектов BaseObject знания о своих типах.
В данной ситуации рекомендуется использовать паттерн Observer.
Вы можете добавить объект Observer в классы Point и GameField. Когда объект Point создается или уничтожается, он будет уведомлять объект GameField об этом. Таким образом, GameField всегда будет в курсе количества объектов Point на поле.
Примерно таким образом вы можете реализовать данный механизм:
#include <iostream>#include <vector>
// Interface for Observer
class Observer {
public:
virtual void update() = 0;
};
// Base class for all objects
class BaseObject {
public:
virtual ~BaseObject() {}
virtual void notifyObservers() = 0; // Notify observers when the state changes
};
// Class representing the Point object
class Point : public BaseObject {
public:
Point() {
notifyObservers();
}
void notifyObservers() override {
for (Observer* observer : observers) {
observer->update();
}
}
void addObserver(Observer* observer) {
observers.push_back(observer);
}
private:
std::vector<Observer*> observers;
};
// Class representing the GameField object
class GameField : public Observer {
public:
void update() override {
// Check the number of Point objects on the field
int pointsCount = 0;
for (BaseObject* object : objects) {
if (dynamic_cast<Point*>(object)) {
pointsCount++;
}
}
// Check win condition
if (pointsCount == 0) {
std::cout << "Game over, player wins!" << std::endl;
}
}
void addObject(BaseObject* object) {
objects.push_back(object);
object->addObserver(this);
}
private:
std::vector<BaseObject*> objects;
};
int main() {
LevelLoader loader;
std::vector<BaseObject*> objects = loader.loadLevel();
GameField field;
for (BaseObject* object : objects) {
field.addObject(object);
}
// Game loop
// Add game logic here
return 0;
}
Таким образом, при добавлении объектов в GameField, GameField будет уведомляться об изменениях и самостоятельно проверять количество объектов Point на поле, не требуя от объектов BaseObject знания о своих типах.