SystemFactory for dynamic creation and fetching of systems in a world.

This commit is contained in:
2014-03-09 03:37:39 +01:00
parent f767cdbc9c
commit c952953787
15 changed files with 218 additions and 100 deletions
+1 -1
View File
@@ -9,6 +9,6 @@ struct Component
EntityID Entity;
};
//&static ComponentFactory componentFactory;
class ComponentFactory : public Factory<Component*> { };
#endif // Component_h__
+4 -4
View File
@@ -12,10 +12,10 @@ namespace Components
struct Input : Component
{
std::array<int, GLFW_KEY_LAST> KeyState;
std::array<int, GLFW_KEY_LAST> LastKeyState;
std::array<int, GLFW_MOUSE_BUTTON_LAST> MouseState;
std::array<int, GLFW_MOUSE_BUTTON_LAST> LastMouseState;
std::array<int, GLFW_KEY_LAST+1> KeyState;
std::array<int, GLFW_KEY_LAST+1> LastKeyState;
std::array<int, GLFW_MOUSE_BUTTON_LAST+1> MouseState;
std::array<int, GLFW_MOUSE_BUTTON_LAST+1> LastMouseState;
float dX, dY;
};
+15 -8
View File
@@ -9,20 +9,24 @@
#include "logging.h"
#include "glerror.h"
#include "World.h"
#include "Renderer.h"
#include "GameWorld.h"
class Engine
{
public:
Engine(int argc, char* argv[])
{
renderer.Initialize();
m_Renderer = std::make_shared<Renderer>();
m_Renderer->Initialize();
m_World = std::make_shared<GameWorld>(m_Renderer);
m_World->Initialize();
m_LastTime = glfwGetTime();
}
bool Running() const { return !glfwWindowShouldClose(renderer.GetWindow()); }
bool Running() const { return !glfwWindowShouldClose(m_Renderer->GetWindow()); }
void Tick()
{
@@ -30,13 +34,16 @@ public:
double dt = currentTime - m_LastTime;
m_LastTime = currentTime;
//World.Update(dt);
renderer.Draw(dt);
m_World->Update(dt);
m_Renderer->Draw(dt);
glfwPollEvents();
}
private:
Renderer renderer;
std::shared_ptr<Renderer> m_Renderer;
// TODO: This should ultimately live in GameFrame
std::shared_ptr<GameWorld> m_World;
double m_LastTime;
};
+1
View File
@@ -137,6 +137,7 @@
<ClInclude Include="Entity.h" />
<ClInclude Include="Frame.h" />
<ClInclude Include="GameFrame.h" />
<ClInclude Include="GameWorld.h" />
<ClInclude Include="GUIManager.h" />
<ClInclude Include="logging.h" />
<ClInclude Include="glerror.h" />
+12 -11
View File
@@ -27,21 +27,21 @@
<ClCompile Include="Engine.h" />
<ClCompile Include="Texture.cpp" />
<ClCompile Include="GUIManager.cpp">
<Filter>Gui</Filter>
<Filter>GUI</Filter>
</ClCompile>
<ClCompile Include="Renderer.cpp" />
<ClCompile Include="ShaderProgram.cpp" />
<ClCompile Include="Frame.cpp">
<Filter>Gui</Filter>
<Filter>GUI</Filter>
</ClCompile>
<ClCompile Include="TextFrame.cpp">
<Filter>Gui</Filter>
<Filter>GUI</Filter>
</ClCompile>
<ClCompile Include="MenuFrame.cpp">
<Filter>Gui</Filter>
<Filter>GUI</Filter>
</ClCompile>
<ClCompile Include="GameFrame.cpp">
<Filter>Gui</Filter>
<Filter>GUI</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
@@ -125,20 +125,21 @@
<ClInclude Include="Renderer.h" />
<ClInclude Include="Texture.h" />
<ClInclude Include="GUIManager.h">
<Filter>Gui</Filter>
<Filter>GUI</Filter>
</ClInclude>
<ClInclude Include="Frame.h">
<Filter>Gui</Filter>
<Filter>GUI</Filter>
</ClInclude>
<ClInclude Include="TextFrame.h">
<Filter>Gui</Filter>
<Filter>GUI</Filter>
</ClInclude>
<ClInclude Include="MenuFrame.h">
<Filter>Gui</Filter>
<Filter>GUI</Filter>
</ClInclude>
<ClInclude Include="GameFrame.h">
<Filter>Gui</Filter>
<Filter>GUI</Filter>
</ClInclude>
<ClInclude Include="GameWorld.h" />
</ItemGroup>
<ItemGroup>
<None Include="Shaders\Fragment.glsl">
@@ -161,7 +162,7 @@
<Filter Include="Util">
<UniqueIdentifier>{d985d7a7-c041-46fe-ae03-aa40295a7aad}</UniqueIdentifier>
</Filter>
<Filter Include="Gui">
<Filter Include="GUI">
<UniqueIdentifier>{7bdb0f69-049e-4f16-b271-2495e02e4b28}</UniqueIdentifier>
</Filter>
</ItemGroup>
-3
View File
@@ -29,7 +29,4 @@ private:
std::map<std::string, std::function<T(void)>> m_FactoryFunctions;
};
struct Component;
class ComponentFactory : public Factory<Component*> { };
#endif // ComponentFactory_h__
+92
View File
@@ -0,0 +1,92 @@
#ifndef GameWorld_h__
#define GameWorld_h__
#include "World.h"
#include "Renderer.h"
#include "Systems/CollisionSystem.h"
#include "Systems/InputSystem.h"
#include "Systems/LevelGenerationSystem.h"
#include "Systems/ParticleSystem.h"
#include "Systems/PlayerSystem.h"
#include "Systems/RenderSystem.h"
#include "Systems/SoundSystem.h"
#include "Components/Bounds.h"
#include "Components/Camera.h"
#include "Components/Collision.h"
#include "Components/DirectionalLight.h"
#include "Components/Input.h"
#include "Components/Model.h"
#include "Components/ParticleEmitter.h"
#include "Components/PointLight.h"
#include "Components/PowerUp.h"
#include "Components/SoundEmitter.h"
#include "Components/Sprite.h"
#include "Components/Stat.h"
#include "Components/Template.h"
#include "Components/Transform.h"
class GameWorld : public World
{
public:
GameWorld(std::shared_ptr<Renderer> renderer);
void Initialize() override;
void RegisterSystems() override;
void RegisterComponents() override;
void Update(double dt) override;
private:
std::shared_ptr<Renderer> m_Renderer;
};
GameWorld::GameWorld(std::shared_ptr<Renderer> renderer)
: m_Renderer(renderer), World()
{
}
void GameWorld::Initialize()
{
World::Initialize();
AddSystem("InputSystem");
}
void GameWorld::RegisterSystems()
{
//m_SystemFactory.Register("LevelGenerationSystem", [this]() { return new Systems::LevelGenerationSystem(this); });
m_SystemFactory.Register("InputSystem", [this]() { return new Systems::InputSystem(this, m_Renderer); });
//m_SystemFactory.Register("CollisionSystem", [this]() { return new Systems::CollisionSystem(this); });
//m_SystemFactory.Register("ParticleSystem", [this]() { return new Systems::ParticleSystem(this); });
//m_SystemFactory.Register("PlayerSystem", [this]() { return new Systems::PlayerSystem(this); });
//m_SystemFactory.Register("SoundSystem", [this]() { return new Systems::SoundSystem(this); });
//m_SystemFactory.Register("RenderSystem", [this]() { return new Systems::RenderSystem(this, m_Renderer); });
}
void GameWorld::RegisterComponents()
{
m_ComponentFactory.Register("Bounds", []() { return new Components::Bounds(); });
m_ComponentFactory.Register("Camera", []() { return new Components::Camera(); });
m_ComponentFactory.Register("Collision", []() { return new Components::Collision(); });
m_ComponentFactory.Register("DirectionalLight", []() { return new Components::DirectionalLight(); });
m_ComponentFactory.Register("Input", []() { return new Components::Input(); });
m_ComponentFactory.Register("Model", []() { return new Components::Model(); });
m_ComponentFactory.Register("ParticleEmitter", []() { return new Components::ParticleEmitter(); });
m_ComponentFactory.Register("PointLight", []() { return new Components::PointLight(); });
m_ComponentFactory.Register("PowerUp", []() { return new Components::PowerUp(); });
m_ComponentFactory.Register("SoundEmitter", []() { return new Components::SoundEmitter(); });
m_ComponentFactory.Register("Sprite", []() { return new Components::Sprite(); });
m_ComponentFactory.Register("Stat", []() { return new Components::Stat(); });
m_ComponentFactory.Register("Template", []() { return new Components::Template(); });
m_ComponentFactory.Register("Transform", []() { return new Components::Transform(); });
}
void GameWorld::Update(double dt)
{
World::Update(dt);
}
#endif // GameWorld_h__
+5 -2
View File
@@ -1,6 +1,7 @@
#ifndef System_h__
#define System_h__
#include "Factory.h"
#include "Entity.h"
#include "Component.h"
@@ -15,13 +16,15 @@ public:
// Called once per system every tick
virtual void Update(double dt) { }
// Called once for every entity in the world every tick
virtual void Update(double dt, EntityID entity, EntityID parent) { }
virtual void UpdateEntity(double dt, EntityID entity, EntityID parent) { }
// Called when a component is created
virtual void OnComponentCreated(std::string type, std:: shared_ptr<Component> component);
virtual void OnComponentCreated(std::string type, std:: shared_ptr<Component> component) { }
protected:
World* m_World;
};
class SystemFactory : public Factory<System*> { };
#endif // System_h__
+1 -1
View File
@@ -1,7 +1,7 @@
#include "CollisionSystem.h"
#include "World.h"
void Systems::Collision::Update(double dt, EntityID entity, EntityID parent)
void Systems::CollisionSystem::UpdateEntity(double dt, EntityID entity, EntityID parent)
{
if (parent != 0)
{
+4 -3
View File
@@ -9,12 +9,13 @@
namespace Systems
{
class Collision : public System
class CollisionSystem : public System
{
public:
Collision(World* world) : System(world) { }
CollisionSystem(World* world)
: System(world) { }
void Update(double dt, EntityID entity, EntityID parent) override;
void UpdateEntity(double dt, EntityID entity, EntityID parent) override;
};
}
+2 -2
View File
@@ -13,7 +13,7 @@ void Systems::InputSystem::Update(double dt)
// Mouse buttons
for (int i = 0; i <= GLFW_MOUSE_BUTTON_LAST; ++i) {
m_CurrentKeyState[i] = glfwGetMouseButton(m_Renderer->GetWindow(), i);
m_CurrentMouseState[i] = glfwGetMouseButton(m_Renderer->GetWindow(), i);
}
// Cursor position
@@ -25,7 +25,7 @@ void Systems::InputSystem::Update(double dt)
m_LastMouseY = ypos;
}
void Systems::InputSystem::Update(double dt, EntityID entity, EntityID parent)
void Systems::InputSystem::UpdateEntity(double dt, EntityID entity, EntityID parent)
{
auto input = m_World->GetComponent<Components::Input>(entity, "Input");
if (input == nullptr)
+7 -7
View File
@@ -13,19 +13,19 @@ namespace Systems
class InputSystem : public System
{
public:
InputSystem(World* world, Renderer* renderer)
InputSystem(World* world, std::shared_ptr<Renderer> renderer)
: System(world), m_Renderer(renderer) { }
void Update(double dt) override;
void Update(double dt, EntityID entity, EntityID parent) override;
void UpdateEntity(double dt, EntityID entity, EntityID parent) override;
private:
Renderer* m_Renderer;
std::shared_ptr<Renderer> m_Renderer;
std::array<int, GLFW_KEY_LAST> m_CurrentKeyState;
std::array<int, GLFW_KEY_LAST> m_LastKeyState;
std::array<int, GLFW_MOUSE_BUTTON_LAST> m_CurrentMouseState;
std::array<int, GLFW_MOUSE_BUTTON_LAST> m_LastMouseState;
std::array<int, GLFW_KEY_LAST+1> m_CurrentKeyState;
std::array<int, GLFW_KEY_LAST+1> m_LastKeyState;
std::array<int, GLFW_MOUSE_BUTTON_LAST+1> m_CurrentMouseState;
std::array<int, GLFW_MOUSE_BUTTON_LAST+1> m_LastMouseState;
float m_CurrentMouseDeltaX, m_CurrentMouseDeltaY;
float m_LastMouseX, m_LastMouseY;
};
+21 -16
View File
@@ -23,7 +23,7 @@ void World::RecursiveUpdate(std::shared_ptr<System> system, double dt, EntityID
EntityID parent = pair.second;
if (parent == parentEntity) {
system->Update(dt, child, parent);
system->UpdateEntity(dt, child, parent);
RecursiveUpdate(system, dt, child);
}
}
@@ -31,17 +31,13 @@ void World::RecursiveUpdate(std::shared_ptr<System> system, double dt, EntityID
void World::Update(double dt)
{
for (auto system : m_Systems) {
for (auto pair : m_Systems) {
auto system = pair.second;
system->Update(dt);
RecursiveUpdate(system, dt, 0);
}
}
void World::AddSystem(System* system)
{
}
//std::vector<EntityID> GetEntityChildren(EntityID entity);
//{
// std::vector<EntityID> children;
@@ -83,21 +79,30 @@ World::~World()
World::World()
{
m_LastEntityID = 0;
m_Systems.push_back(std::make_shared<Systems::Collision>(this));
RegisterComponents();
RegisterSystems();
}
void World::RegisterComponents()
void World::Initialize()
{
m_ComponentFactory.Register("Transform", []() { return new Components::Transform(); });
m_ComponentFactory.Register("Input", []() { return new Components::Input(); });
m_ComponentFactory.Register("DirectionalLight", []() { return new Components::DirectionalLight(); });
RegisterSystems();
RegisterComponents();
}
void World::RegisterSystems()
{
}
void World::RegisterComponents()
{
}
std::shared_ptr<Component> World::AddComponent(EntityID entity, std::string componentType)
{
return AddComponent<Component>(entity, componentType);
}
void World::AddSystem(std::string systemType)
{
m_Systems[systemType] = std::shared_ptr<System>(m_SystemFactory.Create(systemType));
}
+51 -40
View File
@@ -6,17 +6,12 @@
#include <vector>
#include <string>
#include "Renderer.h"
#include "logging.h"
#include "Factory.h"
#include "Entity.h"
#include "Component.h"
#include "Factory.h"
#include "Components/Transform.h"
#include "Components/Input.h"
#include "Components/DirectionalLight.h"
#include "System.h"
#include "Systems/CollisionSystem.h"
class World
{
@@ -24,9 +19,15 @@ public:
World();
~World();
virtual void Initialize();
virtual void RegisterComponents();
virtual void RegisterSystems();
void AddSystem(std::string systemType);
template <class T>
std::shared_ptr<T> GetSystem(std::string systemType);
EntityID CreateEntity(EntityID parent = 0);
void RemoveEntity(EntityID entity);
@@ -36,56 +37,66 @@ public:
EntityID GetEntityParent(EntityID entity);
template <class T>
std::shared_ptr<T> AddComponent(EntityID entity, std::string componentType)
{
std::shared_ptr<T> component = std::shared_ptr<T>(static_cast<T*>(m_ComponentFactory.Create(componentType)));
if (component == nullptr) {
LOG_ERROR("Failed to attach invalid component \"%s\" to entity #%i", componentType.c_str(), entity);
return nullptr;
}
component->Entity = entity;
m_ComponentsOfType[componentType].push_back(component);
m_EntityComponents[entity][componentType] = component;
for (auto system : m_Systems) {
system->OnComponentCreated(componentType, component);
}
return component;
}
std::shared_ptr<Component> AddComponent(EntityID entity, std::string componentType)
{
return AddComponent<Component>(entity, componentType);
}
std::shared_ptr<T> AddComponent(EntityID entity, std::string componentType);
std::shared_ptr<Component> AddComponent(EntityID entity, std::string componentType);
template <class T>
std::shared_ptr<T> GetComponent(EntityID entity, std::string componentType)
{
return std::static_pointer_cast<T>(m_EntityComponents[entity][componentType]);
}
std::shared_ptr<T> GetComponent(EntityID entity, std::string componentType);
/*std::vector<EntityID> GetEntityChildren(EntityID entity);*/
void AddSystem(System* system);
void Update(double dt);
virtual void Update(double dt);
// Recursively update through the scene graph
void RecursiveUpdate(std::shared_ptr<System> system, double dt, EntityID parentEntity);
private:
protected:
SystemFactory m_SystemFactory;
ComponentFactory m_ComponentFactory;
std::unordered_map<std::string, std::shared_ptr<System>> m_Systems;
EntityID m_LastEntityID;
std::stack<EntityID> m_RecycledEntityIDs;
// A bottom to top tree. A map of child entities to parent entities.
std::unordered_map<EntityID, EntityID> m_EntityParents;
ComponentFactory m_ComponentFactory;
std::unordered_map<std::string, std::vector<std::shared_ptr<Component>>> m_ComponentsOfType;
std::unordered_map<EntityID, std::map<std::string, std::shared_ptr<Component>>> m_EntityComponents;
std::vector<std::shared_ptr<System>> m_Systems;
EntityID GenerateEntityID();
void RecycleEntityID(EntityID id);
};
template <class T>
std::shared_ptr<T> World::GetSystem(std::string systemType)
{
return std::static_pointer_cast<T>(m_Systems[systemType]);
}
template <class T>
std::shared_ptr<T> World::AddComponent(EntityID entity, std::string componentType)
{
std::shared_ptr<T> component = std::shared_ptr<T>(static_cast<T*>(m_ComponentFactory.Create(componentType)));
if (component == nullptr) {
LOG_ERROR("Failed to attach invalid component \"%s\" to entity #%i", componentType.c_str(), entity);
return nullptr;
}
component->Entity = entity;
m_ComponentsOfType[componentType].push_back(component);
m_EntityComponents[entity][componentType] = component;
for (auto pair : m_Systems) {
auto system = pair.second;
system->OnComponentCreated(componentType, component);
}
return component;
}
template <class T>
std::shared_ptr<T> World::GetComponent(EntityID entity, std::string componentType)
{
return std::static_pointer_cast<T>(m_EntityComponents[entity][componentType]);
}
#endif // World_h__
+2 -2
View File
@@ -39,13 +39,13 @@
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IncludePath>$(SolutionDir)\Escape-the-Dawn;$(SolutionDir)\Libraries\SOIL\src;\Libraries\SOIL\src;$(ProjectDir);$(SolutionDir)\Libraries;$(SolutionDir)\Libraries\glew-1.10.0\include;$(SolutionDir)\Libraries\glfw-3.0.4\include;$(SolutionDir)\Libraries\glm-0.9.5.2;$(IncludePath)</IncludePath>
<IncludePath>$(BOOST_ROOT);$(SolutionDir)\Escape-the-Dawn;$(SolutionDir)\Libraries\SOIL\src;\Libraries\SOIL\src;$(ProjectDir);$(SolutionDir)\Libraries;$(SolutionDir)\Libraries\glew-1.10.0\include;$(SolutionDir)\Libraries\glfw-3.0.4\include;$(SolutionDir)\Libraries\glm-0.9.5.2;$(IncludePath)</IncludePath>
<LibraryPath>$(BOOST_ROOT)\lib32-msvc-11.0;$(LibraryPath)</LibraryPath>
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<IncludePath>$(SolutionDir)\Escape-the-Dawn;$(SolutionDir)\Libraries\SOIL\src;\Libraries\SOIL\src;$(ProjectDir);$(SolutionDir)\Libraries;$(SolutionDir)\Libraries\glew-1.10.0\include;$(SolutionDir)\Libraries\glfw-3.0.4\include;$(SolutionDir)\Libraries\glm-0.9.5.2;$(IncludePath)</IncludePath>
<IncludePath>$(BOOST_ROOT);$(SolutionDir)\Escape-the-Dawn;$(SolutionDir)\Libraries\SOIL\src;\Libraries\SOIL\src;$(ProjectDir);$(SolutionDir)\Libraries;$(SolutionDir)\Libraries\glew-1.10.0\include;$(SolutionDir)\Libraries\glfw-3.0.4\include;$(SolutionDir)\Libraries\glm-0.9.5.2;$(IncludePath)</IncludePath>
<LibraryPath>$(BOOST_ROOT)\lib32-msvc-11.0;$(LibraryPath)</LibraryPath>
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(ProjectName)\</IntDir>