Merge remote-tracking branch 'origin/master' into Forward+
# Conflicts: # resources/Schema/Types/Entity.xsd
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
#ifndef EPlayerDamage_h__
|
||||
#define EPlayerDamage_h__
|
||||
|
||||
#include "EventBroker.h"
|
||||
#include "../Core/Entity.h"
|
||||
|
||||
namespace Events
|
||||
{
|
||||
|
||||
struct PlayerDamage : Event
|
||||
{
|
||||
double DamageAmount;
|
||||
EntityID PlayerDamagedID;
|
||||
//optional TypeOfDamage
|
||||
std::string TypeOfDamage;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef EPlayerDeath_h__
|
||||
#define EPlayerDeath_h__
|
||||
|
||||
#include "EventBroker.h"
|
||||
#include "../Core/Entity.h"
|
||||
|
||||
namespace Events
|
||||
{
|
||||
|
||||
struct PlayerDeath : Event
|
||||
{
|
||||
//KilledBy,KilledByWhat is optional for now. It might be used later in the playerlog-system
|
||||
EntityID KilledBy;
|
||||
EntityID PlayerID;
|
||||
std::string KilledByWhat;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifndef EPlayerHealthPickup_h__
|
||||
#define EPlayerHealthPickup_h__
|
||||
|
||||
#include "EventBroker.h"
|
||||
#include "../Core/Entity.h"
|
||||
|
||||
namespace Events
|
||||
{
|
||||
|
||||
struct PlayerHealthPickup : Event
|
||||
{
|
||||
double HealthAmount;
|
||||
EntityID PlayerHealedID;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -13,6 +13,8 @@
|
||||
relay = decltype(relay)(std::bind(handler, this, std::placeholders::_1)); \
|
||||
m_EventBroker->Subscribe(relay);
|
||||
|
||||
typedef unsigned int EventID;
|
||||
|
||||
class EventBroker;
|
||||
|
||||
class BaseEventRelay
|
||||
@@ -31,6 +33,7 @@ public:
|
||||
virtual bool Receive(const std::shared_ptr<Event> event) = 0;
|
||||
|
||||
protected:
|
||||
EventID m_EventID;
|
||||
std::string m_ContextTypeName;
|
||||
std::string m_EventTypeName;
|
||||
EventBroker* m_Broker;
|
||||
@@ -95,6 +98,7 @@ public:
|
||||
|
||||
private:
|
||||
bool m_IsProcessing = false;
|
||||
EventID m_NextEventID = 0;
|
||||
|
||||
typedef std::string ContextTypeName_t; // typeid(ContextType).name()
|
||||
typedef std::string EventTypeName_t; // typeid(EventType).name()
|
||||
@@ -103,14 +107,14 @@ private:
|
||||
typedef std::unordered_map<ContextTypeName_t, EventRelays_t> ContextRelays_t;
|
||||
ContextRelays_t m_ContextRelays;
|
||||
std::vector<BaseEventRelay*> m_RelaysToSubscribe;
|
||||
std::vector<BaseEventRelay*> m_RelaysToUnsubscribe;
|
||||
std::vector<std::tuple<EventID, ContextTypeName_t, EventTypeName_t>> m_RelaysToUnsubscribe;
|
||||
|
||||
typedef std::list<std::pair<EventTypeName_t, std::shared_ptr<Event>>> EventQueue_t;
|
||||
std::shared_ptr<EventQueue_t> m_EventQueueRead;
|
||||
std::shared_ptr<EventQueue_t> m_EventQueueWrite;
|
||||
|
||||
void subscribeImmediate(BaseEventRelay& relay);
|
||||
void unsubscribeImmediate(BaseEventRelay& relay);
|
||||
void unsubscribeImmediate(std::tuple<EventID, ContextTypeName_t, EventTypeName_t> identifier);
|
||||
};
|
||||
|
||||
template <typename EventType>
|
||||
|
||||
@@ -14,21 +14,28 @@ public:
|
||||
{ }
|
||||
~SystemPipeline()
|
||||
{
|
||||
for (auto& pair : m_Systems) {
|
||||
delete pair.second;
|
||||
for (UnorderedSystems& group : m_OrderedSystemGroups) {
|
||||
for (auto& pair : group.Systems) {
|
||||
delete pair.second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename... Arguments>
|
||||
void AddSystem(Arguments... args)
|
||||
//All systems with orderlevel 0 will be updated first, then 1, 2, etc.
|
||||
void AddSystem(int updateOrderLevel, Arguments... args)
|
||||
{
|
||||
if (updateOrderLevel + 1 > m_OrderedSystemGroups.size()) {
|
||||
m_OrderedSystemGroups.resize(updateOrderLevel + 1);
|
||||
}
|
||||
UnorderedSystems& group = m_OrderedSystemGroups[updateOrderLevel];
|
||||
System* system = new T(m_EventBroker, args...);
|
||||
m_Systems[typeid(T).name()] = system;
|
||||
group.Systems[typeid(T).name()] = system;
|
||||
|
||||
if (std::is_base_of<PureSystem, T>::value) {
|
||||
PureSystem* pureSystem = static_cast<PureSystem*>(system);
|
||||
if (!pureSystem->m_ComponentType.empty()) {
|
||||
m_PureSystems[pureSystem->m_ComponentType].push_back(pureSystem);
|
||||
group.PureSystems[pureSystem->m_ComponentType].push_back(pureSystem);
|
||||
} else {
|
||||
LOG_ERROR("Failed to add pure system \"%s\": Missing component type!", typeid(T).name());
|
||||
}
|
||||
@@ -36,41 +43,47 @@ public:
|
||||
|
||||
if (std::is_base_of<ImpureSystem, T>::value) {
|
||||
ImpureSystem* impureSystem = static_cast<ImpureSystem*>(system);
|
||||
m_ImpureSystems.push_back(impureSystem);
|
||||
group.ImpureSystems.push_back(impureSystem);
|
||||
}
|
||||
}
|
||||
|
||||
void Update(World* world, double dt)
|
||||
{
|
||||
// Process events
|
||||
for (auto& pair : m_Systems) {
|
||||
m_EventBroker->Process(pair.first);
|
||||
}
|
||||
|
||||
// Update
|
||||
for (auto& pair : m_PureSystems) {
|
||||
const std::string& componentName = pair.first;
|
||||
auto& systems = pair.second;
|
||||
const ComponentPool* pool = world->GetComponents(componentName);
|
||||
if (pool == nullptr) {
|
||||
continue;
|
||||
for (UnorderedSystems& group : m_OrderedSystemGroups) {
|
||||
// Process events
|
||||
for (auto& pair : group.Systems) {
|
||||
m_EventBroker->Process(pair.first);
|
||||
}
|
||||
for (auto& component : *pool) {
|
||||
for (auto& system : systems) {
|
||||
system->UpdateComponent(world, component, dt);
|
||||
|
||||
// Update
|
||||
for (auto& pair : group.PureSystems) {
|
||||
const std::string& componentName = pair.first;
|
||||
auto& systems = pair.second;
|
||||
const ComponentPool* pool = world->GetComponents(componentName);
|
||||
if (pool == nullptr) {
|
||||
continue;
|
||||
}
|
||||
for (auto& component : *pool) {
|
||||
for (auto& system : systems) {
|
||||
system->UpdateComponent(world, component, dt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto& system : m_ImpureSystems) {
|
||||
system->Update(world, dt);
|
||||
for (auto& system : group.ImpureSystems) {
|
||||
system->Update(world, dt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
EventBroker* m_EventBroker;
|
||||
std::map<std::string, System*> m_Systems;
|
||||
std::map<std::string, std::vector<PureSystem*>> m_PureSystems;
|
||||
std::vector<ImpureSystem*> m_ImpureSystems;
|
||||
struct UnorderedSystems
|
||||
{
|
||||
std::map<std::string, System*> Systems;
|
||||
std::map<std::string, std::vector<PureSystem*>> PureSystems;
|
||||
std::vector<ImpureSystem*> ImpureSystems;
|
||||
};
|
||||
std::vector<UnorderedSystems> m_OrderedSystemGroups;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef HealthSystem_h__
|
||||
#define HealthSystem_h__
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <glm/common.hpp>
|
||||
|
||||
#include "Common.h"
|
||||
#include "Core/System.h"
|
||||
#include "Core\EPlayerDamage.h";
|
||||
#include "Core\EPlayerHealthPickup.h";
|
||||
#include "Core\EPlayerDeath.h";
|
||||
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
class HealthSystem : public PureSystem
|
||||
{
|
||||
public:
|
||||
HealthSystem(EventBroker* eventBroker);
|
||||
|
||||
//updatecomponent
|
||||
virtual void UpdateComponent(World* world, ComponentWrapper& health, double dt) override;
|
||||
|
||||
private:
|
||||
//methods which will take care of specific events
|
||||
EventRelay<HealthSystem, Events::PlayerDamage> m_EPlayerDamage;
|
||||
bool HealthSystem::OnPlayerDamaged(const Events::PlayerDamage& e);
|
||||
EventRelay<HealthSystem, Events::PlayerHealthPickup> m_EPlayerHealthPickup;
|
||||
bool HealthSystem::OnPlayerHealthPickup(const Events::PlayerHealthPickup& e);
|
||||
|
||||
//vector which will keep track of health changes
|
||||
std::vector<std::tuple<EntityID, double>> m_DeltaHealthVector;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -9,4 +9,5 @@
|
||||
<xs:include schemaLocation="Components/AABB.xsd"/>
|
||||
<xs:include schemaLocation="Components/PointLight.xsd"/>
|
||||
<xs:include schemaLocation="Components/Trigger.xsd"/>
|
||||
<xs:include schemaLocation="Components/Health.xsd"/>
|
||||
</xs:schema>
|
||||
@@ -0,0 +1,4 @@
|
||||
<c:Health>
|
||||
<Health>100</Health>
|
||||
<MaxHealth>100</MaxHealth>
|
||||
</c:Health>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?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="Health">
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
<xs:element name="Health" type="t:double" minOccurs="0"/>
|
||||
<xs:element name="MaxHealth" type="t:double" minOccurs="0"/>
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
||||
@@ -15,6 +15,7 @@
|
||||
<xs:element ref="c:Test" minOccurs="0"/>
|
||||
<xs:element ref="c:RaptorCopter" minOccurs="0"/>
|
||||
<xs:element ref="c:Player" minOccurs="0"/>
|
||||
<xs:element ref="c:Health" minOccurs="0"/>
|
||||
<xs:element ref="c:PointLight" minOccurs="0"/>
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
void CollisionSystem::UpdateComponent(World * world, ComponentWrapper & cAABB, double dt)
|
||||
{
|
||||
//TODO: Update CollisionSystem system after PlayerSystem.
|
||||
|
||||
//Right now, cAABB is a component attached to any entity that should be collideable.
|
||||
AABB thisBox;
|
||||
if (!Collision::GetEntityBox(world, cAABB, thisBox)) {
|
||||
|
||||
@@ -2,21 +2,24 @@
|
||||
|
||||
BaseEventRelay::~BaseEventRelay()
|
||||
{
|
||||
if (m_Broker != nullptr) {
|
||||
if (m_Broker != nullptr) {
|
||||
m_Broker->Unsubscribe(*this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EventBroker::Unsubscribe(BaseEventRelay &relay) // ?
|
||||
void EventBroker::Unsubscribe(BaseEventRelay& relay) // ?
|
||||
{
|
||||
if (m_IsProcessing) {
|
||||
m_RelaysToUnsubscribe.push_back(&relay);
|
||||
} else {
|
||||
unsubscribeImmediate(relay);
|
||||
}
|
||||
auto identifier = std::make_tuple(relay.m_EventID, relay.m_ContextTypeName, relay.m_EventTypeName);
|
||||
|
||||
relay.m_Broker = nullptr;
|
||||
if (m_IsProcessing) {
|
||||
m_RelaysToUnsubscribe.push_back(identifier);
|
||||
} else {
|
||||
unsubscribeImmediate(identifier);
|
||||
}
|
||||
}
|
||||
|
||||
void EventBroker::Subscribe(BaseEventRelay &relay)
|
||||
void EventBroker::Subscribe(BaseEventRelay& relay)
|
||||
{
|
||||
if (m_IsProcessing) {
|
||||
m_RelaysToSubscribe.push_back(&relay);
|
||||
@@ -38,12 +41,11 @@ int EventBroker::Process(std::string contextTypeName)
|
||||
|
||||
int eventsProcessed = 0;
|
||||
for (auto &pair : *m_EventQueueRead) {
|
||||
std::string &eventTypeName = pair.first;
|
||||
std::string& eventTypeName = pair.first;
|
||||
std::shared_ptr<Event> event = pair.second;
|
||||
|
||||
auto itpair = relays.equal_range(eventTypeName);
|
||||
for (auto it2 = itpair.first; it2 != itpair.second; it2++)
|
||||
{
|
||||
for (auto it2 = itpair.first; it2 != itpair.second; it2++) {
|
||||
std::string name = it2->first;
|
||||
BaseEventRelay* relay = it2->second;
|
||||
relay->Receive(event);
|
||||
@@ -60,8 +62,8 @@ int EventBroker::Process(std::string contextTypeName)
|
||||
m_RelaysToSubscribe.clear();
|
||||
|
||||
// Process pending unsubscriptions
|
||||
for (auto& r : m_RelaysToUnsubscribe) {
|
||||
unsubscribeImmediate(*r);
|
||||
for (auto& identifier : m_RelaysToUnsubscribe) {
|
||||
unsubscribeImmediate(identifier);
|
||||
}
|
||||
m_RelaysToUnsubscribe.clear();
|
||||
|
||||
@@ -81,21 +83,26 @@ void EventBroker::Clear()
|
||||
void EventBroker::subscribeImmediate(BaseEventRelay& relay)
|
||||
{
|
||||
relay.m_Broker = this;
|
||||
relay.m_EventID = m_NextEventID++;
|
||||
m_ContextRelays[relay.m_ContextTypeName].insert(std::make_pair(relay.m_EventTypeName, &relay));
|
||||
}
|
||||
|
||||
void EventBroker::unsubscribeImmediate(BaseEventRelay& relay)
|
||||
void EventBroker::unsubscribeImmediate(std::tuple<EventID, ContextTypeName_t, EventTypeName_t> identifier)
|
||||
{
|
||||
auto contextIt = m_ContextRelays.find(relay.m_ContextTypeName);
|
||||
EventID eventID;
|
||||
ContextTypeName_t contextTypeName;
|
||||
EventTypeName_t eventTypeName;
|
||||
std::tie(eventID, contextTypeName, eventTypeName) = identifier;
|
||||
|
||||
auto contextIt = m_ContextRelays.find(contextTypeName);
|
||||
if (contextIt == m_ContextRelays.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto eventRelays = contextIt->second;
|
||||
auto itpair = eventRelays.equal_range(relay.m_EventTypeName);
|
||||
auto itpair = eventRelays.equal_range(eventTypeName);
|
||||
for (auto it = itpair.first; it != itpair.second; ++it) {
|
||||
if (it->second == &relay) {
|
||||
relay.m_Broker = nullptr;
|
||||
if (it->second->m_EventID == eventID) {
|
||||
eventRelays.erase(it);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ file(GLOB SOURCE_FILES
|
||||
set(SOURCE_FILES
|
||||
${SOURCE_FILES}
|
||||
"Game.cpp"
|
||||
"HealthSystem.cpp"
|
||||
"PlayerSystem.cpp"
|
||||
)
|
||||
|
||||
|
||||
+14
-6
@@ -1,6 +1,7 @@
|
||||
#include "Game.h"
|
||||
#include "Collision/TriggerSystem.h"
|
||||
#include "Collision/CollisionSystem.h"
|
||||
#include "Game/HealthSystem.h"
|
||||
|
||||
Game::Game(int argc, char* argv[])
|
||||
{
|
||||
@@ -27,7 +28,7 @@ Game::Game(int argc, char* argv[])
|
||||
0,
|
||||
m_Config->Get<int>("Video.Width", 1280),
|
||||
m_Config->Get<int>("Video.Height", 720)
|
||||
));
|
||||
));
|
||||
m_Renderer->Initialize();
|
||||
m_Renderer->Camera()->SetFOV(glm::radians(m_Config->Get<float>("Video.FOV", 90.f)));
|
||||
|
||||
@@ -52,11 +53,18 @@ Game::Game(int argc, char* argv[])
|
||||
|
||||
// Create system pipeline
|
||||
m_SystemPipeline = new SystemPipeline(m_EventBroker);
|
||||
m_SystemPipeline->AddSystem<RaptorCopterSystem>();
|
||||
m_SystemPipeline->AddSystem<PlayerSystem>();
|
||||
m_SystemPipeline->AddSystem<EditorSystem>(m_Renderer);
|
||||
m_SystemPipeline->AddSystem<CollisionSystem>();
|
||||
m_SystemPipeline->AddSystem<TriggerSystem>();
|
||||
|
||||
//All systems with orderlevel 0 will be updated first.
|
||||
unsigned int updateOrderLevel = 0;
|
||||
m_SystemPipeline->AddSystem<RaptorCopterSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<PlayerSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<EditorSystem>(updateOrderLevel, m_Renderer);
|
||||
m_SystemPipeline->AddSystem<HealthSystem>(updateOrderLevel);
|
||||
|
||||
//Collision and TriggerSystem should update after player.
|
||||
++updateOrderLevel;
|
||||
m_SystemPipeline->AddSystem<CollisionSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<TriggerSystem>(updateOrderLevel);
|
||||
|
||||
// Invoke network
|
||||
if (m_Config->Get<bool>("Networking.StartNetwork", false)) {
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
#include "HealthSystem.h"
|
||||
#include <algorithm>
|
||||
|
||||
HealthSystem::HealthSystem(EventBroker* eventBroker)
|
||||
: PureSystem(eventBroker, "Health")
|
||||
{
|
||||
//subscribe/listenTo playerdamage,healthpickup events (using the eventBroker)
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EPlayerDamage, &HealthSystem::OnPlayerDamaged);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EPlayerHealthPickup, &HealthSystem::OnPlayerHealthPickup);
|
||||
}
|
||||
|
||||
void HealthSystem::UpdateComponent(World *world, ComponentWrapper &health, double dt)
|
||||
{
|
||||
//if entityID of health is 9 then the players ID is also 9 (player,health are connected to the same entity)
|
||||
ComponentWrapper player = world->GetComponent(health.EntityID, "Player");
|
||||
double maxHealth = (double)health["MaxHealth"];
|
||||
|
||||
//process the DeltaHealthVector and change the entitys health accordingly
|
||||
for (size_t i = m_DeltaHealthVector.size(); i > 0; i--)
|
||||
{
|
||||
auto deltaHP = m_DeltaHealthVector[i - 1];
|
||||
//if we have a healthchange for the current player and health is greater than 0, then apply it
|
||||
if (std::get<0>(deltaHP) == player.EntityID && (double)health["Health"] > 0.0f) {
|
||||
//get the deltaHP value from the tuple and make sure you dont get more than maxHealth
|
||||
double newHealth = std::min((double)health["Health"] + (double)std::get<1>(deltaHP), maxHealth);
|
||||
health["Health"] = newHealth;
|
||||
m_DeltaHealthVector.erase(m_DeltaHealthVector.begin() + i - 1);
|
||||
//check if health is <= 0
|
||||
if ((double)health["Health"] <= 0.0f) {
|
||||
//publish death event
|
||||
Events::PlayerDeath e;
|
||||
e.PlayerID = player.EntityID;
|
||||
m_EventBroker->Publish(e);
|
||||
//clear the remaining hpDeltas for the dead player
|
||||
for (size_t j = m_DeltaHealthVector.size(); j > 0; j--)
|
||||
{
|
||||
if (std::get<0>(m_DeltaHealthVector[j - 1]) == player.EntityID)
|
||||
m_DeltaHealthVector.erase(m_DeltaHealthVector.begin() + j - 1);
|
||||
}
|
||||
//break the loop if the player is dead
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool HealthSystem::OnPlayerDamaged(const Events::PlayerDamage& e)
|
||||
{
|
||||
//save the changed HP to a vector. it will be taken care of in UpdateComponent
|
||||
m_DeltaHealthVector.push_back(std::make_tuple(e.PlayerDamagedID, -e.DamageAmount));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HealthSystem::OnPlayerHealthPickup(const Events::PlayerHealthPickup& e)
|
||||
{
|
||||
//save the changed HP to a vector. it will be taken care of in UpdateComponent
|
||||
m_DeltaHealthVector.push_back(std::make_tuple(e.PlayerHealedID, e.HealthAmount));
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/test/execution_monitor.hpp>
|
||||
using boost::unit_test_framework::test_suite;
|
||||
using boost::unit_test_framework::test_case;
|
||||
#include <stdlib.h>//srand
|
||||
|
||||
//#define private public
|
||||
#include "Engine\Core\ConfigFile.h"
|
||||
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <crtdbg.h>
|
||||
#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__)
|
||||
#define new DEBUG_CLIENTBLOCK
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(confTest)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(configFileTest)
|
||||
{
|
||||
//note: this ConfigFileclass currently has memleaks!
|
||||
|
||||
ResourceManager::RegisterType<ConfigFile>("ConfigFile");
|
||||
auto m_Config = ResourceManager::Load<ConfigFile>("ConfigTest.ini");
|
||||
|
||||
//bägge måste vara av samma typ, T typen är string
|
||||
//http://www.boost.org/doc/libs/1_42_0/doc/html/boost_propertytree/tutorial.html
|
||||
//"Note that we construct the path to the value by separating the individual keys with dots"
|
||||
|
||||
//get from tree tests
|
||||
auto getSomething = m_Config->Get("Test.Test1", 0);
|
||||
BOOST_CHECK(getSomething == 423);
|
||||
|
||||
auto getSomething2 = m_Config->Get("fsdfdsfd.T", std::string(""));
|
||||
BOOST_CHECK(getSomething2 == "\"gfdjakflsdl!\"");
|
||||
|
||||
//set/get tests
|
||||
m_Config->Set("Test.4321", 123);
|
||||
auto getSomething3 = m_Config->Get("Test.4321", 0);
|
||||
BOOST_CHECK(getSomething3 == 123);
|
||||
|
||||
m_Config->Set("3_2_1_0_5", "t454j54hj5k32");
|
||||
auto getSomething4 = m_Config->Get("3_2_1_0_5", std::string(""));
|
||||
BOOST_CHECK(getSomething4 == "t454j54hj5k32");
|
||||
|
||||
//***check so outputwindow says: EE: Failed to find "DefaultConfigTestNotExists.ini"! Relying on hardcoded default values!
|
||||
auto m_Config2 = ResourceManager::Load<ConfigFile>("ConfigTestNotExists.ini");
|
||||
|
||||
//set value/savetodisk/load/checkvalue...
|
||||
m_Config->SaveToDisk();
|
||||
m_Config->Set("Test.4321", 145);
|
||||
m_Config->SaveToDisk();
|
||||
auto m_Config3 = ResourceManager::Load<ConfigFile>("ConfigTest.ini");
|
||||
auto getSomething5 = m_Config->Get("Test.4321", 0);
|
||||
BOOST_CHECK(getSomething5 == 145);
|
||||
|
||||
//***check so outputwindow says: EE: Failed to parse "DefaultConfigTestFailed.ini"
|
||||
//***check so outputwindow says: EE: Failed to parse "ConfigTestFailed.ini":
|
||||
auto m_Config4 = ResourceManager::Load<ConfigFile>("ConfigTestFailed.ini");
|
||||
|
||||
//reload,onchildreload unimplemented
|
||||
|
||||
//NOTE:still massive amount of memoryleaks from this method
|
||||
_CrtDumpMemoryLeaks();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
#ifndef EVENTFIXTURE_H
|
||||
#define EVENTFIXTURE_H
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include "Core\EventBroker.h"
|
||||
|
||||
template <typename EventType>
|
||||
struct EventFixture
|
||||
{
|
||||
EventFixture()
|
||||
{
|
||||
this->ventBroker = new EventBroker();
|
||||
m_EEventType = decltype(m_EEventType)(std::bind(&EventFixture::OnEvent, this, std::placeholders::_1));
|
||||
this->ventBroker->Subscribe(m_EEventType);
|
||||
Run();
|
||||
Check();
|
||||
}
|
||||
~EventFixture()
|
||||
{
|
||||
this->ventBroker->Unsubscribe(m_EEventType);
|
||||
delete this->ventBroker;
|
||||
}
|
||||
|
||||
EventBroker* ventBroker = nullptr;
|
||||
EventRelay<EventFixture, EventType> m_EEventType;
|
||||
bool m_EventRecieved = false;
|
||||
EventType Before;
|
||||
EventType After;
|
||||
|
||||
bool OnEvent(const EventType& event)
|
||||
{
|
||||
m_EventRecieved = true;
|
||||
After = event;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Run()
|
||||
{
|
||||
// Publish the event
|
||||
this->ventBroker->Publish(Before);
|
||||
// Clear to swap buffers
|
||||
this->ventBroker->Swap();
|
||||
// Process the event
|
||||
this->ventBroker->template Process<EventFixture>();
|
||||
}
|
||||
|
||||
void Check()
|
||||
{
|
||||
BOOST_CHECK(m_EventRecieved);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,19 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include "EventFixture.h"
|
||||
|
||||
struct ETestEvent : public Event
|
||||
{
|
||||
int Int = 5;
|
||||
float Float = 1.33333f;
|
||||
double Double = 1.33333;
|
||||
std::string String = "Hello World";
|
||||
};
|
||||
|
||||
BOOST_AUTO_TEST_CASE(EventBrokerTest)
|
||||
{
|
||||
EventFixture<ETestEvent> f;
|
||||
BOOST_CHECK(f.Before.Int == f.After.Int);
|
||||
BOOST_CHECK_CLOSE(f.Before.Float, f.After.Float, 0.00001f);
|
||||
BOOST_CHECK_CLOSE(f.Before.Double, f.After.Double, 0.00001f);
|
||||
BOOST_CHECK(f.Before.String == f.After.String);
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
using boost::unit_test_framework::test_suite;
|
||||
using boost::unit_test_framework::test_case;
|
||||
|
||||
#include "HealthSystemTest.h"
|
||||
#include "Game/HealthSystem.h"
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(HealthSystemSuite)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(HealthSystemTest)
|
||||
{
|
||||
//this tests 2 healthevents and the healthsystem
|
||||
GameHealthSystemTest game;
|
||||
//100 loops will be more than enough to do the test
|
||||
int loops = 100;
|
||||
bool success = false;
|
||||
while (loops > 0) {
|
||||
game.Tick();
|
||||
if (game.TestSucceeded) {
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
loops--;
|
||||
}
|
||||
//The system will process the events, hence it will take a while before we can read anything
|
||||
BOOST_TEST(success);
|
||||
}
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
GameHealthSystemTest::GameHealthSystemTest()
|
||||
{
|
||||
ResourceManager::RegisterType<ConfigFile>("ConfigFile");
|
||||
ResourceManager::RegisterType<EntityXMLFile>("EntityXMLFile");
|
||||
|
||||
m_Config = ResourceManager::Load<ConfigFile>("Config.ini");
|
||||
LOG_LEVEL = static_cast<_LOG_LEVEL>(m_Config->Get<int>("Debug.LogLevel", 1));
|
||||
|
||||
// Create the core event broker
|
||||
m_EventBroker = new EventBroker();
|
||||
|
||||
// Create a world
|
||||
m_World = new World();
|
||||
std::string mapToLoad = m_Config->Get<std::string>("Debug.LoadMap", "");
|
||||
if (!mapToLoad.empty()) {
|
||||
ResourceManager::Load<EntityXMLFile>(mapToLoad)->PopulateWorld(m_World);
|
||||
}
|
||||
|
||||
// Create system pipeline
|
||||
m_SystemPipeline = new SystemPipeline(m_EventBroker);
|
||||
m_SystemPipeline->AddSystem<PlayerSystem>(0);
|
||||
m_SystemPipeline->AddSystem<HealthSystem>(0);
|
||||
|
||||
//The Test
|
||||
//create entity which has transorm,player,model,health in it. i.e. is a player
|
||||
EntityID playerID = m_World->CreateEntity();
|
||||
ComponentWrapper transform = m_World->AttachComponent(playerID, "Transform");
|
||||
ComponentWrapper model = m_World->AttachComponent(playerID, "Model");
|
||||
model["Resource"] = "Models/Core/UnitSphere.obj";
|
||||
ComponentWrapper player = m_World->AttachComponent(playerID, "Player");
|
||||
ComponentWrapper health = m_World->AttachComponent(playerID, "Health");
|
||||
healthsID = playerID;
|
||||
double currentHealth = (double)m_World->GetComponent(healthsID, "Health")["Health"];
|
||||
|
||||
//heal player with 40
|
||||
Events::PlayerHealthPickup e3;
|
||||
e3.HealthAmount = 40.0f;
|
||||
e3.PlayerHealedID = healthsID;
|
||||
m_EventBroker->Publish(e3);
|
||||
//damage player with 50
|
||||
Events::PlayerDamage e;
|
||||
e.DamageAmount = 50.0f;
|
||||
e.PlayerDamagedID = healthsID;
|
||||
m_EventBroker->Publish(e);
|
||||
//heal some other player with 40
|
||||
Events::PlayerHealthPickup e2;
|
||||
e2.HealthAmount = 40.0f;
|
||||
e2.PlayerHealedID = healthsID+1;
|
||||
m_EventBroker->Publish(e2);
|
||||
|
||||
EntityID playerID2 = m_World->CreateEntity();
|
||||
ComponentWrapper transform2 = m_World->AttachComponent(playerID2, "Transform");
|
||||
ComponentWrapper model2 = m_World->AttachComponent(playerID2, "Model");
|
||||
model2["Resource"] = "Models/Core/UnitSphere.obj";
|
||||
ComponentWrapper player2 = m_World->AttachComponent(playerID2, "Player");
|
||||
ComponentWrapper health2 = m_World->AttachComponent(playerID2, "Health");
|
||||
//END TEST
|
||||
}
|
||||
|
||||
GameHealthSystemTest::~GameHealthSystemTest()
|
||||
{
|
||||
delete m_SystemPipeline;
|
||||
delete m_World;
|
||||
delete m_EventBroker;
|
||||
}
|
||||
|
||||
void GameHealthSystemTest::Tick()
|
||||
{
|
||||
glfwPollEvents();
|
||||
|
||||
double currentTime = glfwGetTime();
|
||||
double dt = currentTime - m_LastTime;
|
||||
m_LastTime = currentTime;
|
||||
|
||||
// Iterate through systems and update world!
|
||||
m_SystemPipeline->Update(m_World, dt);
|
||||
|
||||
m_EventBroker->Swap();
|
||||
m_EventBroker->Clear();
|
||||
|
||||
//if health reaches 90 then we know the test has succeeded (start with 100hp, remove 50hp, add 40hp)
|
||||
double currentHealth = (double)m_World->GetComponent(healthsID, "Health")["Health"];
|
||||
if (currentHealth==90)
|
||||
TestSucceeded = true;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#ifndef HealthTest_h__
|
||||
#define HealthTest_h__
|
||||
|
||||
#include "Core/ResourceManager.h"
|
||||
#include "Core/ConfigFile.h"
|
||||
#include "Core/EventBroker.h"
|
||||
#include "Rendering/Renderer.h"
|
||||
#include "Core/InputManager.h"
|
||||
#include "GUI/Frame.h"
|
||||
#include "Core/World.h"
|
||||
#include "Rendering/RenderQueueFactory.h"
|
||||
#include "Input/InputProxy.h"
|
||||
#include "Input/KeyboardInputHandler.h"
|
||||
#include "Input/MouseInputHandler.h"
|
||||
#include "Core/EKeyDown.h"
|
||||
#include "Core/EntityXMLFile.h"
|
||||
#include "Core/SystemPipeline.h"
|
||||
#include "RaptorCopterSystem.h"
|
||||
#include "PlayerSystem.h"
|
||||
#include "Editor/EditorSystem.h"
|
||||
|
||||
class GameHealthSystemTest
|
||||
{
|
||||
public:
|
||||
GameHealthSystemTest();
|
||||
~GameHealthSystemTest();
|
||||
|
||||
void Tick();
|
||||
bool TestSucceeded = false;
|
||||
|
||||
private:
|
||||
double m_LastTime;
|
||||
ConfigFile* m_Config = nullptr;
|
||||
EventBroker* m_EventBroker;
|
||||
World* m_World;
|
||||
SystemPipeline* m_SystemPipeline;
|
||||
int healthsID;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,12 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include "Engine\Core\InputManager.h"
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(inputManagerTests)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(inputManagerTest)
|
||||
{
|
||||
//already tested eventbroker so inputManager is indirectly already tested
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
@@ -34,16 +34,12 @@ BOOST_AUTO_TEST_CASE(octTreeTest)
|
||||
BOOST_CHECK(someAABB.MaxCorner() == maxCorner);
|
||||
BOOST_CHECK(someAABB.Center() == 0.5f * (minCorner + maxCorner));
|
||||
|
||||
//simple OctTree constructor check
|
||||
//OctTree someOctTree(someAABB, 5);
|
||||
//BOOST_CHECK(someOctTree.m_Children[0] != nullptr);
|
||||
|
||||
//simple destructor check in the end, just look for memleaks, then it didnt clear the AABB structure
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(octTreeTest2)
|
||||
{
|
||||
//octtree ritningen osv
|
||||
//octtree draw etc
|
||||
Game game(0, nullptr);
|
||||
while (game.Running()) {
|
||||
game.Tick();
|
||||
|
||||
@@ -5,6 +5,8 @@ Game::Game(int argc, char* argv[]) : someOctTree(AABB(-0.5f*worldSize, 0.5f*worl
|
||||
ResourceManager::RegisterType<ConfigFile>("ConfigFile");
|
||||
ResourceManager::RegisterType<Model>("Model");
|
||||
ResourceManager::RegisterType<Texture>("Texture");
|
||||
ResourceManager::RegisterType<EntityXMLFile>("EntityXMLFile");
|
||||
ResourceManager::RegisterType<ShaderProgram>("ShaderProgram");
|
||||
|
||||
m_Config = ResourceManager::Load<ConfigFile>("Config.ini");
|
||||
LOG_LEVEL = static_cast<_LOG_LEVEL>(m_Config->Get<int>("Debug.LogLevel", 1));
|
||||
@@ -25,9 +27,14 @@ Game::Game(int argc, char* argv[]) : someOctTree(AABB(-0.5f*worldSize, 0.5f*worl
|
||||
m_Config->Get<int>("Video.Height", 720)
|
||||
));
|
||||
m_Renderer->Initialize();
|
||||
m_Renderer->Camera()->SetFOV(glm::radians(m_Config->Get<float>("Video.FOV", 90.f)));
|
||||
|
||||
// Create input manager
|
||||
m_InputManager = new InputManager(m_Renderer->Window(), m_EventBroker);
|
||||
m_InputProxy = new InputProxy(m_EventBroker);
|
||||
m_InputProxy->AddHandler<KeyboardInputHandler>();
|
||||
m_InputProxy->AddHandler<MouseInputHandler>();
|
||||
m_InputProxy->LoadBindings("Input.ini");
|
||||
|
||||
// Create the root level GUI frame
|
||||
m_FrameStack = new GUI::Frame(m_EventBroker);
|
||||
@@ -37,6 +44,9 @@ Game::Game(int argc, char* argv[]) : someOctTree(AABB(-0.5f*worldSize, 0.5f*worl
|
||||
// Create a TEST WORLD
|
||||
m_World = new HardcodedTestWorld();
|
||||
|
||||
m_SystemPipeline = new SystemPipeline(m_EventBroker);
|
||||
m_SystemPipeline->AddSystem<PlayerSystem>(0);
|
||||
|
||||
m_LastTime = glfwGetTime();
|
||||
}
|
||||
|
||||
@@ -52,9 +62,14 @@ void Game::Tick()
|
||||
double dt = currentTime - m_LastTime;
|
||||
m_LastTime = currentTime;
|
||||
|
||||
// Handle input in a weird looking but responsive way
|
||||
m_EventBroker->Process<InputManager>();
|
||||
m_EventBroker->Swap();
|
||||
m_InputManager->Update(dt);
|
||||
m_Renderer->Update(dt);
|
||||
m_EventBroker->Swap();
|
||||
m_InputProxy->Update(dt);
|
||||
m_EventBroker->Swap();
|
||||
m_InputProxy->Process();
|
||||
m_EventBroker->Swap();
|
||||
|
||||
#define TEST1
|
||||
@@ -70,7 +85,7 @@ void Game::Tick()
|
||||
AABB boxi;
|
||||
boxi.CreateFromCenter(pos, maxPos - minPos);
|
||||
frameCounter++;
|
||||
if (frameCounter > 50) {
|
||||
if (frameCounter > 1) {
|
||||
m_World->someOctTree.ClearDynamicObjects();
|
||||
m_World->someOctTree.AddDynamicObject(boxi);
|
||||
frameCounter = 0;
|
||||
@@ -149,8 +164,8 @@ void Game::Tick()
|
||||
if (someOctTree.BoxCollides(redBox, AABB())) {
|
||||
//this checks AABB vs AABB
|
||||
//if (Collision::AABBVsAABB(redBox, aabb)) {
|
||||
m_Renderer->Camera()->SetPosition(m_PrevPos);
|
||||
m_Renderer->Camera()->SetOrientation(m_PrevOri);
|
||||
//m_Renderer->Camera()->SetPosition(m_PrevPos);
|
||||
//m_Renderer->Camera()->SetOrientation(m_PrevOri);
|
||||
model["Color"] = greenCol;
|
||||
}
|
||||
else {
|
||||
@@ -163,8 +178,14 @@ void Game::Tick()
|
||||
m_RenderQueueFactory->Update(m_World);
|
||||
#endif
|
||||
|
||||
m_Renderer->Draw(m_RenderQueueFactory->RenderQueues());
|
||||
// Iterate through systems and update world!
|
||||
m_SystemPipeline->Update(m_World, dt);
|
||||
m_Renderer->Update(dt);
|
||||
|
||||
m_RenderQueueFactory->Update(m_World);
|
||||
GLERROR("Game::Tick m_RenderQueueFactory->Update");
|
||||
m_Renderer->Draw(m_RenderQueueFactory->RenderQueues());
|
||||
GLERROR("Game::Tick m_Renderer->Draw");
|
||||
m_EventBroker->Swap();
|
||||
m_EventBroker->Clear();
|
||||
|
||||
|
||||
@@ -9,11 +9,19 @@
|
||||
#include "GUI/Frame.h"
|
||||
#include "Core/World.h"
|
||||
#include "Rendering/RenderQueueFactory.h"
|
||||
#include "Input/InputProxy.h"
|
||||
#include "Input/KeyboardInputHandler.h"
|
||||
#include "Input/MouseInputHandler.h"
|
||||
#include "Core/EKeyDown.h"
|
||||
#include "Core/EntityXMLFile.h"
|
||||
#include "Core/SystemPipeline.h"
|
||||
#include "RaptorCopterSystem.h"
|
||||
#include "PlayerSystem.h"
|
||||
#include "Editor/EditorSystem.h"
|
||||
|
||||
#include "OctTreeTestHardCodedTestWorld.h"
|
||||
#include "Collision/Collision.h"
|
||||
|
||||
|
||||
class Game
|
||||
{
|
||||
public:
|
||||
@@ -32,6 +40,8 @@ private:
|
||||
GUI::Frame* m_FrameStack;
|
||||
HardcodedTestWorld* m_World;
|
||||
RenderQueueFactory* m_RenderQueueFactory;
|
||||
InputProxy* m_InputProxy;
|
||||
SystemPipeline* m_SystemPipeline;
|
||||
|
||||
//Test1
|
||||
int frameCounter = 0;
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include "Core/World.h"
|
||||
|
||||
//private->public hack doesnt work, tons of link errors
|
||||
//so there is currently no good way to test this class
|
||||
//#define private public
|
||||
#include "Core/ResourceManager.h"
|
||||
#include "Core/ConfigFile.h"
|
||||
#include "Rendering/Renderer.h"
|
||||
#include "Core/EntityXMLFile.h"
|
||||
#include "Engine\Rendering\Texture.h"
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(resourceManagerTests)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(resourceManagerTest)
|
||||
{
|
||||
World m_World;
|
||||
|
||||
//private static metoder/variabler
|
||||
|
||||
ResourceManager::RegisterType<ConfigFile>("ConfigFile");
|
||||
BOOST_CHECK(!ResourceManager::IsResourceLoaded("ConfigFile", "Config.ini"));
|
||||
auto m_Config = ResourceManager::Load<ConfigFile>("Config.ini");
|
||||
BOOST_CHECK(ResourceManager::IsResourceLoaded("ConfigFile", "Config.ini"));
|
||||
ResourceManager::Release("ConfigFile", "Config.ini");
|
||||
BOOST_CHECK(!ResourceManager::IsResourceLoaded("ConfigFile", "Config.ini"));
|
||||
|
||||
//configfile without register
|
||||
//check so output says "EE failed to load: type not registered..."
|
||||
auto m_ScreenQuadNoRegister = ResourceManager::Load<Model>("Models/Core/ScreenQuad.obj");
|
||||
BOOST_CHECK(!ResourceManager::IsResourceLoaded("Model", "Models/Core/ScreenQuad.obj"));
|
||||
|
||||
//there is no error feedback to check if you try to release the wrong resources - hence that cant be tested either
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
Reference in New Issue
Block a user