Also entwickle ich meine erste Game Engine und ich habe eine Wand getroffen. Derzeit habe ich eine Entity-Basisklasse, die einen Vektor von Komponentenzeigern hat, der Zeiger auf Komponentenobjekte innerhalb einiger Systemmanagerklassen (graphisManager, PhysicsManager usw.) enthält. Hier ist meine aktuellen Entity-Header (abgespeckte auf Hauptproblem zu konzentrieren):Wie man Komponenten in einer Spielengine am besten verwaltet?
Entity.h
class Component;
namespace BlazeGameWorld
{
class Entity
{
public:
BlazeFramework::Math::Vector2D position;
protected:
Vector<Component*> components;
static BlazeGraphics::GraphicsManager graphicsManager;
static BlazePhysics::PhysicsManager physicsManager;
static BlazeInput::InputManager inputManager;
//....other managers
private:
///////////////////////////////////////////////////////////////////////
public:
Entity();
~Entity();
virtual bool Initialize();
virtual bool Shutdown();
virtual void Update() = 0;
void AddComponent(Component* p_component);
//Part of the broadcast messaging system for components to be able
//to talk to one another in a decoupled way.
void SendMessage(uint messageID);
protected:
private:
};
}
Wie Sie sehen können, ist die Idee, statische Systemmanager Klassen zu haben, die Zeiger auf den tatsächlichen verwalten Komponenten auf dem Heap. Hier ist ein grober Kopf für die potentielle PhysicsManager Klasse (und es ist ähnlich für die anderen Manager-Klassen):
PhysicsManager.h
class PhysicsComponent;
namespace BlazePhysics
{
class PhysicsManager
{
public:
protected:
int numPhysicsComponents;
private:
Vector<PhysicsComponent*> physicsComponents;
/////////////////////////////////////////////////////////////
public:
PhysicsManager();
~PhysicsManager();
bool Initialize();
bool Shutdown();
void Update();
template <typename PhysicsComponentType>
PhysicsComponentType* CreatePhysicsComponent();
private:
};
//template definitions
template <typename PhysicsComponentType>
PhysicsComponentType* PhysicsManager::CreatePhysicsComponent()
{
PhysicsComponentType* physicsComponent = new PhysicsComponentType
physicsComponents.push_back(physicsComponent);
return physicsComponents.at(numPhysicsComponents++);
}
}
So kann ich speichern Sie alle verschiedenen physicsComponent Zeiger im PhysicsManger Vektor (Zeiger auf CollisionComponents, PositionComponents usw.). Das Problem ist, wenn ich eine Methode aufrufen wollte, die für eine bestimmte Physikkomponente spezifisch ist, kann ich nicht kompilieren. Wenn ich zum Beispiel (in der Update-Schleife für PhysicsManager) die Methode CheckCollision() eines collisionComponents jedes Frame aktualisieren wollte, kann ich nicht einfach in einer for-Schleife physicsComponents.at(i).CheckCollision
sagen, weil der Compiler zur Kompilierzeit nicht weiß, was eine CollisionComponent ist. Gibt es eine Möglichkeit, den Typ der Komponente im Array zuerst abzuleiten und dann, wenn sie mit CollisionComponent übereinstimmt, die CheckCollision-Methode aufzurufen? Oder ist es besser, dies zu implementieren, da dies irgendwie klobig erscheint?
Gut, hier eine komponentenbasierte Engine zu sehen, ich arbeite auch an meiner ersten Game Engine mit einer ähnlichen Struktur wie deiner. Allerdings habe ich jedem System eine Referenz der Game Engine übergeben, damit sie die Referenz für den Zugriff auf andere Systeme verwenden kann. Ich weiß nicht, ob es gut ist, aber zumindest funktioniert es. Ich hoffe, hier eine bessere Lösung zu sehen. XD –
Ich bin froh, dass Sie hören, dass die Dinge funktionieren! Ich betrachte einige Lösungen, die ein Array von Arrays der verschiedenen Komponententypen implementieren.Wenn ich herausfinden kann, wie man so etwas implementiert, könnte ich hier eine Lösung veröffentlichen. – Jason