Spawner, SpawnPoint and PlayerSpawn components, and base work on their systems

This commit is contained in:
2016-01-15 18:32:47 +01:00
parent 97e12ff550
commit db1b972cd1
22 changed files with 288 additions and 4 deletions
+1 -1
Submodule assets updated: a0d1615e51...a3c92ac876
+5
View File
@@ -7,6 +7,11 @@
class World;
struct EntityWrapper
{
EntityWrapper()
: World(nullptr)
, ID(EntityID_Invalid)
{ }
EntityWrapper(::World* world, EntityID id)
: World(world)
, ID(id)
+2 -2
View File
@@ -43,7 +43,7 @@ template <typename ContextType, typename EventType>
class EventRelay : public BaseEventRelay
{
public:
typedef std::function<bool(const EventType&)> CallbackType;
typedef std::function<bool(EventType&)> CallbackType;
EventRelay()
: m_Callback(nullptr)
@@ -65,7 +65,7 @@ template <typename ContextType, typename EventType>
bool EventRelay<ContextType, EventType>::Receive(const std::shared_ptr<Event> event)
{
if (m_Callback != nullptr) {
return m_Callback(*static_cast<const EventType*>(event.get()));
return m_Callback(*static_cast<EventType*>(event.get()));
} else {
return false;
}
+2
View File
@@ -34,6 +34,8 @@ public:
EntityID GetParent(EntityID entity);
// Change the parent of an entity
void SetParent(EntityID entity, EntityID parent);
// Get children of an entity
const std::pair<std::unordered_multimap<EntityID, EntityID>::const_iterator, std::unordered_multimap<EntityID, EntityID>::const_iterator> GetChildren(EntityID entity);
// Get all component pools
const std::unordered_map<std::string, ComponentPool*>& GetComponentPools() const { return m_ComponentPools; }
// Get the entity children map
+18
View File
@@ -0,0 +1,18 @@
#ifndef ESpawnerSpawn_h__
#define ESpawnerSpawn_h__
#include "Core/Event.h"
#include "Core/EntityWrapper.h"
namespace Events
{
struct SpawnerSpawn : Event
{
EntityWrapper Spawner;
EntityWrapper Parent;
};
}
#endif
+17
View File
@@ -0,0 +1,17 @@
#include "Core/System.h"
#include "Input/EInputCommand.h"
#include "Events/ESpawnerSpawn.h"
class PlayerSpawnSystem : public ImpureSystem
{
public:
PlayerSpawnSystem(EventBroker* eventBroker);
virtual void Update(World* world, double dt) override;
private:
EventRelay<PlayerSpawnSystem, Events::InputCommand> m_OnInputCommand;
bool OnInputCommand(const Events::InputCommand& e);
std::vector<int> m_SpawnRequests;
};
+20
View File
@@ -0,0 +1,20 @@
#include <random>
#include "Common.h"
#include "GLM.h"
#include "Core/System.h"
#include "Events/ESpawnerSpawn.h"
#include "Core/Transform.h"
#include "Core/ResourceManager.h"
#include "Core/EntityFileParser.h"
class SpawnerSystem : public System
{
public:
SpawnerSystem(EventBroker* eventBroker);
private:
EventRelay<SpawnerSystem, Events::SpawnerSpawn> m_OnSpawnerSpawn;
bool OnSpawnerSpawn(Events::SpawnerSpawn& e);
void spawnEntity(EntityWrapper spawner, EntityID parent, glm::vec3 position);
};
+3
View File
@@ -12,4 +12,7 @@
<xs:include schemaLocation="Components/Trigger.xsd"/>
<xs:include schemaLocation="Components/Health.xsd"/>
<xs:include schemaLocation="Components/Collidable.xsd"/>
<xs:include schemaLocation="Components/Spawner.xsd"/>
<xs:include schemaLocation="Components/SpawnPoint.xsd"/>
<xs:include schemaLocation="Components/PlayerSpawn.xsd"/>
</xs:schema>
@@ -0,0 +1,3 @@
<c:Spawner>
<TeamID>1</EntityFile>
</c:Spawner>
@@ -0,0 +1,18 @@
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="types">
<xs:import schemaLocation="../Types.xsd" namespace="types"/>
<xs:element name="PlayerSpawn">
<xs:annotation>
<xs:documentation>Combined with a Spawner, defines a spawn point for a player team.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:all>
<xs:element name="TeamID" type="t:int" minOccurs="0">
<xs:annotation><xs:documentation>1 = Spectator, 2 = Red, 3 = Blue</xs:documentation></xs:annotation>
</xs:element>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
@@ -0,0 +1 @@
<c:SpawnPoint/>
@@ -0,0 +1,11 @@
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="types">
<xs:import schemaLocation="../Types.xsd" namespace="types"/>
<xs:element name="SpawnPoint">
<xs:annotation>
<xs:documentation>Defines this entity as a spawn point for a parent Spawner</xs:documentation>
</xs:annotation>
</xs:element>
</xs:schema>
+3
View File
@@ -0,0 +1,3 @@
<c:Spawner>
<EntityFile></EntityFile>
</c:Spawner>
+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="types">
<xs:import schemaLocation="../Types.xsd" namespace="types"/>
<xs:element name="Spawner">
<xs:annotation>
<xs:documentation>Randomly selects a child SpawnPoint component and spawns a copy of an entity template when receiving a SpawnerSpawn event. If no SpawnPoint is found it spawns from its own position.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:all>
<xs:element name="EntityFile" type="t:string" minOccurs="0">
<xs:annotation><xs:documentation>The entity template to spawn</xs:documentation></xs:annotation>
</xs:element>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
+1
View File
@@ -3,6 +3,7 @@
<Components>
<c:AABB/>
<c:Physics/>
<c:Collidable/>
<c:Model>
<Resource>Models/Core/UnitSphere.obj</Resource>
+59
View File
@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Entity xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
<Components>
<c:Transform/>
</Components>
<Children>
<Entity>
<Components>
<c:Spawner>
<EntityFile>Schema/Entities/Player.xml</EntityFile>
</c:Spawner>
<c:Transform>
<Position X="11.2723322" Y="1.28011799" Z="3.66820574"/>
</c:Transform>
</Components>
<Children>
<Entity>
<Components>
<c:SpawnPoint/>
<c:Model>
<Resource>Models/Core/UnitSphere.obj</Resource>
</c:Model>
<c:Transform>
<Position X="0" Y="0" Z="1.26689196"/>
<Scale X="0.300000012" Y="0.300000012" Z="0.300000012"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:SpawnPoint/>
<c:Model>
<Resource>Models/Core/UnitSphere.obj</Resource>
</c:Model>
<c:Transform>
<Position X="0" Y="0" Z="-1.14786315"/>
<Scale X="0.300000012" Y="0.300000012" Z="0.300000012"/>
</c:Transform>
</Components>
<Children/>
</Entity>
</Children>
</Entity>
<Entity>
<Components>
<c:Camera/>
<c:Transform>
<Position X="-9.75645447" Y="12.7158976" Z="7.92630243"/>
<Orientation X="-0.757485211" Y="-1.44177103" Z="7.17310422e-06"/>
</c:Transform>
</Components>
<Children/>
</Entity>
</Children>
</Entity>
+3
View File
@@ -20,6 +20,9 @@
<xs:element ref="c:Trigger" minOccurs="0"/>
<xs:element ref="c:Health" minOccurs="0"/>
<xs:element ref="c:Collidable" minOccurs="0"/>
<xs:element ref="c:Spawner" minOccurs="0"/>
<xs:element ref="c:SpawnPoint" minOccurs="0"/>
<xs:element ref="c:PlayerSpawn" minOccurs="0"/>
</xs:all>
</xs:complexType>
</xs:element>
+5
View File
@@ -125,6 +125,11 @@ void World::SetParent(EntityID entity, EntityID parent)
m_EntityChildren.insert(std::make_pair(parent, entity));
}
const std::pair<std::unordered_multimap<EntityID, EntityID>::const_iterator, std::unordered_multimap<EntityID, EntityID>::const_iterator> World::GetChildren(EntityID entity)
{
return m_EntityChildren.equal_range(entity);
}
void World::SetName(EntityID entity, const std::string& name)
{
m_EntityNames[entity] = name;
+8 -1
View File
@@ -10,16 +10,23 @@ include_directories(
${Boost_INCLUDE_DIRS}
)
file(GLOB SOURCE_FILES
file(GLOB SOURCE_FILES_Systems
"${INCLUDE_PATH}/Systems/*.h"
"Systems/*.cpp"
)
source_group(Systems FILES ${SOURCE_FILES_Systems})
file(GLOB SOURCE_FILES_Events
"${INCLUDE_PATH}/Events/*.h"
"Events/*.cpp"
)
source_group(Events FILES ${SOURCE_FILES_Events})
set(SOURCE_FILES
${SOURCE_FILES}
"Game.cpp"
${SOURCE_FILES_Systems}
${SOURCE_FILES_Events}
)
set(LIBRARIES
+4
View File
@@ -6,6 +6,8 @@
#include "Systems/PlayerSystem.h"
#include "Systems/HealthSystem.h"
#include "Systems/PlayerMovementSystem.h"
#include "Systems/SpawnerSystem.h"
#include "Systems/PlayerSpawnSystem.h"
#include "Core/EntityFileWriter.h"
Game::Game(int argc, char* argv[])
@@ -73,6 +75,8 @@ Game::Game(int argc, char* argv[])
m_SystemPipeline->AddSystem<EditorSystem>(updateOrderLevel, m_Renderer);
m_SystemPipeline->AddSystem<HealthSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<PlayerMovementSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<SpawnerSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<PlayerSpawnSystem>(updateOrderLevel);
// Populate Octree with collidables
++updateOrderLevel;
m_SystemPipeline->AddSystem<CollidableOctreeSystem>(updateOrderLevel, m_OctreeCollision);
+39
View File
@@ -0,0 +1,39 @@
#include "Systems/PlayerSpawnSystem.h"
PlayerSpawnSystem::PlayerSpawnSystem(EventBroker* eventBroker)
: System(eventBroker)
{
EVENT_SUBSCRIBE_MEMBER(m_OnInputCommand, &PlayerSpawnSystem::OnInputCommand);
}
void PlayerSpawnSystem::Update(World* world, double dt)
{
auto componentPools = world->GetComponentPools();
auto spawnerPool = componentPools.find("Spawner");
if (spawnerPool == componentPools.end()) {
return;
}
;
for (auto& team : m_SpawnRequests) {
for (auto& spawner : *spawnerPool->second) {
Events::SpawnerSpawn e;
e.Spawner = EntityWrapper(world, spawner.EntityID);
m_EventBroker->Publish(e);
}
}
m_SpawnRequests.clear();
}
bool PlayerSpawnSystem::OnInputCommand(const Events::InputCommand& e)
{
if (e.Command != "PickTeam") {
return false;
}
if (e.Value != 0) {
m_SpawnRequests.push_back((int)e.Value);
}
return true;
}
+47
View File
@@ -0,0 +1,47 @@
#include "Systems/SpawnerSystem.h"
SpawnerSystem::SpawnerSystem(EventBroker* eventBroker) : System(eventBroker)
{
EVENT_SUBSCRIBE_MEMBER(m_OnSpawnerSpawn, &SpawnerSystem::OnSpawnerSpawn);
}
bool SpawnerSystem::OnSpawnerSpawn(Events::SpawnerSpawn& e)
{
EntityWrapper& spawner = e.Spawner;
auto children = spawner.World->GetChildren(spawner.ID);
std::vector<EntityID> spawnPoints;
for (auto kv = children.first; kv != children.second; ++kv) {
const EntityID& child = kv->second;
if (spawner.World->HasComponent(child, "SpawnPoint")) {
spawnPoints.push_back(child);
}
}
EntityID spawnPoint = spawner.ID;
if (!spawnPoints.empty()) {
// Select a random spawn point
static std::random_device randomDevice;
static std::mt19937 randomGenerator(randomDevice());
std::uniform_int_distribution<> distribution(0, std::distance(spawnPoints.begin(), spawnPoints.end()) - 1);
auto randomSpawnPointIt = spawnPoints.begin();
std::advance(randomSpawnPointIt, distribution(randomGenerator));
spawnPoint = *randomSpawnPointIt;
}
spawnEntity(spawner, e.Parent.ID, Transform::AbsolutePosition(spawner.World, spawnPoint));
return true;
}
void SpawnerSystem::spawnEntity(EntityWrapper spawner, EntityID parent, glm::vec3 position)
{
const std::string& entityFilePath = spawner["Spawner"]["EntityFile"];
auto entityFile = ResourceManager::Load<EntityFile>(entityFilePath);
if (entityFile == nullptr) {
return;
}
EntityFileParser parser(entityFile);
EntityWrapper spawnedEntity(spawner.World, parser.MergeEntities(spawner.World, parent));
spawnedEntity["Transform"]["Position"] = position;
}