Merge remote-tracking branch 'origin/master' into EditorUsefulness

# Conflicts:
#	include/Engine/Collision/CollidableOctreeSystem.h
#	include/Engine/Collision/CollisionSystem.h
#	include/Engine/Collision/TriggerSystem.h
#	include/Engine/Rendering/RenderSystem.h
#	include/Game/Systems/PlayerSystem.h
#	resources/Schema/Components/Physics.xsd
#	resources/Schema/Types/Entity.xsd
#	src/Engine/Rendering/RenderSystem.cpp
#	src/Engine/Rendering/Renderer.cpp
#	src/Game/Game.cpp
#	src/Game/Systems/HealthSystem.cpp
#	src/Game/Systems/PlayerSystem.cpp
#	src/Tests/OctTreeTestGameClass.cpp
This commit is contained in:
2016-01-21 16:05:08 +01:00
84 changed files with 2952 additions and 1201 deletions
+1 -1
Submodule assets updated: e794bef3a7...6ffb46e155
@@ -8,7 +8,7 @@
class CollidableOctreeSystem : public ImpureSystem, public PureSystem class CollidableOctreeSystem : public ImpureSystem, public PureSystem
{ {
public: public:
CollidableOctreeSystem(World* world, EventBroker* eventBroker, Octree* octree) CollidableOctreeSystem(World* world, EventBroker* eventBroker, Octree<AABB>* octree)
: System(world, eventBroker) : System(world, eventBroker)
, PureSystem("Collidable") , PureSystem("Collidable")
, m_Octree(octree) , m_Octree(octree)
@@ -18,7 +18,7 @@ public:
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override; virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override;
private: private:
Octree* m_Octree; Octree<AABB>* m_Octree;
}; };
#endif #endif
+3 -3
View File
@@ -13,9 +13,9 @@
class CollisionSystem : public PureSystem class CollisionSystem : public PureSystem
{ {
public: public:
CollisionSystem(World* world, EventBroker* eventBroker, Octree* octree) CollisionSystem(World* world, EventBroker* eventBroker, Octree<AABB>* octree)
: System(world, eventBroker) : System(world, eventBroker)
, PureSystem("AABB") , PureSystem("Collidable")
, m_Octree(octree) , m_Octree(octree)
, zPress(false) , zPress(false)
{ {
@@ -26,7 +26,7 @@ public:
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override; virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override;
private: private:
Octree* m_Octree; Octree<AABB>* m_Octree;
bool zPress; bool zPress;
EventRelay<CollisionSystem, Events::KeyUp> m_EKeyUp; EventRelay<CollisionSystem, Events::KeyUp> m_EKeyUp;
+15 -3
View File
@@ -14,19 +14,31 @@ class AABB;
class TriggerSystem : public PureSystem class TriggerSystem : public PureSystem
{ {
public: public:
TriggerSystem(World* world, EventBroker* eventBroker, Octree* octree) TriggerSystem(World* world, EventBroker* eventBroker, Octree<AABB>* octree)
: System(world, eventBroker) : System(world, eventBroker)
, PureSystem("Trigger") , PureSystem("Trigger")
, m_Octree(octree) , m_Octree(octree)
{ } {
EVENT_SUBSCRIBE_MEMBER(m_ETouch, &TriggerSystem::OnTouch);
EVENT_SUBSCRIBE_MEMBER(m_EEnter, &TriggerSystem::OnEnter);
EVENT_SUBSCRIBE_MEMBER(m_ELeave, &TriggerSystem::OnLeave);
}
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override; virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override;
private: private:
Octree* m_Octree; Octree<AABB>* m_Octree;
std::unordered_map<EntityID, std::unordered_set<EntityID>> m_EntitiesTouchingTrigger; std::unordered_map<EntityID, std::unordered_set<EntityID>> m_EntitiesTouchingTrigger;
std::unordered_map<EntityID, std::unordered_set<EntityID>> m_EntitiesCompletelyInTrigger; std::unordered_map<EntityID, std::unordered_set<EntityID>> m_EntitiesCompletelyInTrigger;
//TODO: Only exists for debug purposes, remove later.
EventRelay<TriggerSystem, Events::TriggerEnter> m_EEnter;
bool OnEnter(const Events::TriggerEnter &event);
EventRelay<TriggerSystem, Events::TriggerTouch> m_ETouch;
bool OnTouch(const Events::TriggerTouch &event);
EventRelay<TriggerSystem, Events::TriggerLeave> m_ELeave;
bool OnLeave(const Events::TriggerLeave &event);
//True if leave event was thrown. //True if leave event was thrown.
bool throwLeaveIfWasInTrigger(std::unordered_set<EntityID>& triggerSet, EntityID pId, EntityID tId); bool throwLeaveIfWasInTrigger(std::unordered_set<EntityID>& triggerSet, EntityID pId, EntityID tId);
template<typename Event> template<typename Event>
+1
View File
@@ -61,6 +61,7 @@ public:
iterator begin() const; iterator begin() const;
iterator end() const; iterator end() const;
size_t size() const;
//Dumps information about what the pool memory looks like right now //Dumps information about what the pool memory looks like right now
//into an output stream (e.g. file/std::cout, anything that has an operator<<) //into an output stream (e.g. file/std::cout, anything that has an operator<<)
+1 -1
View File
@@ -91,7 +91,7 @@ public:
void AddProperty(std::string fieldName, T defaultValue) void AddProperty(std::string fieldName, T defaultValue)
{ {
m_DefaultValues.push_back(defaultValue); m_DefaultValues.push_back(defaultValue);
m_ComponentInfo.Fields[fieldName].Name = typeid(T).name(); m_ComponentInfo.Fields[fieldName].Type = typeid(T).name();
m_ComponentInfo.Fields[fieldName].Offset = m_ComponentInfo.Stride; m_ComponentInfo.Fields[fieldName].Offset = m_ComponentInfo.Stride;
m_ComponentInfo.Fields[fieldName].Stride = sizeof(T); m_ComponentInfo.Fields[fieldName].Stride = sizeof(T);
m_ComponentInfo.Stride += sizeof(T); m_ComponentInfo.Stride += sizeof(T);
+20
View File
@@ -0,0 +1,20 @@
#ifndef ECaptured_h__
#define ECaptured_h__
#include "EventBroker.h"
#include "../Core/Entity.h"
#include "Engine/GLM.h"
namespace Events
{
//triggers when a capturePoint has been taken over
struct Captured : Event
{
int TeamNumberThatCapturedCapturePoint;
EntityID CapturePointID;
};
}
#endif
+20
View File
@@ -0,0 +1,20 @@
#ifndef EWin_h__
#define EWin_h__
#include "EventBroker.h"
#include "../Core/Entity.h"
#include "Engine/GLM.h"
namespace Events
{
//triggers when a team has captured all capturePoints
struct Win : Event
{
//can be 0 = none, 1,2
int TeamThatWon;
};
}
#endif
+14 -4
View File
@@ -5,6 +5,14 @@
template <typename T> template <typename T>
class MemoryPoolForwardIterator; class MemoryPoolForwardIterator;
namespace DisableMemoryPool
{
//if true -> Pool allocation is not used when calling Allocate/Free, just use regular dynamic allocation.
//if false -> Use pool allocation.
//Should default to false, unless the DisableMemoryPool is true in the Config.ini files.
extern bool Value;
}
//This is the class to use if you want to allocate blocks (slots) of raw memory, with a fixed maximum size (stride). //This is the class to use if you want to allocate blocks (slots) of raw memory, with a fixed maximum size (stride).
//Additionally, if you know that every memory-block will contain one object of a specific type, (i.e. the stride for the slot //Additionally, if you know that every memory-block will contain one object of a specific type, (i.e. the stride for the slot
//will the size of the object type) you should use ObjectPool<T> instead, your life will become easier. //will the size of the object type) you should use ObjectPool<T> instead, your life will become easier.
@@ -80,8 +88,8 @@ public:
//If element cannot be allocated in the pool, because the memory ran out, memory is allocated dynamically with malloc() "outside the pool". //If element cannot be allocated in the pool, because the memory ran out, memory is allocated dynamically with malloc() "outside the pool".
char* Allocate() char* Allocate()
{ {
for (; m_CurrentAllocSlot < m_NumSlots && m_SlotIsAllocated[m_CurrentAllocSlot]; ++m_CurrentAllocSlot); for (; m_CurrentAllocSlot < m_NumSlots && m_SlotIsAllocated[m_CurrentAllocSlot] && !DisableMemoryPool::Value; ++m_CurrentAllocSlot);
if (m_CurrentAllocSlot < m_NumSlots) { if (m_CurrentAllocSlot < m_NumSlots && !DisableMemoryPool::Value) {
if (m_LowestAllocatedSlot > m_CurrentAllocSlot) if (m_LowestAllocatedSlot > m_CurrentAllocSlot)
m_LowestAllocatedSlot = m_CurrentAllocSlot; m_LowestAllocatedSlot = m_CurrentAllocSlot;
//Mark the slot as allocated. //Mark the slot as allocated.
@@ -93,7 +101,9 @@ public:
else { else {
m_ExtraMemory.push_back((char*)malloc(m_Stride)); m_ExtraMemory.push_back((char*)malloc(m_Stride));
//We should preferably not enter here to avoid performance issues. Set more numMaxElements in constructor instead. //We should preferably not enter here to avoid performance issues. Set more numMaxElements in constructor instead.
LOG_WARNING("Allocated slots exceed Pool size, extra memory allocated dynamically. Pool size: %u, dynamic size: %u.", m_NumSlots, m_ExtraMemory.size()); if (!DisableMemoryPool::Value) {
LOG_WARNING("Allocated slots exceed Pool size, extra memory allocated dynamically. Pool size: %u, dynamic size: %u.", m_NumSlots, m_ExtraMemory.size());
}
return m_ExtraMemory.back(); return m_ExtraMemory.back();
} }
} }
@@ -108,7 +118,7 @@ public:
//(i.e. IsAllocatedInPool may give false positives) //(i.e. IsAllocatedInPool may give false positives)
//if it was malloc():ed //if it was malloc():ed
//so, we may enter here even if we shouldn't. //so, we may enter here even if we shouldn't.
if (IsAllocatedInPool(obj)) { if (!DisableMemoryPool::Value && IsAllocatedInPool(obj)) {
--m_NumAllocatedSlots; --m_NumAllocatedSlots;
const size_t freeSlot = (obj - m_StartAddress) / m_Stride; const size_t freeSlot = (obj - m_StartAddress) / m_Stride;
m_SlotIsAllocated[freeSlot] = false; m_SlotIsAllocated[freeSlot] = false;
+193 -65
View File
@@ -1,19 +1,27 @@
#ifndef Octree_h__ #ifndef Octree_h__
#define Octree_h__ #define Octree_h__
#include <type_traits>
#include "../Common.h" #include "../Common.h"
#include "AABB.h" #include "AABB.h"
//Fwd declarations.
class Ray; class Ray;
namespace OctSpace
{
struct Output;
struct ContainedObject;
struct Child;
}
//T needs to be AABB, or inherit from AABB.
//T also needs to have a default constructor.
template<typename T>
class Octree class Octree
{ {
public: public:
struct Output
{
float CollideDistance;
};
Octree() = delete; Octree() = delete;
~Octree(); ~Octree();
//For the root Octree, [octreeBounds] should be a box containing the entire level. //For the root Octree, [octreeBounds] should be a box containing the entire level.
@@ -25,81 +33,201 @@ public:
Octree(const Octree&& other) = delete; Octree(const Octree&& other) = delete;
Octree& operator= (const Octree& other) = delete; Octree& operator= (const Octree& other) = delete;
//Add a dynamic object (one that moves around) into the tree. //Add a dynamic object (one that moves around) into the tree.
void AddDynamicObject(const AABB& box); void AddDynamicObject(const T& object);
//Add a static object (that does not move) into the tree. //Add a static object (that does not move) into the tree.
void AddStaticObject(const AABB& box); void AddStaticObject(const T& object);
//Get the boxes that are in the same area as the input [box], the boxes are put in [outBoxes]. //Get the objects that are in the same area as the input [box], the objects are put in [outObjects].
void BoxesInSameRegion(const AABB& box, std::vector<AABB>& outBoxes); //The type Box must be AABB, or inherit from AABB.
template<typename Box>
void ObjectsInSameRegion(const Box& box, std::vector<T>& outObjects);
//Empty the tree of all objects, static and dynamic. //Empty the tree of all objects, static and dynamic.
void ClearObjects(); void ClearObjects();
//Empty the tree of all dynamic objects. Static objects remain in the tree. //Empty the tree of all dynamic objects. Static objects remain in the tree.
void ClearDynamicObjects(); void ClearDynamicObjects();
//Returns true if the ray collides with something in the tree. Result is written to [data]. //Returns true if the ray collides with something in the tree. Result is written to [data].
bool RayCollides(const Ray& ray, Output& data); bool RayCollides(const Ray& ray, OctSpace::Output& data);
//Returns true if the box collides with something in the tree. //Returns true if the box collides with something in the tree.
//On collision with a box, that box is written to [outBoxIntersected]. //On collision with a box, that box is written to [outBoxIntersected].
//Note: More efficient than calling BoxesInSameRegion from outside and testing there. //Note: More efficient than calling ObjectsInSameRegion from outside and testing there.
bool BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected); bool BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected);
private: private:
struct Child; //Fwd declaration; OctSpace::Child* m_Root;
struct ContainedObject std::vector<OctSpace::ContainedObject> m_StaticObjects;
{ std::vector<OctSpace::ContainedObject> m_DynamicObjects;
ContainedObject()
: Box(AABB())
, Checked(false)
{}
ContainedObject(AABB box)
: Box(box)
, Checked(false)
{}
AABB Box;
bool Checked;
};
Child* m_Root;
std::vector<ContainedObject> m_StaticObjects;
std::vector<ContainedObject> m_DynamicObjects;
bool m_UpdatedOnce;
unsigned int m_BoxID;
glm::vec3 m_PrevPos;
glm::quat m_PrevOri;
void falsifyObjectChecks(); void falsifyObjectChecks();
struct Child
{
~Child();
Child(const AABB& octTreeBounds,
int subDivisions,
std::vector<Octree::ContainedObject>& staticObjects,
std::vector<Octree::ContainedObject>& dynamicObjects);
Child(const Child& other) = delete;
Child(const Child&& other) = delete;
Child& operator= (const Child& other) = delete;
void AddDynamicObject(const AABB& box);
void AddStaticObject(const AABB& box);
void BoxesInSameRegion(const AABB& box, std::vector<AABB>& outBoxes) const;
void ClearObjects();
void ClearDynamicObjects();
bool RayCollides(const Ray& ray, Output& data) const;
bool BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const;
Child* m_Children[8];
//Indices into the lists in Octree.
std::vector<int> m_StaticObjIndices;
std::vector<int> m_DynamicObjIndices;
AABB m_Box;
//Reference to the lists in Octree.
std::vector<Octree::ContainedObject>& m_StaticObjectsRef;
std::vector<Octree::ContainedObject>& m_DynamicObjectsRef;
inline bool hasChildren() const;
int childIndexContainingPoint(const glm::vec3& point) const;
std::vector<int> childIndicesContainingBox(const AABB& box) const;
};
}; };
namespace OctSpace
{
struct Output
{
float CollideDistance;
};
struct ContainedObject
{
ContainedObject()
: Box(nullptr)
, Checked(false)
{}
template<typename BoxlikeObject>
ContainedObject(const BoxlikeObject& box)
: Box(new BoxlikeObject(box))
, Checked(false)
{}
std::unique_ptr<AABB> Box;
bool Checked;
};
struct Child
{
~Child();
Child(const AABB& octTreeBounds,
int subDivisions,
std::vector<ContainedObject>& staticObjects,
std::vector<ContainedObject>& dynamicObjects);
Child(const Child& other) = delete;
Child(const Child&& other) = delete;
Child& operator= (const Child& other) = delete;
void AddDynamicObject(const AABB& box);
void AddStaticObject(const AABB& box);
template<typename T, typename Box>
void ObjectsInSameRegion(const Box& box, std::vector<T>& outObjects) const;
void ClearObjects();
void ClearDynamicObjects();
bool RayCollides(const Ray& ray, Output& data) const;
bool BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const;
Child* m_Children[8];
//Indices into the lists in Octree.
std::vector<int> m_StaticObjIndices;
std::vector<int> m_DynamicObjIndices;
AABB m_Box;
//Reference to the lists in Octree.
std::vector<ContainedObject>& m_StaticObjectsRef;
std::vector<ContainedObject>& m_DynamicObjectsRef;
inline bool hasChildren() const;
int childIndexContainingPoint(const glm::vec3& point) const;
std::vector<int> childIndicesContainingBox(const AABB& box) const;
};
}
template<typename T>
Octree<T>::Octree(const AABB& octTreeBounds, int subDivisions)
: m_Root(new OctSpace::Child(octTreeBounds, subDivisions, m_StaticObjects, m_DynamicObjects))
{
static_assert(std::is_base_of<AABB, T>::value, "template argument type T in Octree must be a subclass of AABB.");
}
template<typename T>
Octree<T>::~Octree()
{
delete m_Root;
}
template<typename T>
void Octree<T>::AddDynamicObject(const T& object)
{
m_Root->AddDynamicObject(object);
m_DynamicObjects.emplace_back(object);
}
template<typename T>
void Octree<T>::AddStaticObject(const T& object)
{
m_Root->AddStaticObject(object);
m_StaticObjects.emplace_back(object);
}
template<typename T>
template<typename Box>
void Octree<T>::ObjectsInSameRegion(const Box& box, std::vector<T>& outObjects)
{
static_assert(std::is_base_of<AABB, Box>::value, "template argument type Box in Octree<T>::ObjectsInSameRegion must be a subclass of AABB.");
falsifyObjectChecks();
m_Root->ObjectsInSameRegion(box, outObjects);
}
template<typename T>
void Octree<T>::ClearObjects()
{
m_StaticObjects.clear();
m_DynamicObjects.clear();
m_Root->ClearObjects();
}
template<typename T>
void Octree<T>::ClearDynamicObjects()
{
m_DynamicObjects.clear();
m_Root->ClearDynamicObjects();
}
template<typename T>
bool Octree<T>::RayCollides(const Ray& ray, OctSpace::Output& data)
{
falsifyObjectChecks();
data.CollideDistance = -1;
return m_Root->RayCollides(ray, data);
}
template<typename T>
bool Octree<T>::BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected)
{
falsifyObjectChecks();
return m_Root->BoxCollides(boxToTest, outBoxIntersected);
}
template<typename T>
void Octree<T>::falsifyObjectChecks()
{
for (auto& obj : m_StaticObjects) {
obj.Checked = false;
}
for (auto& obj : m_DynamicObjects) {
obj.Checked = false;
}
}
template<typename T, typename Box>
void OctSpace::Child::ObjectsInSameRegion(const Box& box, std::vector<T>& outObjects) const
{
if (hasChildren()) {
for (auto i : childIndicesContainingBox(box)) {
m_Children[i]->ObjectsInSameRegion(box, outObjects);
}
} else {
size_t startIndex = outObjects.size();
int numDuplicates = 0;
outObjects.resize(outObjects.size() + m_StaticObjIndices.size() + m_DynamicObjIndices.size());
for (size_t i = 0; i < m_StaticObjIndices.size(); ++i) {
ContainedObject& obj = m_StaticObjectsRef[m_StaticObjIndices[i]];
if (obj.Checked) {
++numDuplicates;
} else {
obj.Checked = true;
outObjects[startIndex + i - numDuplicates] = *static_cast<T*>(obj.Box.get());
}
}
for (size_t i = 0; i < m_DynamicObjIndices.size(); ++i) {
ContainedObject& obj = m_DynamicObjectsRef[m_DynamicObjIndices[i]];
if (obj.Checked) {
++numDuplicates;
} else {
obj.Checked = true;
outObjects[startIndex + i - numDuplicates] = *static_cast<T*>(obj.Box.get());
}
}
for (size_t i = 0; i < numDuplicates; ++i) {
outObjects.pop_back();
}
}
}
#endif #endif
+28 -10
View File
@@ -3,9 +3,12 @@
#include <string> #include <string>
#include <ctime> #include <ctime>
#include <limits>
#include <queue>
#include <glm/common.hpp> #include <glm/common.hpp>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include <boost/shared_array.hpp>
#include "Network/Network.h" #include "Network/Network.h"
#include "Network/MessageType.h" #include "Network/MessageType.h"
@@ -15,6 +18,8 @@
#include "Core/EventBroker.h" #include "Core/EventBroker.h"
#include "Core/ConfigFile.h" #include "Core/ConfigFile.h"
#include "Input/EInputCommand.h" #include "Input/EInputCommand.h"
#include "Core/EPlayerDamage.h"
#include "Network/EInterpolate.h"
class Client : public Network class Client : public Network
{ {
@@ -32,8 +37,6 @@ private:
// Sending message to server logic // Sending message to server logic
int bytesRead = -1; int bytesRead = -1;
char readBuf[INPUTSIZE] = { 0 }; char readBuf[INPUTSIZE] = { 0 };
int snapshotInterval = 33;
std::clock_t previousSnapshotMessage = std::clock();
// Packet loss logic // Packet loss logic
unsigned int m_PacketID = 0; unsigned int m_PacketID = 0;
@@ -44,40 +47,55 @@ private:
World* m_World; World* m_World;
std::string m_PlayerName; std::string m_PlayerName;
int m_PlayerID = -1; int m_PlayerID = -1;
EntityID m_ServerEntityID = std::numeric_limits<EntityID>::max();
bool m_IsConnected = false;
// Server Client Lookup map
// Assumes that root node for client and server is EntityID 0.
// Don't Add items to these two maps with insert, use insertIntoServerClientMaps(EntityID, EntityID)!!!!
std::unordered_map<EntityID, EntityID> m_ServerIDToClientID;
std::unordered_map<EntityID, EntityID> m_ClientIDToServerID;
// Network logic // Network logic
PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS]; PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS];
SnapshotDefinitions m_NextSnapshot; SnapshotDefinitions m_NextSnapshot;
double m_DurationOfPingTime; double m_DurationOfPingTime;
std::clock_t m_StartPingTime; std::clock_t m_StartPingTime;
// Use to check if we should send disconnect message std::vector<Events::InputCommand> m_InputCommandBuffer;
// if game is turned of by closing window.
bool m_WasStarted = false;
// Private member functions // Private member functions
void readFromServer(); void readFromServer();
void sendSnapshotToServer();
int receive(char* data, size_t length); int receive(char* data, size_t length);
void send(Packet& packet); void send(Packet& packet);
void connect(); void connect();
void disconnect(); void disconnect();
void ping(); void ping();
void moveMessageHead(char*& data, size_t& length, size_t stepSize);
void parseMessageType(Packet& packet); void parseMessageType(Packet& packet);
void parseEventMessage(Packet& packet);
void updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType); void updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType);
void parseConnect(Packet& packet); void parseConnect(Packet& packet);
void parsePlayerConnected(Packet& packet);
void parsePing(); void parsePing();
void parseServerPing(); void parseServerPing();
void InterpolateFields(Packet & packet, const ComponentInfo & componentInfo, const EntityID & entityID, const std::string & componentType);
void parseSnapshot(Packet& packet); void parseSnapshot(Packet& packet);
void identifyPacketLoss(); void identifyPacketLoss();
bool isConnected(); bool hasServerTimedOut();
EntityID createPlayer(); EntityID createPlayer();
void sendInputCommands();
void becomePlayer();
// Mapping Logic
// Returns if local EntityID exist in map
bool clientServerMapsHasEntity(EntityID clientEntityID);
// Returns if server EntityID exist in map
bool serverClientMapsHasEntity(EntityID serverEntityID);
void insertIntoServerClientMaps(EntityID serverEntityID, EntityID clientEntityID);
// Events // Events
EventBroker* m_EventBroker; EventBroker* m_EventBroker;
EventRelay<Client, Events::InputCommand> m_EInputCommand; EventRelay<Client, Events::InputCommand> m_EInputCommand;
bool OnInputCommand(const Events::InputCommand &e); bool OnInputCommand(const Events::InputCommand& e);
EventRelay<Client, Events::PlayerDamage> m_EPlayeDamage;
bool OnPlayerDamage(const Events::PlayerDamage& e);
}; };
#endif #endif
+20
View File
@@ -0,0 +1,20 @@
#ifndef Events_Interpolate_h__
#define Events_Interpolate_h__
#include <boost/shared_array.hpp>
#include "Core/EventBroker.h"
#include "Core/Entity.h"
namespace Events
{
struct Interpolate : Event
{
EntityID Entity;
boost::shared_array<char> DataArray;
};
}
#endif
+4 -1
View File
@@ -11,7 +11,10 @@ enum class MessageType
ServerPing, ServerPing,
Message, Message,
Snapshot, Snapshot,
Event, OnInputCommand,
OnPlayerDamage,
PlayerConnected,
BecomePlayer
}; };
#endif #endif
+1
View File
@@ -7,6 +7,7 @@
#define MAXCONNECTIONS 8 #define MAXCONNECTIONS 8
#define INPUTSIZE 4097 #define INPUTSIZE 4097
#define TIMEOUTMS 15000
class Network class Network
{ {
+2 -1
View File
@@ -14,6 +14,7 @@ public:
Packet(MessageType type, unsigned int& packetID); Packet(MessageType type, unsigned int& packetID);
// Used to create packet from already existing data buffer. // Used to create packet from already existing data buffer.
Packet(char* data, const int sizeOfPacket); Packet(char* data, const int sizeOfPacket);
Packet(MessageType type);
~Packet(); ~Packet();
void Init(MessageType type, unsigned int& packetID); void Init(MessageType type, unsigned int& packetID);
@@ -49,7 +50,7 @@ public:
// Pops the first element as if it was a string. // Pops the first element as if it was a string.
std::string ReadString(); std::string ReadString();
char* ReadData(int SizeOfData); char* ReadData(int SizeOfData);
void ChangePacketID(unsigned int& packetID);
int Size() { return m_Offset; }; int Size() { return m_Offset; };
char* Data() { return m_Data; }; char* Data() { return m_Data; };
unsigned int DataReadSize() { return m_ReturnDataOffset; } unsigned int DataReadSize() { return m_ReturnDataOffset; }
@@ -6,6 +6,8 @@ struct PlayerDefinition {
int EntityID = -1; int EntityID = -1;
std::string Name = ""; std::string Name = "";
boost::asio::ip::udp::endpoint Endpoint; boost::asio::ip::udp::endpoint Endpoint;
unsigned int PacketID;
std::clock_t StopTime;
}; };
#endif #endif
+14 -13
View File
@@ -11,7 +11,9 @@
#include "Network/PlayerDefinition.h" #include "Network/PlayerDefinition.h"
#include "Core/World.h" #include "Core/World.h"
#include "Core/EventBroker.h" #include "Core/EventBroker.h"
#include "Network/Network.h" #include "../Network/Network.h"
#include "Input/EInputCommand.h"
#include "Core/EPlayerDamage.h"
class Server : public Network class Server : public Network
{ {
@@ -25,9 +27,10 @@ private:
boost::asio::ip::udp::endpoint m_ReceiverEndpoint; boost::asio::ip::udp::endpoint m_ReceiverEndpoint;
boost::asio::io_service m_IOService; boost::asio::io_service m_IOService;
boost::asio::ip::udp::socket m_Socket; boost::asio::ip::udp::socket m_Socket;
PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS];
// Sending messages to client logic // Sending messages to client logic
PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS];
std::vector<PlayerDefinition> m_ConnectedUsers;
char readBuffer[INPUTSIZE] = { 0 }; char readBuffer[INPUTSIZE] = { 0 };
int bytesRead = 0; int bytesRead = 0;
// time for previouse message // time for previouse message
@@ -41,40 +44,38 @@ private:
//Timers //Timers
std::clock_t m_StartPingTime; std::clock_t m_StartPingTime;
std::clock_t m_StopTimes[8];
// Game logic // Game logic
World* m_World; World* m_World;
EventBroker* m_EventBroker; EventBroker* m_EventBroker;
// vec.size() = ammount of players to create, stores playerID's
std::vector<unsigned int> m_PlayersToCreate;
// Packet loss logic // Packet loss logic
unsigned int m_PacketID; unsigned int m_PacketID = 0;
unsigned int m_PreviousPacketID; unsigned int m_PreviousPacketID = 0;
unsigned int m_SendPacketID;
// Private member functions // Private member functions
int receive(char* data, size_t length); int receive(char* data, size_t length);
void readFromClients(); void readFromClients();
void send(Packet& packet, int playerID); void send(Packet& packet, int playerID);
void send(Packet& packet); void send(Packet& packet);
void moveMessageHead(char*& data, size_t& length, size_t stepSize);
void broadcast(std::string message);
void broadcast(Packet& packet); void broadcast(Packet& packet);
void sendSnapshot(); void sendSnapshot();
void sendPing(); void sendPing();
void checkForTimeOuts(); void checkForTimeOuts();
void disconnect(int i); void disconnect(int i);
void parseMessageType(Packet& packet); void parseMessageType(Packet& packet);
void parseEvent(Packet& packet); void parseOnInputCommand(Packet& packet);
void parseOnPlayerDamage(Packet& packet);
void parseConnect(Packet& packet); void parseConnect(Packet& packet);
void parseDisconnect(); void parseDisconnect();
void parseClientPing(); void parseClientPing();
void parseServerPing(); void parseServerPing();
void parseSnapshot(Packet& packet);
void identifyPacketLoss(); void identifyPacketLoss();
EntityID createPlayer(); void createPlayer();
int GetPlayerIDFromEndpoint(boost::asio::ip::udp::endpoint endpoint);
// Debug event
EventRelay<Server, Events::InputCommand> m_EInputCommand;
bool OnInputCommand(const Events::InputCommand& e);
}; };
#endif #endif
@@ -0,0 +1,35 @@
#ifndef DirectionalLightJob_h__
#define DirectionalLightJob_h__
#include <cstdint>
#include "../Common.h"
#include "../GLM.h"
#include "../Core/ComponentWrapper.h"
#include "RenderJob.h"
#include "../Core/Transform.h"
#include "../Core/World.h"
struct DirectionalLightJob : RenderJob
{
DirectionalLightJob(ComponentWrapper transformComponent, ComponentWrapper directionalLightComponent, World* m_World)
: RenderJob()
{
Direction = glm::vec4(0,0,-1,0) * glm::inverse(Transform::AbsoluteOrientation(m_World, transformComponent.EntityID));
//Direction = glm::vec4((glm::vec3)directionalLightComponent["Direction"], 0.f);
Color = (glm::vec4)directionalLightComponent["Color"];
Intensity = (double)directionalLightComponent["Intensity"];
};
glm::vec4 Direction;
glm::vec4 Color;
float Intensity;
void CalculateHash() override
{
Hash = 0;
}
};
#endif
+9 -8
View File
@@ -46,8 +46,8 @@ private:
int m_NumberOfTiles = 0; int m_NumberOfTiles = 0;
struct Plane { struct Plane {
glm::vec3 Normal; glm::vec3 Normal = glm::vec3(0.f);
float d; float d = 0;
}; };
struct Frustum { struct Frustum {
@@ -56,20 +56,21 @@ private:
Frustum* m_Frustums; Frustum* m_Frustums;
//This should be a component //This should be a component
struct PointLight { struct LightSource {
glm::vec4 Position = glm::vec4(0.f); glm::vec4 Position = glm::vec4(0.f);
glm::vec4 Direction = glm::vec4(10.f);
glm::vec4 Color = glm::vec4(1.f); glm::vec4 Color = glm::vec4(1.f);
float Radius = 5.f; float Radius = 5.f;
float Intensity = 0.8f; float Intensity = 0.8f;
float Falloff = 0.3f; float Falloff = 0.3f;
float Padding = 1337; enum Type_t { Zero, Point, Directional, Spot } Type;
}; };
std::vector<PointLight> m_PointLights; std::vector<LightSource> m_LightSources;
struct LightGrid { struct LightGrid {
float Start; float Start = 0;
float Amount; float Amount = 0;
glm::vec2 Padding; glm::vec2 Padding = glm::vec2(1.f, 2.f);
}; };
LightGrid* m_LightGrid; LightGrid* m_LightGrid;
+4
View File
@@ -12,6 +12,7 @@
#include "../Core/ResourceManager.h" #include "../Core/ResourceManager.h"
#include "Camera.h" #include "Camera.h"
#include "../Core/World.h" #include "../Core/World.h"
#include "../Core/Transform.h"
struct ModelJob : RenderJob struct ModelJob : RenderJob
{ {
@@ -28,6 +29,9 @@ struct ModelJob : RenderJob
Matrix = matrix; Matrix = matrix;
Color = modelComponent["Color"]; Color = modelComponent["Color"];
Entity = modelComponent.EntityID; Entity = modelComponent.EntityID;
glm::vec3 abspos = Transform::AbsolutePosition(world, modelComponent.EntityID);
glm::vec3 worldpos = glm::vec3(camera->ViewMatrix() * glm::vec4(abspos, 1));
Depth = worldpos.z;
World = world; World = world;
}; };
+3
View File
@@ -12,6 +12,7 @@
#include "RenderJob.h" #include "RenderJob.h"
#include "ModelJob.h" #include "ModelJob.h"
#include "PointLightJob.h" #include "PointLightJob.h"
#include "DirectionalLightJob.h"
/* /*
@@ -53,6 +54,7 @@ struct RenderScene
::Camera* Camera = nullptr; ::Camera* Camera = nullptr;
std::list<std::shared_ptr<RenderJob>> ForwardJobs; std::list<std::shared_ptr<RenderJob>> ForwardJobs;
std::list<std::shared_ptr<RenderJob>> PointLightJobs; std::list<std::shared_ptr<RenderJob>> PointLightJobs;
std::list<std::shared_ptr<RenderJob>> DirectionalLightJobs;
Rectangle Viewport; Rectangle Viewport;
bool ClearDepth = false; bool ClearDepth = false;
@@ -60,6 +62,7 @@ struct RenderScene
{ {
ForwardJobs.clear(); ForwardJobs.clear();
PointLightJobs.clear(); PointLightJobs.clear();
DirectionalLightJobs.clear();
} }
}; };
+2
View File
@@ -33,6 +33,8 @@ private:
EventRelay<RenderSystem, Events::SetCamera> m_ESetCamera; EventRelay<RenderSystem, Events::SetCamera> m_ESetCamera;
bool OnSetCamera(Events::SetCamera &event); bool OnSetCamera(Events::SetCamera &event);
void fillPointLights(std::list<std::shared_ptr<RenderJob>>& jobs, World* world);
void fillDirectionalLights(std::list<std::shared_ptr<RenderJob>>& jobs, World* world);
EventRelay<RenderSystem, Events::InputCommand> m_EInputCommand; EventRelay<RenderSystem, Events::InputCommand> m_EInputCommand;
bool OnInputCommand(const Events::InputCommand& e); bool OnInputCommand(const Events::InputCommand& e);
+2 -4
View File
@@ -21,9 +21,8 @@
class Renderer : public IRenderer class Renderer : public IRenderer
{ {
public: public:
Renderer(EventBroker* eventBroker, World* world) Renderer(EventBroker* eventBroker)
: m_EventBroker(eventBroker) : m_EventBroker(eventBroker)
, m_World(world)
{ } { }
virtual void Initialize() override; virtual void Initialize() override;
@@ -35,7 +34,6 @@ public:
private: private:
//----------------------Variables----------------------// //----------------------Variables----------------------//
EventBroker* m_EventBroker; EventBroker* m_EventBroker;
World* m_World;
Texture* m_ErrorTexture; Texture* m_ErrorTexture;
Texture* m_WhiteTexture; Texture* m_WhiteTexture;
@@ -60,7 +58,7 @@ private:
void DrawScreenQuad(GLuint textureToDraw); void DrawScreenQuad(GLuint textureToDraw);
static bool DepthSort(const std::shared_ptr<RenderJob> &i, const std::shared_ptr<RenderJob> &j) { return (i->Depth < j->Depth); } static bool DepthSort(const std::shared_ptr<RenderJob> &i, const std::shared_ptr<RenderJob> &j) { return (i->Depth < j->Depth); }
void FillDepth(RenderScene& scene); void SortRenderJobsByDepth(RenderScene &scene);
void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type); void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type);
//--------------------ShaderPrograms-------------------// //--------------------ShaderPrograms-------------------//
ShaderProgram* m_BasicForwardProgram; ShaderProgram* m_BasicForwardProgram;
+3 -3
View File
@@ -19,7 +19,7 @@
#include "Rendering/RenderSystem.h" #include "Rendering/RenderSystem.h"
#include "Core/EntityFileParser.h" #include "Core/EntityFileParser.h"
#include "Core/Octree.h" #include "Core/Octree.h"
#include "Systems/InterpolationSystem.h"
// Network // Network
#include <boost/thread.hpp> #include <boost/thread.hpp>
#include "Network/Network.h" #include "Network/Network.h"
@@ -47,8 +47,8 @@ private:
InputProxy* m_InputProxy; InputProxy* m_InputProxy;
GUI::Frame* m_FrameStack; GUI::Frame* m_FrameStack;
World* m_World; World* m_World;
Octree* m_OctreeCollision; Octree<AABB>* m_OctreeCollision;
Octree* m_OctreeFrustrumCulling; Octree<AABB>* m_OctreeFrustrumCulling;
SystemPipeline* m_SystemPipeline; SystemPipeline* m_SystemPipeline;
RenderFrame* m_RenderFrame; RenderFrame* m_RenderFrame;
// Network variables // Network variables
+55
View File
@@ -0,0 +1,55 @@
#ifndef CapturePointSystem_h__
#define CapturePointSystem_h__
#include <GLFW/glfw3.h>
#include <glm/common.hpp>
#include "Common.h"
#include "Core/System.h"
#include "Engine/Collision/ETrigger.h"
#include "Core/ECaptured.h"
#include "Core/EWin.h"
#include <tuple>
#include <vector>
class CapturePointSystem : public PureSystem
{
public:
//WARNING: on new map, destroy all info in the vectors, as well as reset all variables (just make new?)
CapturePointSystem(World* world, EventBroker* eventBroker);
//updatecomponent
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& capturePoint, double dt) override;
private:
//methods which will take care of specific events
EventRelay<CapturePointSystem, Events::TriggerTouch> m_ETriggerTouch;
bool CapturePointSystem::OnTriggerTouch(const Events::TriggerTouch& e);
EventRelay<CapturePointSystem, Events::TriggerLeave> m_ETriggerLeave;
bool CapturePointSystem::OnTriggerLeave(const Events::TriggerLeave& e);
EventRelay<CapturePointSystem, Events::Captured> m_ECaptured;
bool CapturePointSystem::OnCaptured(const Events::Captured& e);
bool m_WinnerWasFound = false;
//need to track these variables for the captureSystem to work as per design!
const int m_NotACapturePoint = 999;
int m_RedTeamNextPossibleCapturePoint = m_NotACapturePoint;
int m_BlueTeamNextPossibleCapturePoint = m_NotACapturePoint;
int m_RedTeamHomeCapturePoint = m_NotACapturePoint;
int m_BlueTeamHomeCapturePoint = m_NotACapturePoint;
int m_NumberOfCapturePoints = 0;
std::map<int, EntityID> m_CapturePointNumberToEntityIDMap;
//std::vector<ComponentWrapper>
const double m_CaptureTimeToTakeOver = 15.0;
bool m_ResetTimers = false;
//vectors which will keep track of enter/leave changes
std::vector<std::tuple<EntityID, EntityID>> m_ETriggerTouchVector;
std::vector<std::tuple<EntityID, EntityID>> m_ETriggerLeaveVector;
};
#endif
@@ -0,0 +1,53 @@
#ifndef Systems_InterpolationSystem_h__
#define Systems_InterpolationSystem_h__
#include <queue>
#include <unordered_map>
#include <boost/shared_array.hpp>
#include <glm/common.hpp>
#include <glm/gtc/quaternion.hpp>
#include "Common.h"
#include "Core/System.h"
#include "Core/EventBroker.h"
#include "Network/EInterpolate.h"
#define SNAPSHOTINTERVAL 0.05f
class InterpolationSystem : public PureSystem
{
struct Transform
{
glm::vec3 Position;
glm::vec3 Scale;
glm::quat Orientation;
double interpolationTime;
};
public:
InterpolationSystem(World* world, EventBroker* eventBroker)
: System(world, eventBroker)
, PureSystem("Transform")
{
EVENT_SUBSCRIBE_MEMBER(m_EInterpolate, &InterpolationSystem::OnInterpolate);
}
~InterpolationSystem() { }
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& transform, double dt) override;
private:
std::unordered_map<EntityID, Transform> m_NextTransform;
std::unordered_map<EntityID, Transform> m_LastReceivedTransform;
//glm::vec3 vectorInterpolation(glm::vec3 prev, glm::vec3 next, double currentTime);
template <typename T>
T vectorInterpolation(T prev, T next, double currentTime)
{
T difference = next - prev;
T vector = (difference / SNAPSHOTINTERVAL) * static_cast<float>(currentTime);
return vector;
}
EventRelay<InterpolationSystem, Events::Interpolate> m_EInterpolate;
bool InterpolationSystem::OnInterpolate(const Events::Interpolate& e);
};
#endif
-34
View File
@@ -1,34 +0,0 @@
#ifndef PlayerSystem_h__
#define PlayerSystem_h__
#include <GLFW/glfw3.h>
#include <glm/common.hpp>
#include "Common.h"
#include "Core/System.h"
#include "Collision/ETrigger.h"
class PlayerSystem : public PureSystem
{
public:
PlayerSystem(World* world, EventBroker* eventBroker)
: System(world, eventBroker)
, PureSystem("Player")
{
EVENT_SUBSCRIBE_MEMBER(m_ETouch, &PlayerSystem::OnTouch);
EVENT_SUBSCRIBE_MEMBER(m_EEnter, &PlayerSystem::OnEnter);
EVENT_SUBSCRIBE_MEMBER(m_ELeave, &PlayerSystem::OnLeave);
}
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override;
private:
float m_Speed = 5;
EventRelay<PlayerSystem, Events::TriggerEnter> m_EEnter;
bool OnEnter(const Events::TriggerEnter &event);
EventRelay<PlayerSystem, Events::TriggerTouch> m_ETouch;
bool PlayerSystem::OnTouch(const Events::TriggerTouch &event);
EventRelay<PlayerSystem, Events::TriggerLeave> m_ELeave;
bool PlayerSystem::OnLeave(const Events::TriggerLeave &event);
};
#endif
+3 -1
View File
@@ -2,7 +2,9 @@
LogLevel=1 LogLevel=1
LoadMap= LoadMap=
EditorEnabled=false EditorEnabled=false
; if true -> Pool allocation is not used when calling Allocate/Free, just use regular dynamic allocation.
; if false -> Use pool allocation.
DisableMemoryPool=false
[Video] [Video]
Fullscreen=false Fullscreen=false
+2
View File
@@ -9,8 +9,10 @@
<xs:include schemaLocation="Components/Camera.xsd"/> <xs:include schemaLocation="Components/Camera.xsd"/>
<xs:include schemaLocation="Components/AABB.xsd"/> <xs:include schemaLocation="Components/AABB.xsd"/>
<xs:include schemaLocation="Components/PointLight.xsd"/> <xs:include schemaLocation="Components/PointLight.xsd"/>
<xs:include schemaLocation="Components/DirectionalLight.xsd"/>
<xs:include schemaLocation="Components/Trigger.xsd"/> <xs:include schemaLocation="Components/Trigger.xsd"/>
<xs:include schemaLocation="Components/Health.xsd"/> <xs:include schemaLocation="Components/Health.xsd"/>
<xs:include schemaLocation="Components/CapturePoint.xsd"/>
<xs:include schemaLocation="Components/Listener.xsd"/> <xs:include schemaLocation="Components/Listener.xsd"/>
<xs:include schemaLocation="Components/SoundEmitter.xsd"/> <xs:include schemaLocation="Components/SoundEmitter.xsd"/>
<xs:include schemaLocation="Components/Collidable.xsd"/> <xs:include schemaLocation="Components/Collidable.xsd"/>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<CapturePoint xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="CapturePoint.xsd">
<CapturePointNumber>0</CapturePointNumber>
<CaptureTimer>0</CaptureTimer>
<HomePointForTeam><Spectator/></HomePointForTeam>
</CapturePoint>
@@ -0,0 +1,44 @@
<?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:complexType name="TeamEnum" mixed="true">
<xs:complexContent>
<xs:extension base="t:enum">
<xs:choice>
<xs:element name="Spectator" type="xs:integer" fixed="1" minOccurs="0"/>
<xs:element name="Red" type="xs:integer" fixed="2" minOccurs="0"/>
<xs:element name="Blue" type="xs:integer" fixed="3" minOccurs="0"/>
</xs:choice>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="CapturePoint">
<xs:annotation>
<xs:documentation>A Capture Point. Add a Team Component to specify who currently owns it</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:all>
<xs:element name="CaptureTimer" type="t:double" minOccurs="0">
<xs:annotation>
<xs:documentation>CaptureTimer handled by Capture Point System</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="CapturePointNumber" type="t:int" minOccurs="0">
<xs:annotation>
<xs:documentation>CapturePointNumber specify an int number for this</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="HomePointForTeam" type="TeamEnum" minOccurs="0">
<xs:annotation>
<xs:documentation>Specify if this is a HomePoint for either team</xs:documentation>
</xs:annotation>
</xs:element>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<DirectionalLight xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="DirectionalLight.xsd">
<Color R="1" G="1" B="1" A="1"/>
<Intensity>0.8</Intensity>
<Visible>true</Visible>
</DirectionalLight>
@@ -0,0 +1,16 @@
<?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="DirectionalLight">
<xs:annotation>
<xs:documentation>A directional light that shines bright like the future.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:all>
<xs:element name="Color" type="t:Color" minOccurs="0"/>
<xs:element name="Intensity" type="t:double" minOccurs="0"/>
<xs:element name="Visible" type="t:bool" minOccurs="0"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
+1
View File
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?> <?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Physics xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Physics.xsd"> <Physics xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Physics.xsd">
<Velocity X="0" Y="0" Z="0"/> <Velocity X="0" Y="0" Z="0"/>
<Gravity>true</Gravity>
</Physics> </Physics>
+1
View File
@@ -12,6 +12,7 @@
<xs:element name="Velocity" type="t:Vector" minOccurs="0"> <xs:element name="Velocity" type="t:Vector" minOccurs="0">
<xs:annotation><xs:documentation>m/s^2</xs:documentation></xs:annotation> <xs:annotation><xs:documentation>m/s^2</xs:documentation></xs:annotation>
</xs:element> </xs:element>
<xs:element name="Gravity" type="t:bool" minOccurs="0"/>
</xs:all> </xs:all>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
+3
View File
@@ -4,6 +4,9 @@
<xs:import schemaLocation="../Types.xsd" namespace="types"/> <xs:import schemaLocation="../Types.xsd" namespace="types"/>
<xs:element name="Player"> <xs:element name="Player">
<xs:annotation>
<xs:documentation>The player charachter</xs:documentation>
</xs:annotation>
<xs:complexType> <xs:complexType>
<xs:all> <xs:all>
<xs:element name="Velocity" type="t:Vector" minOccurs="0"/> <xs:element name="Velocity" type="t:Vector" minOccurs="0"/>
+1 -1
View File
@@ -14,7 +14,7 @@
</xs:extension> </xs:extension>
</xs:complexContent> </xs:complexContent>
</xs:complexType> </xs:complexType>
<xs:element name="Team"> <xs:element name="Team">
<xs:annotation> <xs:annotation>
<xs:documentation>Represents entity team affiliation</xs:documentation> <xs:documentation>Represents entity team affiliation</xs:documentation>
+156
View File
@@ -0,0 +1,156 @@
<?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:Model>
<Resource>../assets/Models/DummyScene.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health>
<Health>60</Health>
</c:Health>
<c:AABB/>
<c:Camera/>
<c:Listener/>
<c:Player/>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="-0.151326105" Y="13.5594187" Z="12.5957394"/>
<Orientation X="-0.872664392" Y="0.157068729" Z="4.90324332e-08"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<HomePointForTeam>3</HomePointForTeam>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="1" G="0.200000003" R="0"/>
</c:Model>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="5.48757935" Y="2.62824345" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<CapturePointNumber>1</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="0" G="1" R="1"/>
</c:Model>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="1.91470337" Y="2.32191443" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<CapturePointNumber>2</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="1" G="1" R="0"/>
</c:Model>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="-1.31178355" Y="2.16289616" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<HomePointForTeam>2</HomePointForTeam>
<CapturePointNumber>3</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="0" G="0.200000003" R="1"/>
</c:Model>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="-4.27947044" Y="1.99913001" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="0.482352942" G="0.490196079" R="1"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="-1.67672658" Y="2.23822045" Z="-0.0577065349"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="1" G="0.196078435" R="0.196078435"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="2.40398169" Y="2.02053547" Z="-0.0348547697"/>
</c:Transform>
</Components>
<Children/>
</Entity>
</Children>
</Entity>
@@ -0,0 +1,158 @@
<?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:Model>
<Resource>../assets/Models/DummyScene.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health>
<Health>60</Health>
</c:Health>
<c:AABB/>
<c:Camera/>
<c:Listener/>
<c:Player/>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="-2.38960934" Y="11.7122087" Z="11.4659815"/>
<Orientation X="-0.645771146" Y="-1.17512627e-05" Z="1.76718231e-07"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<HomePointForTeam>3</HomePointForTeam>
<CaptureTimer>6.9158446328696002</CaptureTimer>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="0" G="1" R="1"/>
</c:Model>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="5.48757935" Y="2.62824345" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<CaptureTimer>-13.234195338196177</CaptureTimer>
<CapturePointNumber>1</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="1" G="1" R="0"/>
</c:Model>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="1.38422918" Y="2.32191443" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<CapturePointNumber>2</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="0" G="0.200000003" R="1"/>
</c:Model>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="-1.79222715" Y="2.16289616" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<HomePointForTeam>2</HomePointForTeam>
<CapturePointNumber>3</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="0" G="0.200000003" R="1"/>
</c:Model>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="-4.27947044" Y="1.99913001" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="0.482352942" G="0.490196079" R="1"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="4.99647331" Y="2.23822045" Z="1.80651212"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="1" G="0.196078435" R="0.196078435"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="2.7091608" Y="2.02053547" Z="-0.0348547697"/>
</c:Transform>
</Components>
<Children/>
</Entity>
</Children>
</Entity>
@@ -0,0 +1,152 @@
<?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:Model>
<Resource>../assets/Models/DummyScene.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health>
<Health>60</Health>
</c:Health>
<c:AABB/>
<c:Camera/>
<c:Listener/>
<c:Player/>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="-0.151326105" Y="13.5594187" Z="12.5957394"/>
<Orientation X="-0.872664511" Y="0.157068729" Z="3.01738083e-08"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<HomePointForTeam>3</HomePointForTeam>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="1" G="0.200000003" R="0"/>
</c:Model>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="5.48757935" Y="2.62824345" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<CapturePointNumber>1</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="1" G="1" R="0"/>
</c:Model>
<c:Team/>
<c:Transform>
<Position X="1.91470337" Y="2.32191443" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<CapturePointNumber>2</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="0" G="1" R="1"/>
</c:Model>
<c:Team/>
<c:Transform>
<Position X="-1.31178355" Y="2.16289616" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<HomePointForTeam>2</HomePointForTeam>
<CapturePointNumber>3</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="0" G="0.200000003" R="1"/>
</c:Model>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="-4.27947044" Y="1.99913001" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="0.482352942" G="0.490196079" R="1"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="-5.74354839" Y="2.23822045" Z="-0.0577065349"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="1" G="0.196078435" R="0.196078435"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="6.96941662" Y="2.02053547" Z="-0.0348547697"/>
</c:Transform>
</Components>
<Children/>
</Entity>
</Children>
</Entity>
@@ -0,0 +1,212 @@
<?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:Model>
<Resource>../assets/Models/DummyScene.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health>
<Health>60</Health>
</c:Health>
<c:AABB/>
<c:Camera/>
<c:Listener/>
<c:Player/>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="-0.151326105" Y="13.5594187" Z="12.5957394"/>
<Orientation X="-0.942477643" Y="0.157067701" Z="-1.50870125e-08"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<HomePointForTeam>3</HomePointForTeam>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="1" G="0.200000003" R="0"/>
</c:Model>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="5.39647007" Y="2.36802292" Z="0.0546064377"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<CapturePointNumber>1</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="0" G="1" R="1"/>
</c:Model>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="4.21088505" Y="2.32191443" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<CapturePointNumber>2</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="1" G="1" R="0"/>
</c:Model>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="2.30499458" Y="2.04659939" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<CapturePointNumber>3</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="0" G="0.200000003" R="1"/>
</c:Model>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="0.196968079" Y="1.99913001" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<HomePointForTeam>2</HomePointForTeam>
<CapturePointNumber>4</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="0" G="0.200000003" R="1"/>
</c:Model>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="-1.82539892" Y="1.96172595" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="0.482352942" G="0.490196079" R="1"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="1.15194035" Y="2.23822045" Z="-0.0577065349"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="0.482352942" G="0.490196079" R="1"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="-0.266237378" Y="2.23822045" Z="0.344228983"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="1" G="0.196078435" R="0.196078435"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="6.96941662" Y="2.02053547" Z="1.9484092"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="1" G="0.196078435" R="0.196078435"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="3.63076782" Y="2.5672617" Z="-0.0348547697"/>
</c:Transform>
</Components>
<Children/>
</Entity>
</Children>
</Entity>
@@ -0,0 +1,205 @@
<?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:Model>
<Resource>../assets/Models/DummyScene.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health>
<Health>60</Health>
</c:Health>
<c:AABB/>
<c:Camera/>
<c:Listener/>
<c:Player/>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="-0.151326105" Y="13.5594187" Z="12.5957394"/>
<Orientation X="-0.62831825" Y="0.0872534811" Z="-7.47903606e-09"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<HomePointForTeam>3</HomePointForTeam>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="1" G="0.200000003" R="0"/>
</c:Model>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="5.39647007" Y="2.36802292" Z="0.0546064377"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<CapturePointNumber>1</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="1" G="1" R="0"/>
</c:Model>
<c:Team/>
<c:Transform>
<Position X="3.68890452" Y="2.32191443" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<CapturePointNumber>2</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
</c:Model>
<c:Team/>
<c:Transform>
<Position X="1.98802853" Y="2.16289616" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<CapturePointNumber>3</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="0" G="1" R="1"/>
</c:Model>
<c:Team/>
<c:Transform>
<Position X="0.196968079" Y="1.99913001" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<HomePointForTeam>2</HomePointForTeam>
<CapturePointNumber>4</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="0" G="0.200000003" R="1"/>
</c:Model>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="-1.82539892" Y="1.96172595" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="0.482352942" G="0.490196079" R="1"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="-7.44269609" Y="2.23822045" Z="-0.0577065349"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="0.482352942" G="0.490196079" R="1"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="-5.74354839" Y="2.23822045" Z="1.40012479"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="1" G="0.196078435" R="0.196078435"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="6.96941662" Y="2.02053547" Z="1.9484092"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="1" G="0.196078435" R="0.196078435"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="7.70311165" Y="2.02053547" Z="-0.0348547697"/>
</c:Transform>
</Components>
<Children/>
</Entity>
</Children>
</Entity>
+52 -2
View File
@@ -13,6 +13,7 @@
</c:Model> </c:Model>
<c:Transform> <c:Transform>
<Scale X="100" Y="1" Z="100"/> <Scale X="100" Y="1" Z="100"/>
<Orientation X="0" Y="2.59200001" Z="0"/>
</c:Transform> </c:Transform>
</Components> </Components>
<Children/> <Children/>
@@ -45,9 +46,58 @@
<Entity> <Entity>
<Components> <Components>
<c:Camera/> <c:Camera/>
<c:Listener/>
<c:Transform> <c:Transform>
<Position X="5.85247707" Y="3.8454349" Z="-1.14486957"/> <Position X="1.36896265" Y="4.4259491" Z="10.6640663"/>
<Orientation X="2.51327395" Y="1.23916209" Z="-3.1415925"/> <Orientation X="-0.0349078141" Y="0.157154545" Z="-2.60252193e-07"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:DirectionalLight/>
<c:Model>
<Resource>Models/DirectionalLightWidget.obj</Resource>
</c:Model>
<c:Transform>
<Position X="2.1529963" Y="6.59221172" Z="0.169116676"/>
<Orientation X="4.32000017" Y="4.6340003" Z="0"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Model>
<Resource>Models/Assault.obj</Resource>
</c:Model>
<c:Transform>
<Position X="-2.00568962" Y="0.527161121" Z="0"/>
</c:Transform>
</Components>
<Children>
<Entity>
<Components>
<c:Model>
<Resource>Models/SecondaryWeapon.fbx</Resource>
</c:Model>
<c:Transform>
<Position X="-0.546139359" Y="0.853016734" Z="0.177482292"/>
<Orientation X="1.47266471" Y="0.524984181" Z="1.243698"/>
</c:Transform>
</Components>
<Children/>
</Entity>
</Children>
</Entity>
<Entity>
<Components>
<c:Model>
<Resource>Models/Core/UnitSphere.obj</Resource>
</c:Model>
<c:Transform>
<Position X="0" Y="3.70000029" Z="0"/>
</c:Transform> </c:Transform>
</Components> </Components>
<Children/> <Children/>
+4 -2
View File
@@ -19,6 +19,7 @@
<xs:element ref="c:AABB" minOccurs="0"/> <xs:element ref="c:AABB" minOccurs="0"/>
<xs:element ref="c:Trigger" minOccurs="0"/> <xs:element ref="c:Trigger" minOccurs="0"/>
<xs:element ref="c:Health" minOccurs="0"/> <xs:element ref="c:Health" minOccurs="0"/>
<xs:element ref="c:CapturePoint" minOccurs="0"/>
<xs:element ref="c:PointLight" minOccurs="0"/> <xs:element ref="c:PointLight" minOccurs="0"/>
<xs:element ref="c:Listener" minOccurs="0"/> <xs:element ref="c:Listener" minOccurs="0"/>
<xs:element ref="c:SoundEmitter" minOccurs="0"/> <xs:element ref="c:SoundEmitter" minOccurs="0"/>
@@ -27,6 +28,7 @@
<xs:element ref="c:SpawnPoint" minOccurs="0"/> <xs:element ref="c:SpawnPoint" minOccurs="0"/>
<xs:element ref="c:PlayerSpawn" minOccurs="0"/> <xs:element ref="c:PlayerSpawn" minOccurs="0"/>
<xs:element ref="c:Team" minOccurs="0"/> <xs:element ref="c:Team" minOccurs="0"/>
<xs:element ref="c:DirectionalLight" minOccurs="0"/>
<xs:element ref="c:UniformScale" minOccurs="0"/> <xs:element ref="c:UniformScale" minOccurs="0"/>
<xs:element ref="c:EditorWidget" minOccurs="0"/> <xs:element ref="c:EditorWidget" minOccurs="0"/>
</xs:all> </xs:all>
@@ -39,7 +41,7 @@
<xs:element ref="Entity" minOccurs="0" maxOccurs="unbounded"/> <xs:element ref="Entity" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="EntityRef" minOccurs="0" maxOccurs="unbounded"> <xs:element name="EntityRef" minOccurs="0" maxOccurs="unbounded">
<xs:complexType> <xs:complexType>
<xs:attribute name="file" type="xs:string" minOccurs="0"/> <xs:attribute name="file" type="xs:string" minOccurs="0"/>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
</xs:sequence> </xs:sequence>
@@ -47,7 +49,7 @@
</xs:element> </xs:element>
</xs:all> </xs:all>
<xs:attribute ref="xml:base"/> <xs:attribute ref="xml:base"/>
<xs:attribute name="name" type="xs:string" minOccurs="0" default=""/> <xs:attribute name="name" type="xs:string" minOccurs="0" default=""/>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
</xs:schema> </xs:schema>
+16 -13
View File
@@ -27,19 +27,20 @@ layout (std430, binding = 0) buffer FrustumBuffer
Frustum Data[]; Frustum Data[];
} Frustums; } Frustums;
struct PointLight { struct LightSource {
vec4 Position; vec4 Position;
vec4 Direction;
vec4 Color; vec4 Color;
float Radius; float Radius;
float Intensity; float Intensity;
float Falloff; float Falloff;
float Padding; int Type;
}; };
layout (std430, binding = 1) buffer LightBuffer layout (std430, binding = 1) buffer LightBuffer
{ {
PointLight List[]; LightSource List[];
} PointLights; } LightSources;
struct LightGrid { struct LightGrid {
float Start; float Start;
@@ -106,8 +107,7 @@ layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
void main () void main ()
{ {
GroupIndex = int(gl_WorkGroupID.x + (gl_WorkGroupID.y * int(ScreenDimensions.x/TILE_SIZE))); GroupIndex = int(gl_WorkGroupID.x + (gl_WorkGroupID.y * int(ScreenDimensions.x/TILE_SIZE)));
if(gl_LocalInvocationIndex == 0) if(gl_LocalInvocationIndex == 0) {
{
GroupLightCount = 0; GroupLightCount = 0;
GroupFrustum = Frustums.Data[GroupIndex]; GroupFrustum = Frustums.Data[GroupIndex];
} }
@@ -115,22 +115,25 @@ void main ()
barrier(); barrier();
memoryBarrierShared(); memoryBarrierShared();
for(int i = int(gl_LocalInvocationIndex); i < PointLights.List.length(); i += TILE_SIZE*TILE_SIZE) for(int i = int(gl_LocalInvocationIndex); i < LightSources.List.length(); i += TILE_SIZE*TILE_SIZE) {
{ LightSource light = LightSources.List[i];
PointLight light = PointLights.List[i];
//if pointlight //if pointlight
//Pos i view antagligen //Pos i view antagligen
if(SphereInsideFrustrum( vec3(V * light.Position), light.Radius, GroupFrustum)) if(light.Type == 1) {
{ if(SphereInsideFrustrum( vec3(V * light.Position), light.Radius, GroupFrustum)) {
//TODO: Fix transparent and opaque list, and depth test. //TODO: Fix transparent and opaque list, and depth test.
AppendLight( i ); AppendLight( i );
}
} }
//if conelight //if conelight
//if directional //if directional
if(light.Type == 2) {
AppendLight( i );
}
} }
+39 -20
View File
@@ -9,19 +9,20 @@ uniform sampler2D texture0;
#define TILE_SIZE 16 #define TILE_SIZE 16
struct PointLight { struct LightSource {
vec4 Position; vec4 Position;
vec4 Direction;
vec4 Color; vec4 Color;
float Radius; float Radius;
float Intensity; float Intensity;
float Falloff; float Falloff;
float Padding; int Type;
}; };
layout (std430, binding = 1) buffer LightBuffer layout (std430, binding = 1) buffer LightBuffer
{ {
PointLight List[]; LightSource List[];
} PointLights; } LightSources;
struct LightGrid { struct LightGrid {
float Start; float Start;
@@ -71,7 +72,7 @@ vec4 CalcDiffuse(vec4 lightColor, vec4 lightVec, vec4 normal) {
return lightColor * power; return lightColor * power;
} }
LightResult CalcPointLight(vec4 lightPos, float lightRadius, vec4 lightColor, float intensity, vec4 viewVec, vec4 position, vec4 normal, float falloff) LightResult CalcPointLightSource(vec4 lightPos, float lightRadius, vec4 lightColor, float intensity, vec4 viewVec, vec4 position, vec4 normal, float falloff)
{ {
vec4 L = lightPos - position; vec4 L = lightPos - position;
float dist = length(L); float dist = length(L);
@@ -85,6 +86,16 @@ LightResult CalcPointLight(vec4 lightPos, float lightRadius, vec4 lightColor, fl
return result; return result;
} }
LightResult CalcDirectionalLightSource(vec4 direction, vec4 color, float intensity, vec4 viewVec, vec4 vertNormal)
{
vec4 L = normalize( -vec4(direction.xyz, 0) );
LightResult result;
result.Diffuse = CalcDiffuse(color, L, vertNormal) * intensity;
result.Specular = CalcSpecular(color, viewVec, L, vertNormal) * intensity;
return result;
}
void main() void main()
{ {
@@ -94,8 +105,8 @@ void main()
vec4 viewVec = normalize(-position); vec4 viewVec = normalize(-position);
vec2 tilePos; vec2 tilePos;
tilePos.x = int(gl_FragCoord.x/16); tilePos.x = int(gl_FragCoord.x/TILE_SIZE);
tilePos.y = int(gl_FragCoord.y/16); tilePos.y = int(gl_FragCoord.y/TILE_SIZE);
LightResult totalLighting; LightResult totalLighting;
totalLighting.Diffuse = scene_ambient; totalLighting.Diffuse = scene_ambient;
@@ -103,30 +114,38 @@ void main()
int start = int(LightGrids.Data[currentTile].Start); int start = int(LightGrids.Data[currentTile].Start);
int amount = int(LightGrids.Data[currentTile].Amount); int amount = int(LightGrids.Data[currentTile].Amount);
//for(int i = 0; i < 3; i++)
for(int i = start; i < start + amount; i++) for(int i = start; i < start + amount; i++) {
{
int l = int(LightIndex[i]); int l = int(LightIndex[i]);
LightSource light = LightSources.List[l];
LightResult result = CalcPointLight(V * PointLights.List[l].Position, PointLights.List[l].Radius, PointLights.List[l].Color, PointLights.List[l].Intensity, viewVec, position, normal, PointLights.List[i].Falloff); LightResult result;
if(light.Type == 1) { // point
result = CalcPointLightSource(V * light.Position, light.Radius, light.Color, light.Intensity, viewVec, position, normal, light.Falloff);
} else if (light.Type == 2) { //Directional
result = CalcDirectionalLightSource(V * light.Direction, light.Color, light.Intensity, viewVec, normal);
}
totalLighting.Diffuse += result.Diffuse; totalLighting.Diffuse += result.Diffuse;
totalLighting.Specular += result.Specular; totalLighting.Specular += result.Specular;
} }
//fragmentColor += Input.DiffuseColor;
fragmentColor += Input.DiffuseColor * (totalLighting.Diffuse + totalLighting.Specular) * texel * Color; fragmentColor += Input.DiffuseColor * (totalLighting.Diffuse + totalLighting.Specular) * texel * Color;
//fragmentColor += Input.DiffuseColor * (totalLighting.Diffuse) * texel * Color; //fragmentColor += Input.DiffuseColor * (totalLighting.Diffuse) * texel * Color;
//fragmentColor += vec4(0.0, LightGrids.Data[currentTile].Amount/3.0, 0, 1); //fragmentColor += Input.DiffuseColor + vec4(0.0, LightGrids.Data[currentTile].Amount/3, 0, 1);
//fragmentColor = texel * Input.DiffuseColor * Color; //fragmentColor = texel * Input.DiffuseColor * Color;
if(int(gl_FragCoord.x)%16 == 0 || int(gl_FragCoord.y)%16 == 0 ) //fragmentColor += vec4(currentTile/3600.f, 0, 0, 1);
{
//fragmentColor += vec4(0.5, 0, 0, 0); //Tiled Debug Code
/*
if(int(gl_FragCoord.x)%16 == 0 || int(gl_FragCoord.y)%16 == 0 ) {
fragmentColor += vec4(0.5, 0, 0, 0);
} else { } else {
//fragmentColor += vec4(LightGrids.Data[int(tilePos.x + tilePos.y*80)].Amount/3.0, 0, 0, 1); fragmentColor += vec4(LightGrids.Data[int(tilePos.x + tilePos.y*80)].Amount/LightSources.List.length(), 0, 0, 1);
} }
*/
} }
+1 -1
View File
@@ -29,6 +29,6 @@ void main()
Output.Position = Position; Output.Position = Position;
Output.TextureCoordinate = TextureCoords; Output.TextureCoordinate = TextureCoords;
Output.Normal = Normal; Output.Normal = vec3(M * vec4(Normal, 0.0));
Output.DiffuseColor = DiffuseVertexColor; Output.DiffuseColor = DiffuseVertexColor;
} }
+3 -5
View File
@@ -23,17 +23,15 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c
// Collide against octree // Collide against octree
std::vector<AABB> octreeResult; std::vector<AABB> octreeResult;
m_Octree->BoxesInSameRegion(*boundingBox, octreeResult); m_Octree->ObjectsInSameRegion(*boundingBox, octreeResult);
for (auto& boxB : octreeResult) { for (auto& boxB : octreeResult) {
glm::vec3 resolutionVector; glm::vec3 resolutionVector;
if (Collision::IsSameBoxProbably(boxA, boxB)) { if (Collision::IsSameBoxProbably(boxA, boxB)) {
continue; continue;
} }
if (Collision::AABBVsAABB(boxA, boxB, resolutionVector)) { if (Collision::AABBVsAABB(boxA, boxB, resolutionVector)) {
if (entity.HasComponent("Physics")) { (glm::vec3&)cTransform["Position"] += resolutionVector;
(glm::vec3&)cTransform["Position"] += resolutionVector; cPhysics["Velocity"] = glm::vec3(0, 0, 0);
cPhysics["Velocity"] = glm::vec3(0, 0, 0);
}
} }
} }
+23 -3
View File
@@ -34,9 +34,12 @@ void TriggerSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& com
throwLeaveIfWasInTrigger(m_EntitiesCompletelyInTrigger[tId], pId, tId); throwLeaveIfWasInTrigger(m_EntitiesCompletelyInTrigger[tId], pId, tId);
} else { } else {
//Entity is at least touching the trigger. //Entity is at least touching the trigger.
AABB completelyInsideBox = AABB::FromOriginSize((*triggerBox).Origin(), (*triggerBox).Size() - 2.0f * (*playerBox).Size()); AABB completelyInsideBox;
if (Collision::AABBVsAABB(completelyInsideBox, *playerBox) && bool playerFitsInTrigger = glm::all(glm::greaterThan((*triggerBox).Size(), (*playerBox).Size()));
glm::all(glm::greaterThan((*triggerBox).Size(), (*playerBox).Size()))) { if (playerFitsInTrigger) {
completelyInsideBox = AABB::FromOriginSize((*triggerBox).Origin(), (*triggerBox).Size() - 2.0f * (*playerBox).Size());
}
if (playerFitsInTrigger && Collision::AABBVsAABB(completelyInsideBox, *playerBox)) {
//Entity is completely inside the trigger. //Entity is completely inside the trigger.
//If it was only touching before, it is erased. //If it was only touching before, it is erased.
m_EntitiesTouchingTrigger[tId].erase(pId); m_EntitiesTouchingTrigger[tId].erase(pId);
@@ -78,3 +81,20 @@ bool TriggerSystem::throwLeaveIfWasInTrigger(std::unordered_set<EntityID>& trigg
return false; return false;
} }
bool TriggerSystem::OnTouch(const Events::TriggerTouch &event)
{
LOG_INFO("Player entity %i touched trigger entity %i.", event.Entity, event.Trigger);
return true;
}
bool TriggerSystem::OnEnter(const Events::TriggerEnter &event)
{
LOG_INFO("Player entity %i entered trigger entity %i.", event.Entity, event.Trigger);
return true;
}
bool TriggerSystem::OnLeave(const Events::TriggerLeave &event)
{
LOG_INFO("Player entity %i left trigger entity %i.", event.Entity, event.Trigger);
return true;
}
+2
View File
@@ -15,6 +15,8 @@ AABB::AABB(const glm::vec3& minPos, const glm::vec3& maxPos)
m_MinCorner.y = glm::min(m_MaxCorner.y, m_MinCorner.y); m_MinCorner.y = glm::min(m_MaxCorner.y, m_MinCorner.y);
m_MaxCorner.z = glm::max(m_MaxCorner.z, m_MinCorner.z); m_MaxCorner.z = glm::max(m_MaxCorner.z, m_MinCorner.z);
m_MinCorner.z = glm::min(m_MaxCorner.z, m_MinCorner.z); m_MinCorner.z = glm::min(m_MaxCorner.z, m_MinCorner.z);
m_Origin = 0.5f * (m_MaxCorner + m_MinCorner);
m_HalfSize = 0.5f * (m_MaxCorner - m_MinCorner);
} }
} }
+5
View File
@@ -71,6 +71,11 @@ ComponentPool::iterator ComponentPool::end() const
return iterator(m_ComponentInfo, m_Pool.end(), m_Pool.end()); return iterator(m_ComponentInfo, m_Pool.end(), m_Pool.end());
} }
size_t ComponentPool::size() const
{
return m_Pool.size();
}
template <typename InterpretType /*= char*/> template <typename InterpretType /*= char*/>
void ComponentPool::Dump() const void ComponentPool::Dump() const
{ {
+5
View File
@@ -0,0 +1,5 @@
#include "Core/MemoryPool.h"
namespace DisableMemoryPool
{
bool Value = false;
}
+26 -115
View File
@@ -21,72 +21,11 @@ bool isFirstLower(const ChildInfo& first, const ChildInfo& second)
} }
Octree::Octree(const AABB& octTreeBounds, int subDivisions) namespace OctSpace
: m_Root(new Child(octTreeBounds, subDivisions, m_StaticObjects, m_DynamicObjects))
, m_UpdatedOnce(false)
{ }
Octree::~Octree()
{ {
delete m_Root;
}
void Octree::AddDynamicObject(const AABB& box) Child::Child(const AABB& octTreeBounds,
{ int subDivisions,
m_Root->AddDynamicObject(box);
m_DynamicObjects.push_back(box);
}
void Octree::AddStaticObject(const AABB& box)
{
m_Root->AddStaticObject(box);
m_StaticObjects.push_back(box);
}
void Octree::BoxesInSameRegion(const AABB& box, std::vector<AABB>& outBoxes)
{
falsifyObjectChecks();
m_Root->BoxesInSameRegion(box, outBoxes);
}
void Octree::ClearObjects()
{
m_StaticObjects.clear();
m_DynamicObjects.clear();
m_Root->ClearObjects();
}
void Octree::ClearDynamicObjects()
{
m_DynamicObjects.clear();
m_Root->ClearDynamicObjects();
}
bool Octree::RayCollides(const Ray& ray, Output& data)
{
falsifyObjectChecks();
data.CollideDistance = -1;
return m_Root->RayCollides(ray, data);
}
bool Octree::BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected)
{
falsifyObjectChecks();
return m_Root->BoxCollides(boxToTest, outBoxIntersected);
}
void Octree::falsifyObjectChecks()
{
for (auto& obj : m_StaticObjects) {
obj.Checked = false;
}
for (auto& obj : m_DynamicObjects) {
obj.Checked = false;
}
}
Octree::Child::Child(const AABB& octTreeBounds,
int subDivisions,
std::vector<ContainedObject>& staticObjects, std::vector<ContainedObject>& staticObjects,
std::vector<ContainedObject>& dynamicObjects) std::vector<ContainedObject>& dynamicObjects)
: m_Box(octTreeBounds) : m_Box(octTreeBounds)
@@ -135,7 +74,7 @@ Octree::Child::Child(const AABB& octTreeBounds,
} }
} }
Octree::Child::~Child() Child::~Child()
{ {
for (Child*& c : m_Children) { for (Child*& c : m_Children) {
if (c != nullptr) { if (c != nullptr) {
@@ -145,7 +84,7 @@ Octree::Child::~Child()
} }
} }
bool Octree::Child::BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const bool Child::BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const
{ {
if (hasChildren()) { if (hasChildren()) {
for (int i : childIndicesContainingBox(boxToTest)) { for (int i : childIndicesContainingBox(boxToTest)) {
@@ -155,7 +94,7 @@ bool Octree::Child::BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected)
} else { } else {
for (int i : m_StaticObjIndices) { for (int i : m_StaticObjIndices) {
if (!m_StaticObjectsRef[i].Checked) { if (!m_StaticObjectsRef[i].Checked) {
const AABB& objBox = m_StaticObjectsRef[i].Box; const AABB& objBox = *m_StaticObjectsRef[i].Box;
if (Collision::AABBVsAABB(boxToTest, objBox)) { if (Collision::AABBVsAABB(boxToTest, objBox)) {
outBoxIntersected = objBox; outBoxIntersected = objBox;
return true; return true;
@@ -165,7 +104,7 @@ bool Octree::Child::BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected)
} }
for (int i : m_DynamicObjIndices) { for (int i : m_DynamicObjIndices) {
if (!m_DynamicObjectsRef[i].Checked) { if (!m_DynamicObjectsRef[i].Checked) {
const AABB& objBox = m_DynamicObjectsRef[i].Box; const AABB& objBox = *m_DynamicObjectsRef[i].Box;
if (!Collision::IsSameBoxProbably(boxToTest, objBox) && if (!Collision::IsSameBoxProbably(boxToTest, objBox) &&
Collision::AABBVsAABB(boxToTest, objBox)) { Collision::AABBVsAABB(boxToTest, objBox)) {
outBoxIntersected = objBox; outBoxIntersected = objBox;
@@ -178,7 +117,7 @@ bool Octree::Child::BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected)
return false; return false;
} }
bool Octree::Child::RayCollides(const Ray& ray, Output& data) const bool Child::RayCollides(const Ray& ray, OctSpace::Output& data) const
{ {
//If the node AABB is missed, everything it contains is missed. //If the node AABB is missed, everything it contains is missed.
if (Collision::RayAABBIntr(ray, m_Box)) { if (Collision::RayAABBIntr(ray, m_Box)) {
@@ -205,7 +144,7 @@ bool Octree::Child::RayCollides(const Ray& ray, Output& data) const
float dist; float dist;
//If we haven't tested against this object before, and the ray hits. //If we haven't tested against this object before, and the ray hits.
if (!m_StaticObjectsRef[i].Checked && if (!m_StaticObjectsRef[i].Checked &&
Collision::RayVsAABB(ray, m_StaticObjectsRef[i].Box, dist)) { Collision::RayVsAABB(ray, *m_StaticObjectsRef[i].Box, dist)) {
minDist = std::min(dist, minDist); minDist = std::min(dist, minDist);
intersected = true; intersected = true;
} }
@@ -215,7 +154,7 @@ bool Octree::Child::RayCollides(const Ray& ray, Output& data) const
float dist; float dist;
//If we haven't tested against this object before, and the ray hits. //If we haven't tested against this object before, and the ray hits.
if (!m_DynamicObjectsRef[i].Checked && if (!m_DynamicObjectsRef[i].Checked &&
Collision::RayVsAABB(ray, m_DynamicObjectsRef[i].Box, dist)) { Collision::RayVsAABB(ray, *m_DynamicObjectsRef[i].Box, dist)) {
minDist = std::min(dist, minDist); minDist = std::min(dist, minDist);
intersected = true; intersected = true;
} }
@@ -230,7 +169,7 @@ bool Octree::Child::RayCollides(const Ray& ray, Output& data) const
} }
void Octree::Child::AddDynamicObject(const AABB& box) void Child::AddDynamicObject(const AABB& box)
{ {
if (hasChildren()) { if (hasChildren()) {
for (auto i : childIndicesContainingBox(box)) { for (auto i : childIndicesContainingBox(box)) {
@@ -242,7 +181,7 @@ void Octree::Child::AddDynamicObject(const AABB& box)
} }
} }
void Octree::Child::AddStaticObject(const AABB& box) void Child::AddStaticObject(const AABB& box)
{ {
if (hasChildren()) { if (hasChildren()) {
for (auto i : childIndicesContainingBox(box)) { for (auto i : childIndicesContainingBox(box)) {
@@ -254,41 +193,7 @@ void Octree::Child::AddStaticObject(const AABB& box)
} }
} }
void Octree::Child::BoxesInSameRegion(const AABB& box, std::vector<AABB>& outBoxes) const void Child::ClearObjects()
{
if (hasChildren()) {
for (auto i : childIndicesContainingBox(box)) {
m_Children[i]->BoxesInSameRegion(box, outBoxes);
}
} else {
size_t startIndex = outBoxes.size();
int numDuplicates = 0;
outBoxes.resize(outBoxes.size() + m_StaticObjIndices.size() + m_DynamicObjIndices.size());
for (size_t i = 0; i < m_StaticObjIndices.size(); ++i){
ContainedObject& obj = m_StaticObjectsRef[m_StaticObjIndices[i]];
if (obj.Checked) {
++numDuplicates;
} else {
obj.Checked = true;
outBoxes[startIndex + i - numDuplicates] = obj.Box;
}
}
for (size_t i = 0; i < m_DynamicObjIndices.size(); ++i) {
ContainedObject& obj = m_DynamicObjectsRef[m_DynamicObjIndices[i]];
if (obj.Checked) {
++numDuplicates;
} else {
obj.Checked = true;
outBoxes[startIndex + i - numDuplicates] = obj.Box;
}
}
for (size_t i = 0; i < numDuplicates; ++i) {
outBoxes.pop_back();
}
}
}
void Octree::Child::ClearObjects()
{ {
if (hasChildren()) { if (hasChildren()) {
for (Child*& c : m_Children) { for (Child*& c : m_Children) {
@@ -300,11 +205,11 @@ void Octree::Child::ClearObjects()
} }
} }
void Octree::Child::ClearDynamicObjects() void Child::ClearDynamicObjects()
{ {
if (hasChildren()) { if (hasChildren()) {
for (Child*& c : m_Children) { for (Child*& c : m_Children) {
c->ClearObjects(); c->ClearDynamicObjects();
} }
} else { } else {
m_DynamicObjIndices.clear(); m_DynamicObjIndices.clear();
@@ -323,13 +228,13 @@ void Octree::Child::ClearDynamicObjects()
// x : - - - - + + + + // x : - - - - + + + +
// y : - - + + - - + + // y : - - + + - - + +
// z : - + - + - + - + // z : - + - + - + - +
int Octree::Child::childIndexContainingPoint(const glm::vec3& point) const int Child::childIndexContainingPoint(const glm::vec3& point) const
{ {
const glm::vec3& c = m_Box.Origin(); const glm::vec3& c = m_Box.Origin();
return (1 << 2) * (point.x >= c.x) | (1 << 1) * (point.y >= c.y) | (point.z >= c.z); return (1 << 2) * (point.x >= c.x) | (1 << 1) * (point.y >= c.y) | (point.z >= c.z);
} }
std::vector<int> Octree::Child::childIndicesContainingBox(const AABB& box) const std::vector<int> Child::childIndicesContainingBox(const AABB& box) const
{ {
int minInd = childIndexContainingPoint(box.MinCorner()); int minInd = childIndexContainingPoint(box.MinCorner());
int maxInd = childIndexContainingPoint(box.MaxCorner()); int maxInd = childIndexContainingPoint(box.MaxCorner());
@@ -352,9 +257,13 @@ std::vector<int> Octree::Child::childIndicesContainingBox(const AABB& box) const
//the dimensions they are responsible for (which octant). //the dimensions they are responsible for (which octant).
bits.flip(); bits.flip();
//At this point the bits necessarily have exactly one bit set. //At this point the bits necessarily have exactly one bit set.
//Check the same bit in the minInd as the one set in bits.
int setOrUnset = (bits.to_ulong() & minInd);
for (int c = 0; c < 8; ++c) { for (int c = 0; c < 8; ++c) {
//If the child index have the same bit set as the bits, add box to it. //Check the same bit in the child index as the one set in bits.
if (bits.to_ulong() & c) { //Enter here if both c and minInd have the bit set, or if neither have it set.
//I.e, if they are on the same side (+ or -) in the dimension marked by the bit in bits.
if (!((bits.to_ulong() & c) ^ setOrUnset)) {
ret.push_back(c); ret.push_back(c);
} }
} }
@@ -367,7 +276,9 @@ std::vector<int> Octree::Child::childIndicesContainingBox(const AABB& box) const
} }
} }
inline bool Octree::Child::hasChildren() const inline bool Child::hasChildren() const
{ {
return m_Children[0] != nullptr; return m_Children[0] != nullptr;
}
} }
+1 -1
View File
@@ -48,7 +48,7 @@ void EditorRenderSystem::Update(double dt)
EntityWrapper entity(m_World, cModel.EntityID); EntityWrapper entity(m_World, cModel.EntityID);
glm::mat4 modelMatrix = Transform::ModelMatrix(entity.ID, entity.World); glm::mat4 modelMatrix = Transform::ModelMatrix(entity.ID, entity.World);
for (auto matGroup : model->MaterialGroups()) { for (auto matGroup : model->MaterialGroups()) {
std::shared_ptr<ModelJob> modelJob = std::make_shared<ModelJob>(model, nullptr, modelMatrix, matGroup, cModel, entity.World); std::shared_ptr<ModelJob> modelJob = std::make_shared<ModelJob>(model, scene.Camera, modelMatrix, matGroup, cModel, entity.World);
scene.ForwardJobs.push_back(modelJob); scene.ForwardJobs.push_back(modelJob);
} }
} }
+155 -130
View File
@@ -5,28 +5,27 @@ using namespace boost::asio::ip;
Client::Client(ConfigFile* config) : m_Socket(m_IOService) Client::Client(ConfigFile* config) : m_Socket(m_IOService)
{ {
// Asumes root node is EntityID 0
insertIntoServerClientMaps(0, 0);
// Default is local host // Default is local host
std::string address = config->Get<std::string>("Networking.Address", "127.0.0.1"); std::string address = config->Get<std::string>("Networking.Address", "127.0.0.1");
int port = config->Get<int>("Networking.Port", 13); int port = config->Get<int>("Networking.Port", 13);
m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string(address), port); m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string(address), port);
// Set up network stream // Set up network stream
m_PlayerName = config->Get<std::string>("Networking.Name", "Raptorcopter"); m_PlayerName = config->Get<std::string>("Networking.Name", "Raptorcopter");
m_NextSnapshot.InputForward = "";
m_NextSnapshot.InputRight = "";
} }
Client::~Client() Client::~Client()
{ { }
}
void Client::Start(World* world, EventBroker* eventBroker) void Client::Start(World* world, EventBroker* eventBroker)
{ {
m_WasStarted = true;
m_EventBroker = eventBroker; m_EventBroker = eventBroker;
m_World = world; m_World = world;
// Subscribe to events // Subscribe to events
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Client::OnInputCommand); EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Client::OnInputCommand);
EVENT_SUBSCRIBE_MEMBER(m_EPlayeDamage, &Client::OnPlayerDamage);
m_Socket.connect(m_ReceiverEndpoint); m_Socket.connect(m_ReceiverEndpoint);
LOG_INFO("I am client. BIP BOP"); LOG_INFO("I am client. BIP BOP");
@@ -34,7 +33,11 @@ void Client::Start(World* world, EventBroker* eventBroker)
void Client::Update() void Client::Update()
{ {
m_EventBroker->Process<Client>();
readFromServer(); readFromServer();
if (m_IsConnected) {
hasServerTimedOut();
}
} }
void Client::readFromServer() void Client::readFromServer()
@@ -46,58 +49,7 @@ void Client::readFromServer()
parseMessageType(packet); parseMessageType(packet);
} }
} }
std::clock_t currentTime = std::clock(); sendInputCommands();
if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) {
if (isConnected()) {
//sendSnapshotToServer();
}
previousSnapshotMessage = currentTime;
}
}
void Client::sendSnapshotToServer()
{
// Reset previous key state in snapshot.
m_NextSnapshot.InputForward = "";
m_NextSnapshot.InputRight = "";
auto player = m_World->GetComponent(m_PlayerDefinitions[m_PlayerID].EntityID, "Player");
// See if any movement keys are down
// We dont care if it's overwritten by later
// if statement. Watcha gonna do, right!
if (player["Forward"]) {
m_NextSnapshot.InputForward = "+Forward";
}
if (player["Left"]) {
m_NextSnapshot.InputRight = "-Right";
}
if (player["Back"]) {
m_NextSnapshot.InputForward = "-Forward";
}
if (player["Right"]) {
m_NextSnapshot.InputRight = "+Right";
}
if (m_NextSnapshot.InputForward != "") {
Packet packet(MessageType::Event, m_SendPacketID);
packet.WriteString(m_NextSnapshot.InputForward);
send(packet);
} else {
Packet packet(MessageType::Event, m_SendPacketID);
packet.WriteString("0Forward");
send(packet);
}
if (m_NextSnapshot.InputRight != "") {
Packet packet(MessageType::Event, m_SendPacketID);
packet.WriteString(m_NextSnapshot.InputRight);
send(packet);
} else {
Packet packet(MessageType::Event, m_SendPacketID);
packet.WriteString("0Right");
send(packet);
}
} }
void Client::parseMessageType(Packet& packet) void Client::parseMessageType(Packet& packet)
@@ -108,9 +60,7 @@ void Client::parseMessageType(Packet& packet)
// Read packet ID // Read packet ID
m_PreviousPacketID = m_PacketID; // Set previous packet id m_PreviousPacketID = m_PacketID; // Set previous packet id
m_PacketID = packet.ReadPrimitive<int>(); //Read new packet id m_PacketID = packet.ReadPrimitive<int>(); //Read new packet id
if (m_PacketID <= m_PreviousPacketID) identifyPacketLoss();
return;
//IdentifyPacketLoss();
switch (static_cast<MessageType>(messageType)) { switch (static_cast<MessageType>(messageType)) {
case MessageType::Connect: case MessageType::Connect:
@@ -129,9 +79,8 @@ void Client::parseMessageType(Packet& packet)
break; break;
case MessageType::Disconnect: case MessageType::Disconnect:
break; break;
case MessageType::Event: case MessageType::PlayerConnected:
parseEventMessage(packet); parsePlayerConnected(packet);
break;
default: default:
break; break;
} }
@@ -139,34 +88,52 @@ void Client::parseMessageType(Packet& packet)
void Client::parseConnect(Packet& packet) void Client::parseConnect(Packet& packet)
{ {
m_PlayerID = packet.ReadPrimitive<int>(); // Map ServerEntityID and your PlayerID
LOG_INFO("%i: I am player: %i", m_PacketID, m_PlayerID); LOG_INFO("I be connected PogChamp");
}
void Client::parsePlayerConnected(Packet & packet)
{
// Map ServerEntityID and other player's PlayerID
LOG_INFO("A Player connected");
} }
void Client::parsePing() void Client::parsePing()
{ {
m_DurationOfPingTime = 1000 * (std::clock() - m_StartPingTime) / static_cast<double>(CLOCKS_PER_SEC);
LOG_INFO("%i: response time with ctime(ms): %f", m_PacketID, m_DurationOfPingTime);
} }
void Client::parseServerPing() void Client::parseServerPing()
{ {
// Might miss connect message so set it here instead.
m_IsConnected = true;
// Time since last ping was received
m_DurationOfPingTime = 1000 * (std::clock() - m_StartPingTime) / static_cast<double>(CLOCKS_PER_SEC);
LOG_INFO("%i: response time with ctime(ms): %f", m_PacketID, m_DurationOfPingTime);
m_StartPingTime = std::clock();
Packet packet(MessageType::ServerPing, m_SendPacketID); Packet packet(MessageType::ServerPing, m_SendPacketID);
packet.WriteString("Ping recieved"); packet.WriteString("Ping recieved");
send(packet); send(packet);
} }
void Client::parseEventMessage(Packet& packet) // Fields with strings will not work right now
void Client::InterpolateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType)
{ {
int Id = -1; int sizeOfFields = 0;
std::string command = packet.ReadString(); for (auto field : componentInfo.FieldsInOrder) {
if (command.find("+Player") != std::string::npos) { ComponentInfo::Field_t fieldInfo = componentInfo.Fields.at(field);
Id = packet.ReadPrimitive<int>(); sizeOfFields += fieldInfo.Stride;
// Sett Player name
m_PlayerDefinitions[Id].Name = command.erase(0, 7);
} else {
LOG_INFO("%i: Event message: %s", m_PacketID, command.c_str());
} }
// Is the size correct?
boost::shared_array<char> eventData(new char[componentInfo.Stride]);
memcpy(eventData.get(), packet.ReadData(componentInfo.Stride), componentInfo.Stride);
//Send event to interpolat system
Events::Interpolate e;
e.Entity = entityID;
e.DataArray = eventData;
m_EventBroker->Publish(e);
} }
void Client::updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType) void Client::updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType)
@@ -182,17 +149,27 @@ void Client::updateFields(Packet& packet, const ComponentInfo& componentInfo, co
} }
} }
// Field parse
void Client::parseSnapshot(Packet& packet) void Client::parseSnapshot(Packet& packet)
{ {
std::string componentType = packet.ReadString(); std::string componentType = packet.ReadString();
while (packet.DataReadSize() < packet.Size()) { while (packet.DataReadSize() < packet.Size()) {
EntityID entityID = packet.ReadPrimitive<EntityID>(); // Components EntityID
EntityID receivedEntityID = packet.ReadPrimitive<EntityID>();
// Parents EntityID
EntityID receivedParentEntityID = packet.ReadPrimitive<EntityID>();
ComponentInfo componentInfo = m_World->GetComponents(componentType)->ComponentInfo(); ComponentInfo componentInfo = m_World->GetComponents(componentType)->ComponentInfo();
if (m_World->ValidEntity(entityID)) { // Check if the received EntityID is mapped to one of our local EntityIDs
if (serverClientMapsHasEntity(receivedEntityID)) {
// Get the local EntityID
EntityID entityID = m_ServerIDToClientID.at(receivedEntityID);
// Check if the component exists
if (m_World->HasComponent(entityID, componentType)) { if (m_World->HasComponent(entityID, componentType)) {
// If the entity and the component exists update it // If the entity and the component exists update it
updateFields(packet, componentInfo, entityID, componentType); if (componentType == "Transform") {
InterpolateFields(packet, componentInfo, entityID, componentType);
} else {
updateFields(packet, componentInfo, entityID, componentType);
}
// if entity exists but not the component // if entity exists but not the component
} else { } else {
// Create component // Create component
@@ -202,11 +179,12 @@ void Client::parseSnapshot(Packet& packet)
} }
// If the entity dosent exist nor the component // If the entity dosent exist nor the component
} else { } else {
//Create Entity // Create Entity
// If entity dosen't exist // If entity dosen't exist
EntityID newEntityID = m_World->CreateEntity(); EntityID newEntityID = m_World->CreateEntity();
insertIntoServerClientMaps(receivedEntityID, newEntityID);
// Check if EntityIDs are out of sync // Check if EntityIDs are out of sync
if (newEntityID != entityID) { if (newEntityID != receivedEntityID) {
LOG_INFO("Client::parseSnapshot(Packet& packet): Newly created EntityID is not the \ LOG_INFO("Client::parseSnapshot(Packet& packet): Newly created EntityID is not the \
same as the one sent by server (EntityIDs are out of sync)"); same as the one sent by server (EntityIDs are out of sync)");
} }
@@ -215,6 +193,21 @@ void Client::parseSnapshot(Packet& packet)
// Copy data to newly created component // Copy data to newly created component
updateFields(packet, componentInfo, newEntityID, componentType); updateFields(packet, componentInfo, newEntityID, componentType);
} }
// Parent Logic
// Don't need to check if receivedEntityID is mapped. (It should have been set)
if (receivedParentEntityID != std::numeric_limits<EntityID>::max()) {
if (serverClientMapsHasEntity(receivedParentEntityID)) {
m_World->SetParent(m_ServerIDToClientID.at(receivedEntityID), m_ServerIDToClientID.at(receivedParentEntityID));
// If Parent dosen't exist create one and map receivedParentEntityID to it.
} else {
// Create the new parent and add it to map
EntityID newParentEntityID = m_World->CreateEntity();
insertIntoServerClientMaps(receivedParentEntityID, newParentEntityID);
// Set the newly created Entity as parent.
m_World->SetParent(m_ServerIDToClientID.at(receivedEntityID), newParentEntityID);
}
}
} }
} }
@@ -228,9 +221,8 @@ int Client::receive(char* data, size_t length)
0, error); 0, error);
if (error) { if (error) {
LOG_ERROR("receive: %s", error.message().c_str()); //LOG_ERROR("receive: %s", error.message().c_str());
} }
return bytesReceived; return bytesReceived;
} }
@@ -252,76 +244,73 @@ void Client::connect()
void Client::disconnect() void Client::disconnect()
{ {
Packet packet(MessageType::Connect, m_SendPacketID); m_PreviousPacketID = 0;
packet.WriteString("+Disconnect"); m_PacketID = 0;
Packet packet(MessageType::Disconnect, m_SendPacketID);
send(packet); send(packet);
} }
void Client::ping() void Client::ping()
{ {
Packet packet(MessageType::Connect, m_SendPacketID); //Packet packet(MessageType::Connect, m_SendPacketID);
packet.WriteString("Ping"); //packet.WriteString("Ping");
m_StartPingTime = std::clock(); //m_StartPingTime = std::clock();
send(packet); //send(packet);
}
void Client::moveMessageHead(char*& data, size_t& length, size_t stepSize)
{
data += stepSize;
length -= stepSize;
} }
bool Client::OnInputCommand(const Events::InputCommand & e) bool Client::OnInputCommand(const Events::InputCommand & e)
{ {
if (isConnected()) {
ComponentWrapper& player = m_World->GetComponent(m_PlayerDefinitions[m_PlayerID].EntityID, "Player");
if (e.Command == "Forward") {
if (e.Value > 0) {
(bool&)player["Forward"] = true;
(bool&)player["Back"] = false;
} else if (e.Value < 0) {
(bool&)player["Back"] = true;
(bool&)player["Forward"] = false;
} else {
(bool&)player["Forward"] = false;
(bool&)player["Back"] = false;
}
}
if (e.Command == "Right") {
if (e.Value > 0) {
(bool&)player["Right"] = true;
(bool&)player["Left"] = false;
} else if (e.Value < 0) {
(bool&)player["Left"] = true;
(bool&)player["Right"] = false;
} else {
(bool&)player["Left"] = false;
(bool&)player["Right"] = false;
}
}
}
if (e.Command == "ConnectToServer") { // Connect for now if (e.Command == "ConnectToServer") { // Connect for now
connect(); if (e.Value > 0) {
connect();
}
//LOG_DEBUG("Client::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID);
return true;
} else if (e.Command == "DisconnectFromServer") {
if (e.Value > 0) {
disconnect();
}
return true;
} else if (e.Command == "SwitchToPlayer") {
if (e.Value > 0) {
becomePlayer();
}
} else {
m_InputCommandBuffer.push_back(e);
//LOG_DEBUG("Client::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID);
return true;
} }
return false; return false;
} }
bool Client::OnPlayerDamage(const Events::PlayerDamage & e)
{
Packet packet(MessageType::OnInputCommand, m_SendPacketID);
packet.WritePrimitive(e.DamageAmount);
packet.WritePrimitive(e.PlayerDamagedID);
packet.WriteString(e.TypeOfDamage);
send(packet);
return false;
}
void Client::identifyPacketLoss() void Client::identifyPacketLoss()
{ {
// if no packets lost, difference should be equal to 1 // if no packets lost, difference should be equal to 1
int difference = m_PacketID - m_PreviousPacketID; int difference = m_PacketID - m_PreviousPacketID;
if (difference != 1) { if (difference != 1) {
LOG_INFO("%i Packet(s) were lost...", difference); LOG_INFO("%i Packet(s) were lost...", difference - 1);
} }
} }
bool Client::isConnected() bool Client::hasServerTimedOut()
{ {
if (m_PlayerID != -1) { // Time in ms
if (m_PlayerDefinitions[m_PlayerID].EntityID != -1) { float timeSincePing = 1000 * (std::clock() - m_StartPingTime) / static_cast<double>(CLOCKS_PER_SEC);
return true; if (timeSincePing > TIMEOUTMS) {
} // Clear everything and go to menu.
LOG_INFO("Server has timed out, returning to menu, Beep Boop.");
m_IsConnected = false;
return true;
} }
return false; return false;
} }
@@ -335,3 +324,39 @@ EntityID Client::createPlayer()
ComponentWrapper player = m_World->AttachComponent(entityID, "Player"); ComponentWrapper player = m_World->AttachComponent(entityID, "Player");
return entityID; return entityID;
} }
void Client::sendInputCommands()
{
if (m_InputCommandBuffer.size() > 0) {
Packet packet(MessageType::OnInputCommand, m_SendPacketID);
for (int i = 0; i < m_InputCommandBuffer.size(); i++) {
packet.WriteString(m_InputCommandBuffer[i].Command);
packet.WritePrimitive(m_InputCommandBuffer[i].Value);
}
send(packet);
m_InputCommandBuffer.clear();
}
}
void Client::becomePlayer()
{
Packet packet = Packet(MessageType::BecomePlayer, m_SendPacketID);
send(packet);
}
bool Client::clientServerMapsHasEntity(EntityID clientEntityID)
{
return m_ClientIDToServerID.find(clientEntityID) != m_ClientIDToServerID.end();
}
bool Client::serverClientMapsHasEntity(EntityID serverEntityID)
{
return m_ServerIDToClientID.find(serverEntityID) != m_ServerIDToClientID.end();
}
void Client::insertIntoServerClientMaps(EntityID serverEntityID, EntityID clientEntityID)
{
m_ServerIDToClientID.insert(std::make_pair(serverEntityID, clientEntityID));
m_ClientIDToServerID.insert(std::make_pair(clientEntityID, serverEntityID));
}
+21 -8
View File
@@ -17,20 +17,26 @@ Packet::Packet(char* data, const int sizeOfPacket)
m_Offset = sizeOfPacket; m_Offset = sizeOfPacket;
} }
Packet::Packet(MessageType type)
{
m_Data = new char[m_MaxPacketSize];
unsigned int dummy = 0;
Init(type, dummy);
}
Packet::~Packet() Packet::~Packet()
{ {
delete[] m_Data; delete[] m_Data;
} }
void Packet::Init(MessageType type, unsigned int & packetID) void Packet::Init(MessageType type, unsigned int & packetID)
{ {
m_ReturnDataOffset = 0; m_ReturnDataOffset = 0;
m_Offset = 0; m_Offset = 0;
// Create message header // Create message header
// Add message type // Add message type
int messageType = static_cast<int>(type); int messageType = static_cast<int>(type);
Packet::WritePrimitive<int>(messageType); Packet::WritePrimitive<int>(messageType);
packetID = packetID % 1000; // Packet id modulos
Packet::WritePrimitive<int>(packetID); Packet::WritePrimitive<int>(packetID);
packetID++; packetID++;
} }
@@ -40,7 +46,7 @@ void Packet::WriteString(const std::string& str)
// Message, add one extra byte for null terminator // Message, add one extra byte for null terminator
int sizeOfString = str.size() + 1; int sizeOfString = str.size() + 1;
if (m_Offset + sizeOfString > m_MaxPacketSize) { if (m_Offset + sizeOfString > m_MaxPacketSize) {
LOG_WARNING("Package::WriteString(): Data size in packet exceeded maximum package size. New size is %i bytes\n", m_MaxPacketSize*2); //LOG_WARNING("Package::WriteString(): Data size in packet exceeded maximum package size. New size is %i bytes\n", m_MaxPacketSize*2);
resizeData(); resizeData();
} }
memcpy(m_Data + m_Offset, str.data(), sizeOfString * sizeof(char)); memcpy(m_Data + m_Offset, str.data(), sizeOfString * sizeof(char));
@@ -50,7 +56,7 @@ void Packet::WriteString(const std::string& str)
void Packet::WriteData(char * data, int sizeOfData) void Packet::WriteData(char * data, int sizeOfData)
{ {
if (m_Offset + sizeOfData > m_MaxPacketSize) { if (m_Offset + sizeOfData > m_MaxPacketSize) {
LOG_WARNING("Packet::WriteData(): Data size in packet exceeded maximum packet size. New size is %i bytes\n", m_MaxPacketSize*2); //LOG_WARNING("Packet::WriteData(): Data size in packet exceeded maximum packet size. New size is %i bytes\n", m_MaxPacketSize*2);
resizeData(); resizeData();
} }
memcpy(m_Data + m_Offset, data, sizeOfData); memcpy(m_Data + m_Offset, data, sizeOfData);
@@ -61,7 +67,7 @@ std::string Packet::ReadString()
{ {
std::string returnValue(m_Data + m_ReturnDataOffset); std::string returnValue(m_Data + m_ReturnDataOffset);
if (m_Offset < m_ReturnDataOffset + returnValue.size()) { if (m_Offset < m_ReturnDataOffset + returnValue.size()) {
LOG_WARNING("packet ReadString(): Oh no! You are trying to remove things outside my memory kingdom"); //LOG_WARNING("packet ReadString(): Oh no! You are trying to remove things outside my memory kingdom");
return "PopFrontString Failed"; return "PopFrontString Failed";
} }
// +1 for null terminator. // +1 for null terminator.
@@ -72,7 +78,7 @@ std::string Packet::ReadString()
char * Packet::ReadData(int SizeOfData) char * Packet::ReadData(int SizeOfData)
{ {
if (m_Offset < m_ReturnDataOffset + SizeOfData) { if (m_Offset < m_ReturnDataOffset + SizeOfData) {
LOG_WARNING("packet ReadData(): Oh no! You are trying to remove things outside my memory kingdom"); //LOG_WARNING("packet ReadData(): Oh no! You are trying to remove things outside my memory kingdom");
return nullptr; return nullptr;
} }
unsigned int oldReturnDataOffset = m_ReturnDataOffset; unsigned int oldReturnDataOffset = m_ReturnDataOffset;
@@ -80,14 +86,21 @@ char * Packet::ReadData(int SizeOfData)
return (m_Data + oldReturnDataOffset); return (m_Data + oldReturnDataOffset);
} }
void Packet::ChangePacketID(unsigned int & packetID)
{
packetID = packetID + 1;
// Overwrite old PacketID
memcpy(m_Data + sizeof(int), &packetID, sizeof(int));
}
void Packet::resizeData() void Packet::resizeData()
{ {
// Allocate memory to store our data in // Allocate memory to store our data in
char* holdData = new char[m_MaxPacketSize]; char* holdData = new char[m_MaxPacketSize];
// Copy our data to the newly allocated memory // Copy our data to the newly allocated memory
memcpy(holdData, m_Data, m_Offset); memcpy(holdData, m_Data, m_Offset);
// Increase max packet size // Increase max packet size
m_MaxPacketSize = m_MaxPacketSize * 2; m_MaxPacketSize = m_MaxPacketSize * 2;
// Delete our data // Delete our data
delete m_Data; delete m_Data;
+152 -131
View File
@@ -8,13 +8,14 @@ Server::~Server()
} }
void Server::Start(World* world, EventBroker* eventBroker) void Server::Start(World* world, EventBroker* eventBroker)
{ {
m_World = world; m_World = world;
m_EventBroker = eventBroker; m_EventBroker = eventBroker;
// Subscribe to events
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Server::OnInputCommand);
for (size_t i = 0; i < MAXCONNECTIONS; i++) { for (size_t i = 0; i < MAXCONNECTIONS; i++) {
m_StopTimes[i] = std::clock(); m_PlayerDefinitions[i].StopTime = std::clock();
} }
LOG_INFO("I am Server. BIP BOP\n"); LOG_INFO("I am Server. BIP BOP\n");
} }
@@ -22,8 +23,10 @@ void Server::Start(World* world, EventBroker* eventBroker)
void Server::Update() void Server::Update()
{ {
readFromClients(); readFromClients();
m_EventBroker->Process<Server>();
} }
void Server::readFromClients() void Server::readFromClients()
{ {
while (m_Socket.available()) { while (m_Socket.available()) {
@@ -50,7 +53,7 @@ void Server::readFromClients()
// Time out logic // Time out logic
if (checkTimeOutInterval < (1000 * (currentTime - timOutTimer) / (double)CLOCKS_PER_SEC)) { if (checkTimeOutInterval < (1000 * (currentTime - timOutTimer) / (double)CLOCKS_PER_SEC)) {
//checkForTimeOuts(); checkForTimeOuts();
timOutTimer = currentTime; timOutTimer = currentTime;
} }
} }
@@ -62,7 +65,7 @@ void Server::parseMessageType(Packet& packet)
// Read packet ID // Read packet ID
m_PreviousPacketID = m_PacketID; // Set previous packet id m_PreviousPacketID = m_PacketID; // Set previous packet id
m_PacketID = packet.ReadPrimitive<int>(); //Read new packet id m_PacketID = packet.ReadPrimitive<int>(); //Read new packet id
//IdentifyPacketLoss(); //identifyPacketLoss();
switch (static_cast<MessageType>(messageType)) { switch (static_cast<MessageType>(messageType)) {
case MessageType::Connect: case MessageType::Connect:
parseConnect(packet); parseConnect(packet);
@@ -76,13 +79,18 @@ void Server::parseMessageType(Packet& packet)
case MessageType::Message: case MessageType::Message:
break; break;
case MessageType::Snapshot: case MessageType::Snapshot:
parseSnapshot(packet);
break; break;
case MessageType::Disconnect: case MessageType::Disconnect:
parseDisconnect(); parseDisconnect();
break; break;
case MessageType::Event: case MessageType::OnInputCommand:
parseEvent(packet); parseOnInputCommand(packet);
break;
case MessageType::OnPlayerDamage:
parseOnPlayerDamage(packet);
break;
case MessageType::BecomePlayer:
createPlayer();
break; break;
default: default:
break; break;
@@ -98,11 +106,11 @@ int Server::receive(char * data, size_t length)
return length; return length;
} }
void Server::send(Packet& packet, int playerID) void Server::send(Packet& packet, int userID)
{ {
int bytesSent = m_Socket.send_to( int bytesSent = m_Socket.send_to(
boost::asio::buffer(packet.Data(), packet.Size()), boost::asio::buffer(packet.Data(), packet.Size()),
m_PlayerDefinitions[playerID].Endpoint, m_ConnectedUsers[userID].Endpoint,
0); 0);
} }
@@ -116,27 +124,11 @@ void Server::send(Packet & packet)
0); 0);
} }
void Server::moveMessageHead(char *& data, size_t & length, size_t stepSize)
{
data += stepSize;
length -= stepSize;
}
void Server::broadcast(std::string message)
{
Packet packet(MessageType::Event, m_SendPacketID);
packet.WriteString(message);
for (int i = 0; i < MAXCONNECTIONS; i++) {
if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) {
send(packet, i);
}
}
}
void Server::broadcast(Packet& packet) void Server::broadcast(Packet& packet)
{ {
for (int i = 0; i < MAXCONNECTIONS; ++i) { for (int i = 0; i < m_ConnectedUsers.size(); i++) {
if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) { if (m_ConnectedUsers[i].Endpoint.address() != boost::asio::ip::address()) {
packet.ChangePacketID(m_ConnectedUsers[i].PacketID);
send(packet, i); send(packet, i);
} }
} }
@@ -148,14 +140,16 @@ void Server::sendSnapshot()
// Should time this // Should time this
std::unordered_map<std::string, ComponentPool*> worldComponentPools = m_World->GetComponentPools(); std::unordered_map<std::string, ComponentPool*> worldComponentPools = m_World->GetComponentPools();
for (auto& it : worldComponentPools) { for (auto& it : worldComponentPools) {
Packet packet(MessageType::Snapshot, m_SendPacketID); Packet packet(MessageType::Snapshot);
std::string componentType = it.first;
ComponentPool* componentPool = it.second; ComponentPool* componentPool = it.second;
ComponentInfo componentInfo = componentPool->ComponentInfo(); ComponentInfo componentInfo = componentPool->ComponentInfo();
// Component Type
packet.WriteString(componentInfo.Name); packet.WriteString(componentInfo.Name);
for (auto& componentWrapper : *componentPool) { for (auto& componentWrapper : *componentPool) {
// Components EntityID
packet.WritePrimitive(componentWrapper.EntityID); packet.WritePrimitive(componentWrapper.EntityID);
// Parents EntityID
packet.WritePrimitive(m_World->GetParent(componentWrapper.EntityID));
for (auto& componentField : componentWrapper.Info.FieldsInOrder) { for (auto& componentField : componentWrapper.Info.FieldsInOrder) {
ComponentInfo::Field_t fieldInfo = componentInfo.Fields.at(componentField); ComponentInfo::Field_t fieldInfo = componentInfo.Fields.at(componentField);
if (fieldInfo.Type == "string") { if (fieldInfo.Type == "string") {
@@ -173,14 +167,14 @@ void Server::sendSnapshot()
void Server::sendPing() void Server::sendPing()
{ {
// Prints connected players ping // Prints connected players ping
for (size_t i = 0; i < MAXCONNECTIONS; i++) { for (int i = 0; i < m_ConnectedUsers.size(); i++) {
if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) { if (m_ConnectedUsers[i].Endpoint.address() != boost::asio::ip::address()) {
int ping = 1000 * (m_StopTimes[i] - m_StartPingTime) / static_cast<double>(CLOCKS_PER_SEC); int ping = 1000 * (m_ConnectedUsers[i].StopTime - m_StartPingTime) / static_cast<double>(CLOCKS_PER_SEC);
LOG_INFO("Last packetID received %i: Player %i's ping: %i", m_PacketID, i, ping); LOG_INFO("Last packetID received %i: User %i's ping: %i", m_ConnectedUsers[i].PacketID, i, std::abs(ping));
} }
} }
// Create ping message // Create ping message
Packet packet(MessageType::ServerPing, m_SendPacketID); Packet packet(MessageType::ServerPing);
packet.WriteString("Ping from server"); packet.WriteString("Ping from server");
// Time message // Time message
m_StartPingTime = std::clock(); m_StartPingTime = std::clock();
@@ -190,16 +184,15 @@ void Server::sendPing()
void Server::checkForTimeOuts() void Server::checkForTimeOuts()
{ {
int timeOutTimeMs = 5000;
int startPing = 1000 * m_StartPingTime int startPing = 1000 * m_StartPingTime
/ static_cast<double>(CLOCKS_PER_SEC); / static_cast<double>(CLOCKS_PER_SEC);
for (size_t i = 0; i < MAXCONNECTIONS; i++) { for (int i = 0; i < m_ConnectedUsers.size(); i++) {
if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) { if (m_ConnectedUsers[i].Endpoint.address() != boost::asio::ip::address()) {
int stopPing = 1000 * m_StopTimes[i] int stopPing = 1000 * m_ConnectedUsers[i].StopTime /
/ static_cast<double>(CLOCKS_PER_SEC); static_cast<double>(CLOCKS_PER_SEC);
if (startPing > stopPing + timeOutTimeMs) { if (startPing > stopPing + TIMEOUTMS) {
LOG_INFO("Player %i timed out!", i); LOG_INFO("User %i timed out!", i);
disconnect(i); disconnect(i);
} }
} }
@@ -208,92 +201,89 @@ void Server::checkForTimeOuts()
void Server::disconnect(int i) void Server::disconnect(int i)
{ {
broadcast("A player disconnected"); //broadcast("A player disconnected");
LOG_INFO("Player %i disconnected/timed out", i); LOG_INFO("User %s disconnected/timed out", m_PlayerDefinitions[i].Name.c_str());
// Remove enteties and stuff (When we can remove entity, remove it and tell clients to remove the copy they have)
// Remove enteties and stuff
m_PlayerDefinitions[i].Endpoint = boost::asio::ip::udp::endpoint(); m_PlayerDefinitions[i].Endpoint = boost::asio::ip::udp::endpoint();
m_PlayerDefinitions[i].EntityID = -1; m_PlayerDefinitions[i].EntityID = -1;
m_PlayerDefinitions[i].Name = ""; m_PlayerDefinitions[i].Name = "";
m_PlayerDefinitions[i].PacketID = 0;
m_ConnectedUsers.erase(m_ConnectedUsers.begin() + i);
} }
void Server::parseEvent(Packet& packet) void Server::parseOnInputCommand(Packet& packet)
{ {
size_t i; int playerID = -1;
for (i = 0; i < MAXCONNECTIONS; i++) { // Check which player it was who sent the message
if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address()) { for (int i = 0; i < MAXCONNECTIONS; i++) {
// if the player is connected set playerID to the correct PlayerID
if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address()
&& m_PlayerDefinitions[i].Endpoint.port() == m_ReceiverEndpoint.port()) {
playerID = i;
break; break;
} }
} }
// If no player matches the address return. if (playerID != -1) {
if (i >= 8) while (packet.DataReadSize() < packet.Size()) {
return; Events::InputCommand e;
e.Command = packet.ReadString();
e.PlayerID = playerID; // Set correct player id
e.Value = packet.ReadPrimitive<float>();
m_EventBroker->Publish(e);
//LOG_INFO("Server::parseOnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID);
}
}
}
unsigned int entityId = m_PlayerDefinitions[i].EntityID; void Server::parseOnPlayerDamage(Packet & packet)
std::string eventString = packet.ReadString(); {
if ("+Forward" == eventString) { Events::PlayerDamage e;
m_World->GetComponent(entityId, "Player")["Forward"] = true; e.DamageAmount = packet.ReadPrimitive<double>();
m_World->GetComponent(entityId, "Player")["Back"] = false; e.PlayerDamagedID = packet.ReadPrimitive<EntityID>();
} else if ("-Forward" == eventString) { e.TypeOfDamage = packet.ReadString();
m_World->GetComponent(entityId, "Player")["Forward"] = false; m_EventBroker->Publish(e);
m_World->GetComponent(entityId, "Player")["Back"] = true; //LOG_DEBUG("Server::parseOnPlayerDamage: Command is %s. Value is %f. PlayerID is %i.", e.DamageAmount, e.PlayerDamagedID, e.TypeOfDamage.c_str());
} else if ("0Forward" == eventString) {
m_World->GetComponent(entityId, "Player")["Forward"] = false;
m_World->GetComponent(entityId, "Player")["Back"] = false;
}
if ("+Right" == eventString) {
m_World->GetComponent(entityId, "Player")["Left"] = false;
m_World->GetComponent(entityId, "Player")["Right"] = true;
} else if ("-Right" == eventString) {
m_World->GetComponent(entityId, "Player")["Right"] = false;
m_World->GetComponent(entityId, "Player")["Left"] = true;
} else if ("0Right" == eventString) {
m_World->GetComponent(entityId, "Player")["Right"] = false;
m_World->GetComponent(entityId, "Player")["Left"] = false;
}
} }
void Server::parseConnect(Packet& packet) void Server::parseConnect(Packet& packet)
{ {
LOG_INFO("Parsing connections"); LOG_INFO("Parsing connections");
// Check if player is already connected // Check if player is already connected
for (int i = 0; i < MAXCONNECTIONS; i++) { if (GetPlayerIDFromEndpoint(m_ReceiverEndpoint) != -1) {
if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address()) { return;
}
for (int i = 0; i < m_ConnectedUsers.size(); i++) {
if (m_ConnectedUsers[i].Endpoint.address() == m_ReceiverEndpoint.address() &&
m_ConnectedUsers[i].Endpoint.port() == m_ReceiverEndpoint.port()) {
// Already connected
return; return;
} }
} }
// Create a new player
PlayerDefinition pd;
pd.EntityID = 0; // Overlook this
pd.Endpoint = m_ReceiverEndpoint;
pd.Name = packet.ReadString();
pd.PacketID = 0;
pd.StopTime = std::clock();
m_ConnectedUsers.push_back(pd);
LOG_INFO("Spectator \"%s\" connected on IP: %s", pd.Name.c_str(), pd.Endpoint.address().to_string().c_str());
for (int i = 0; i < MAXCONNECTIONS; i++) { // Send a message to the player that connected
if (m_PlayerDefinitions[i].Endpoint.address() == boost::asio::ip::address()) { Packet connnectPacket(MessageType::Connect, m_ConnectedUsers[m_ConnectedUsers.size() - 1].PacketID);
// Create new player send(connnectPacket);
m_PlayerDefinitions[i].EntityID = createPlayer();
m_PlayerDefinitions[i].Endpoint = m_ReceiverEndpoint;
m_PlayerDefinitions[i].Name = packet.ReadString();
m_StopTimes[i] = std::clock(); // Send notification that a player has connected
Packet notificationPacket(MessageType::PlayerConnected);
LOG_INFO("Player \"%s\" connected on IP: %s", m_PlayerDefinitions[i].Name.c_str(), m_PlayerDefinitions[i].Endpoint.address().to_string().c_str()); broadcast(notificationPacket);
Packet packet(MessageType::Connect, m_SendPacketID);
packet.WritePrimitive<int>(i); // Player ID
send(packet, i);
// Send notification that a player has connected
std::string str = m_PacketID + "Player " + m_PlayerDefinitions[i].Name + " connected on: "
+ m_PlayerDefinitions[i].Endpoint.address().to_string();
broadcast(str);
break;
}
}
} }
void Server::parseDisconnect() void Server::parseDisconnect()
{ {
LOG_INFO("%i: Parsing disconnect", m_PacketID); LOG_INFO("%i: Parsing disconnect", m_PacketID);
for (int i = 0; i < MAXCONNECTIONS; i++) { for (int i = 0; i < m_ConnectedUsers.size(); i++) {
if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address()) { if (m_ConnectedUsers[i].Endpoint.address() == m_ReceiverEndpoint.address()) {
disconnect(i); disconnect(i);
break; break;
} }
@@ -303,37 +293,26 @@ void Server::parseDisconnect()
void Server::parseClientPing() void Server::parseClientPing()
{ {
LOG_INFO("%i: Parsing ping", m_PacketID); LOG_INFO("%i: Parsing ping", m_PacketID);
int playerID = GetPlayerIDFromEndpoint(m_ReceiverEndpoint);
if (playerID == -1) {
return;
}
// Return ping // Return ping
Packet packet(MessageType::ClientPing, m_SendPacketID); Packet packet(MessageType::ClientPing, m_PlayerDefinitions[playerID].PacketID);
packet.WriteString("Ping received"); packet.WriteString("Ping received");
send(packet); // This dosen't work for multiple users send(packet);
} }
void Server::parseServerPing() void Server::parseServerPing()
{ {
for (int i = 0; i < MAXCONNECTIONS; i++) { for (int i = 0; i < m_ConnectedUsers.size(); i++) {
if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address()) { if (m_ConnectedUsers[i].Endpoint.address() == m_ReceiverEndpoint.address()) {
m_StopTimes[i] = std::clock(); m_ConnectedUsers[i].StopTime = std::clock();
break; break;
} }
} }
} }
// NOT USED
void Server::parseSnapshot(Packet& packet)
{
// Does no logic. Returns snapshot if client request one
// The snapshot is not a real snapshot tho...
for (int i = 0; i < MAXCONNECTIONS; i++) {
if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) {
m_Socket.send_to(
boost::asio::buffer("I'm sending a snapshot to you guys!"),
m_PlayerDefinitions[i].Endpoint,
0);
}
}
}
void Server::identifyPacketLoss() void Server::identifyPacketLoss()
{ {
// if no packets lost, difference should be equal to 1 // if no packets lost, difference should be equal to 1
@@ -343,14 +322,56 @@ void Server::identifyPacketLoss()
} }
} }
EntityID Server::createPlayer() void Server::createPlayer()
{ {
EntityID entityID = m_World->CreateEntity(); if (GetPlayerIDFromEndpoint(m_ReceiverEndpoint) != -1) {
ComponentWrapper transform = m_World->AttachComponent(entityID, "Transform"); // Already connected as player
transform["Position"] = glm::vec3(-1.5f, 0.f, 0.f); LOG_WARNING("Already connected!");
ComponentWrapper model = m_World->AttachComponent(entityID, "Model"); return;
model["Resource"] = "Models/Core/UnitSphere.obj"; }
model["Color"] = glm::vec4(rand()%255 / 255.f, rand()%255 / 255.f, rand() %255 / 255.f, 1.f); int userIndex;
ComponentWrapper player = m_World->AttachComponent(entityID, "Player"); for (userIndex = 0; userIndex < m_ConnectedUsers.size(); userIndex++) {
return entityID; if (m_ConnectedUsers[userIndex].Endpoint.address() == m_ReceiverEndpoint.address() &&
m_ConnectedUsers[userIndex].Endpoint.port() == m_ReceiverEndpoint.port()) {
// Found user
break;
}
}
if (userIndex == m_ConnectedUsers.size()) {
LOG_WARNING("Not a recognized user!");
return;
}
for (int playerIndex = 0; playerIndex < MAXCONNECTIONS; playerIndex++) {
if (m_PlayerDefinitions[playerIndex].Endpoint.address() == boost::asio::ip::address()) {
m_PlayerDefinitions[playerIndex] = m_ConnectedUsers[userIndex];
EntityID entityID = m_World->CreateEntity();
ComponentWrapper transform = m_World->AttachComponent(entityID, "Transform");
transform["Position"] = glm::vec3(-1.5f, 0.f, 0.f);
ComponentWrapper model = m_World->AttachComponent(entityID, "Model");
model["Resource"] = "Models/Core/UnitSphere.obj";
model["Color"] = glm::vec4(rand()%255 / 255.f, rand()%255 / 255.f, rand() %255 / 255.f, 1.f);
ComponentWrapper player = m_World->AttachComponent(entityID, "Player");
m_PlayerDefinitions[playerIndex].EntityID = entityID;
return;
}
}
LOG_WARNING("Server is full!");
}
int Server::GetPlayerIDFromEndpoint(boost::asio::ip::udp::endpoint endpoint)
{
for (int i = 0; i < MAXCONNECTIONS; i++) {
if (m_PlayerDefinitions[i].Endpoint.address() == endpoint.address() &&
m_PlayerDefinitions[i].Endpoint.port() == endpoint.port()) {
return i;
}
}
return -1;
}
bool Server::OnInputCommand(const Events::InputCommand & e)
{
//LOG_DEBUG("Server::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID);
return true;
} }
+26 -19
View File
@@ -40,15 +40,14 @@ void LightCullingPass::OnResolutionChange()
void LightCullingPass::SetSSBOSizes() void LightCullingPass::SetSSBOSizes()
{ {
m_NumberOfTiles = (int)(m_Renderer->Resolution().Width*m_Renderer->Resolution().Height)/TILE_SIZE; m_NumberOfTiles = (int)(m_Renderer->Resolution().Width/TILE_SIZE) * (int)(m_Renderer->Resolution().Height/TILE_SIZE);
//m_Frustums = new Frustum[s];
//m_LightGrid = new LightGrid[s];
//m_LightIndex = new float[s*200];
m_Frustums = new Frustum[m_NumberOfTiles]; m_Frustums = new Frustum[m_NumberOfTiles];
m_LightGrid = new LightGrid[m_NumberOfTiles]; m_LightGrid = new LightGrid[m_NumberOfTiles];
m_LightIndex = new float[m_NumberOfTiles*MAX_LIGHTS_PER_TILE]; m_LightIndex = new float[m_NumberOfTiles*MAX_LIGHTS_PER_TILE];
for (int i = 0; i < m_NumberOfTiles*MAX_LIGHTS_PER_TILE; i++) {
m_LightIndex[i] = -1;
}
} }
void LightCullingPass::CullLights(RenderScene& scene) void LightCullingPass::CullLights(RenderScene& scene)
@@ -59,8 +58,8 @@ void LightCullingPass::CullLights(RenderScene& scene)
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightOffsetSSBO); glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightOffsetSSBO);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightOffset), &m_LightOffset, GL_DYNAMIC_COPY); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightOffset), &m_LightOffset, GL_DYNAMIC_COPY);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightSSBO); glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightSSBO);
if (m_PointLights.size() > 0) { if (m_LightSources.size() > 0) {
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(PointLight) * m_PointLights.size(), &(m_PointLights[0]), GL_DYNAMIC_COPY); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(LightSource) * m_LightSources.size(), &(m_LightSources[0]), GL_DYNAMIC_COPY);
} else { } else {
GLfloat zero = 0.f; GLfloat zero = 0.f;
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &zero , GL_DYNAMIC_COPY); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &zero , GL_DYNAMIC_COPY);
@@ -75,27 +74,38 @@ void LightCullingPass::CullLights(RenderScene& scene)
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightGridSSBO); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightGridSSBO);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_LightOffsetSSBO); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_LightOffsetSSBO);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightIndexSSBO); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightIndexSSBO);
glDispatchCompute(m_Renderer->Resolution().Width / TILE_SIZE, m_Renderer->Resolution().Height / TILE_SIZE, 1); glDispatchCompute(glm::ceil(m_Renderer->Resolution().Width / TILE_SIZE), glm::ceil(m_Renderer->Resolution().Height / TILE_SIZE), 1);
GLERROR("CullLights Error: End"); GLERROR("CullLights Error: End");
} }
void LightCullingPass::FillLightList(RenderScene& scene) void LightCullingPass::FillLightList(RenderScene& scene)
{ {
m_PointLights.clear(); m_LightSources.clear();
for(auto &job : scene.PointLightJobs) { for(auto &job : scene.PointLightJobs) {
auto pointLightjob = std::dynamic_pointer_cast<PointLightJob>(job); auto pointLightjob = std::dynamic_pointer_cast<PointLightJob>(job);
if (pointLightjob) { if (pointLightjob) {
PointLight p; LightSource p;
p.Color = pointLightjob->Color; p.Color = pointLightjob->Color;
p.Falloff = pointLightjob->Falloff; p.Falloff = pointLightjob->Falloff;
p.Intensity = pointLightjob->Intensity; p.Intensity = pointLightjob->Intensity;
p.Position = glm::vec4(glm::vec3(pointLightjob->Position), 1.f); p.Position = glm::vec4(glm::vec3(pointLightjob->Position), 1.f);
p.Radius = pointLightjob->Radius; p.Radius = pointLightjob->Radius;
p.Padding = 123.f; //p.Padding = 123.f;
m_PointLights.push_back(p); p.Type = LightSource::Point;
continue; m_LightSources.push_back(p);
}
}
for(auto &job : scene.DirectionalLightJobs) {
auto directionalLightJob = std::dynamic_pointer_cast<DirectionalLightJob>(job);
if(directionalLightJob) {
LightSource p;
p.Direction = directionalLightJob->Direction;
p.Color = directionalLightJob->Color;
p.Intensity = directionalLightJob->Intensity;
p.Type = LightSource::Directional;
m_LightSources.push_back(p);
} }
} }
} }
@@ -104,25 +114,22 @@ void LightCullingPass::InitializeSSBOs()
{ {
glGenBuffers(1, &m_FrustumSSBO); glGenBuffers(1, &m_FrustumSSBO);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_FrustumSSBO); glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_FrustumSSBO);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(Frustum)*m_NumberOfTiles, m_Frustums, GL_DYNAMIC_COPY); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(Frustum)*m_NumberOfTiles, nullptr, GL_DYNAMIC_COPY);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
GLERROR("m_FrustumSSBO"); GLERROR("m_FrustumSSBO");
glGenBuffers(1, &m_LightSSBO); glGenBuffers(1, &m_LightSSBO);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightSSBO); glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightSSBO);
if(m_PointLights.size() > 0) { glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(LightSource) * 200, nullptr, GL_DYNAMIC_COPY);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(PointLight) * m_PointLights.size(), &(m_PointLights[0]), GL_DYNAMIC_COPY);
}
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
GLERROR("m_LightSSBO"); GLERROR("m_LightSSBO");
glGenBuffers(1, &m_LightGridSSBO); glGenBuffers(1, &m_LightGridSSBO);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightGridSSBO); glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightGridSSBO);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(LightGrid)*m_NumberOfTiles, m_LightGrid, GL_DYNAMIC_COPY); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(LightGrid)*m_NumberOfTiles, nullptr, GL_DYNAMIC_COPY);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
GLERROR("m_LightGridSSBO"); GLERROR("m_LightGridSSBO");
glGenBuffers(1, &m_LightOffsetSSBO); glGenBuffers(1, &m_LightOffsetSSBO);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightOffsetSSBO); glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightOffsetSSBO);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightOffset), &m_LightOffset, GL_DYNAMIC_COPY); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightOffset), &m_LightOffset, GL_DYNAMIC_COPY);
+36 -15
View File
@@ -68,25 +68,45 @@ void RenderSystem::fillModels(std::list<std::shared_ptr<RenderJob>>& jobs)
} }
} }
void RenderSystem::fillLight(std::list<std::shared_ptr<RenderJob>>& jobs) void RenderSystem::fillPointLights(std::list<std::shared_ptr<RenderJob>>& jobs, World* world)
{ {
auto pointLights = m_World->GetComponents("PointLight"); auto pointLights = m_World->GetComponents("PointLight");
if (pointLights == nullptr) { if (pointLights != nullptr) {
return; for (auto& pointlightC : *pointLights) {
bool visible = pointlightC["Visible"];
if (!visible) {
continue;
}
auto transformC = world->GetComponent(pointlightC.EntityID, "Transform");
if (&transformC == nullptr) {
continue;
}
std::shared_ptr<PointLightJob> pointLightJob = std::shared_ptr<PointLightJob>(new PointLightJob(transformC, pointlightC, m_World));
jobs.push_back(pointLightJob);
}
} }
}
for (auto& pointlightC : *pointLights) {
bool visible = pointlightC["Visible"];
if (!visible) {
continue;
}
auto transformC = m_World->GetComponent(pointlightC.EntityID, "Transform");
if (&transformC == nullptr) {
return;
}
std::shared_ptr<PointLightJob> pointLightJob = std::shared_ptr<PointLightJob>(new PointLightJob(transformC, pointlightC, m_World)); void RenderSystem::fillDirectionalLights(std::list<std::shared_ptr<RenderJob>>& jobs, World* world)
jobs.push_back(pointLightJob); {
auto directionalLights = world->GetComponents("DirectionalLight");
if (directionalLights != nullptr) {
for (auto& directionalLightC : *directionalLights) {
bool visable = directionalLightC["Visible"];
if (!visable) {
continue;
}
auto transformC = world->GetComponent(directionalLightC.EntityID, "Transform");
if (&transformC == nullptr) {
continue;
}
std::shared_ptr<DirectionalLightJob> directionalLightJob = std::shared_ptr<DirectionalLightJob>(new DirectionalLightJob(transformC, directionalLightC, m_World));
jobs.push_back(directionalLightJob);
}
} }
} }
@@ -110,7 +130,8 @@ void RenderSystem::Update(double dt)
scene.Camera = m_Camera; scene.Camera = m_Camera;
scene.Viewport = Rectangle(1280, 720); scene.Viewport = Rectangle(1280, 720);
fillModels(scene.ForwardJobs); fillModels(scene.ForwardJobs);
fillLight(scene.PointLightJobs); fillPointLights(scene.PointLightJobs, m_World);
fillDirectionalLights(scene.DirectionalLightJobs, m_World);
m_RenderFrame->Add(scene); m_RenderFrame->Add(scene);
} }
+8 -20
View File
@@ -90,8 +90,7 @@ void Renderer::Draw(RenderFrame& frame)
if (scene->ClearDepth) { if (scene->ClearDepth) {
glClear(GL_DEPTH_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT);
} }
SortRenderJobsByDepth(*scene);
FillDepth(*scene);
m_PickingPass->Draw(*scene); m_PickingPass->Draw(*scene);
m_LightCullingPass->GenerateNewFrustum(*scene); m_LightCullingPass->GenerateNewFrustum(*scene);
m_LightCullingPass->FillLightList(*scene); m_LightCullingPass->FillLightList(*scene);
@@ -138,6 +137,13 @@ void Renderer::InitializeTextures()
m_WhiteTexture = ResourceManager::Load<Texture>("Textures/Core/Blank.png"); m_WhiteTexture = ResourceManager::Load<Texture>("Textures/Core/Blank.png");
} }
void Renderer::SortRenderJobsByDepth(RenderScene &scene)
{
//Sort all forward jobs so transparency is good.
scene.ForwardJobs.sort(Renderer::DepthSort);
}
void Renderer::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) void Renderer::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type)
{ {
glGenTextures(1, texture); glGenTextures(1, texture);
@@ -156,21 +162,3 @@ void Renderer::InitializeRenderPasses()
m_LightCullingPass = new LightCullingPass(this); m_LightCullingPass = new LightCullingPass(this);
m_DrawFinalPass = new DrawFinalPass(this, m_LightCullingPass); m_DrawFinalPass = new DrawFinalPass(this, m_LightCullingPass);
} }
//Temp func
void Renderer::FillDepth(RenderScene& scene)
{
// HACK: FIX ME TOBIAS
/*for (auto job : scene.ForwardJobs) {
auto modelJob = std::dynamic_pointer_cast<ModelJob>(job);
if(! modelJob) {
return;
}
glm::vec3 abspos = Transform::AbsolutePosition(modelJob->World, modelJob->Entity);
glm::vec3 worldpos = glm::vec3(scene.Camera->ViewMatrix() * glm::vec4(abspos, 1));
modelJob->Depth = worldpos.z;
}
scene.ForwardJobs.sort(Renderer::DepthSort);*/
}
+3 -1
View File
@@ -26,7 +26,9 @@ set(SOURCE_FILES
${SOURCE_FILES} ${SOURCE_FILES}
"Game.cpp" "Game.cpp"
${SOURCE_FILES_Systems} ${SOURCE_FILES_Systems}
${SOURCE_FILES_Events} ${SOURCE_FILES_Events}
) )
set(LIBRARIES set(LIBRARIES
+8 -8
View File
@@ -3,12 +3,12 @@
#include "Collision/TriggerSystem.h" #include "Collision/TriggerSystem.h"
#include "Collision/CollisionSystem.h" #include "Collision/CollisionSystem.h"
#include "Systems/RaptorCopterSystem.h" #include "Systems/RaptorCopterSystem.h"
#include "Systems/PlayerSystem.h"
#include "Systems/HealthSystem.h" #include "Systems/HealthSystem.h"
#include "Systems/PlayerMovementSystem.h" #include "Systems/PlayerMovementSystem.h"
#include "Systems/SpawnerSystem.h" #include "Systems/SpawnerSystem.h"
#include "Systems/PlayerSpawnSystem.h" #include "Systems/PlayerSpawnSystem.h"
#include "Core/EntityFileWriter.h" #include "Core/EntityFileWriter.h"
#include "Game/Systems/CapturePointSystem.h"
Game::Game(int argc, char* argv[]) Game::Game(int argc, char* argv[])
{ {
@@ -22,13 +22,14 @@ Game::Game(int argc, char* argv[])
m_Config = ResourceManager::Load<ConfigFile>("Config.ini"); m_Config = ResourceManager::Load<ConfigFile>("Config.ini");
ResourceManager::UseThreading = m_Config->Get<bool>("Multithreading.ResourceLoading", true); ResourceManager::UseThreading = m_Config->Get<bool>("Multithreading.ResourceLoading", true);
DisableMemoryPool::Value = m_Config->Get<bool>("Debug.DisableMemoryPool", false);
LOG_LEVEL = static_cast<_LOG_LEVEL>(m_Config->Get<int>("Debug.LogLevel", 1)); LOG_LEVEL = static_cast<_LOG_LEVEL>(m_Config->Get<int>("Debug.LogLevel", 1));
// Create the core event broker // Create the core event broker
m_EventBroker = new EventBroker(); m_EventBroker = new EventBroker();
// Create the renderer // Create the renderer
m_Renderer = new Renderer(m_EventBroker, m_World); m_Renderer = new Renderer(m_EventBroker);
m_Renderer->SetFullscreen(m_Config->Get<bool>("Video.Fullscreen", false)); m_Renderer->SetFullscreen(m_Config->Get<bool>("Video.Fullscreen", false));
m_Renderer->SetVSYNC(m_Config->Get<bool>("Video.VSYNC", false)); m_Renderer->SetVSYNC(m_Config->Get<bool>("Video.VSYNC", false));
m_Renderer->SetResolution(Rectangle::Rectangle( m_Renderer->SetResolution(Rectangle::Rectangle(
@@ -63,21 +64,20 @@ Game::Game(int argc, char* argv[])
EntityFileParser fp(file); EntityFileParser fp(file);
fp.MergeEntities(m_World); fp.MergeEntities(m_World);
} }
//SO MUCH TEMP PLEASE REMOVE ME OMFG VIKTOR HELP
m_Renderer->m_World = m_World;
// Create Octrees // Create Octrees
m_OctreeCollision = new Octree(AABB(glm::vec3(-100), glm::vec3(100)), 4); m_OctreeCollision = new Octree<AABB>(AABB(glm::vec3(-100), glm::vec3(100)), 4);
m_OctreeFrustrumCulling = new Octree(AABB(glm::vec3(-100), glm::vec3(100)), 4); m_OctreeFrustrumCulling = new Octree<AABB>(AABB(glm::vec3(-100), glm::vec3(100)), 4);
// Create system pipeline // Create system pipeline
m_SystemPipeline = new SystemPipeline(m_World, m_EventBroker); m_SystemPipeline = new SystemPipeline(m_World, m_EventBroker);
// All systems with orderlevel 0 will be updated first. // All systems with orderlevel 0 will be updated first.
unsigned int updateOrderLevel = 0; unsigned int updateOrderLevel = 0;
m_SystemPipeline->AddSystem<RaptorCopterSystem>(updateOrderLevel); m_SystemPipeline->AddSystem<RaptorCopterSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<PlayerSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<HealthSystem>(updateOrderLevel); m_SystemPipeline->AddSystem<HealthSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<PlayerMovementSystem>(updateOrderLevel); m_SystemPipeline->AddSystem<PlayerMovementSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<InterpolationSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<SpawnerSystem>(updateOrderLevel); m_SystemPipeline->AddSystem<SpawnerSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<PlayerSpawnSystem>(updateOrderLevel); m_SystemPipeline->AddSystem<PlayerSpawnSystem>(updateOrderLevel);
// Populate Octree with collidables // Populate Octree with collidables
@@ -88,6 +88,7 @@ Game::Game(int argc, char* argv[])
m_SystemPipeline->AddSystem<CollisionSystem>(updateOrderLevel, m_OctreeCollision); m_SystemPipeline->AddSystem<CollisionSystem>(updateOrderLevel, m_OctreeCollision);
m_SystemPipeline->AddSystem<TriggerSystem>(updateOrderLevel, m_OctreeCollision); m_SystemPipeline->AddSystem<TriggerSystem>(updateOrderLevel, m_OctreeCollision);
++updateOrderLevel; ++updateOrderLevel;
m_SystemPipeline->AddSystem<CapturePointSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<RenderSystem>(updateOrderLevel, m_Renderer, m_RenderFrame); m_SystemPipeline->AddSystem<RenderSystem>(updateOrderLevel, m_Renderer, m_RenderFrame);
++updateOrderLevel; ++updateOrderLevel;
m_SystemPipeline->AddSystem<EditorSystem>(updateOrderLevel, m_Renderer, m_RenderFrame); m_SystemPipeline->AddSystem<EditorSystem>(updateOrderLevel, m_Renderer, m_RenderFrame);
@@ -146,7 +147,6 @@ void Game::Tick()
m_SystemPipeline->Update(dt); m_SystemPipeline->Update(dt);
debugTick(dt); debugTick(dt);
m_Renderer->Update(dt); m_Renderer->Update(dt);
m_EventBroker->Process<Client>();
m_SoundSystem->Update(dt); m_SoundSystem->Update(dt);
GLERROR("Game::Tick m_RenderQueueFactory->Update"); GLERROR("Game::Tick m_RenderQueueFactory->Update");
m_Renderer->Draw(*m_RenderFrame); m_Renderer->Draw(*m_RenderFrame);
+236
View File
@@ -0,0 +1,236 @@
#include "Systems/CapturePointSystem.h"
#include <algorithm>
CapturePointSystem::CapturePointSystem(World* world, EventBroker* eventBroker)
: System(world, eventBroker)
, PureSystem("CapturePoint")
{
//subscribe/listenTo playerdamage,healthpickup events (using the eventBroker)
EVENT_SUBSCRIBE_MEMBER(m_ETriggerTouch, &CapturePointSystem::OnTriggerTouch);
EVENT_SUBSCRIBE_MEMBER(m_ETriggerLeave, &CapturePointSystem::OnTriggerLeave);
EVENT_SUBSCRIBE_MEMBER(m_ECaptured, &CapturePointSystem::OnCaptured);
}
//here all capturepoints will update their component
//NOTE: needs to run each frame, since we're possibly modifying the captureTimer for the capturePoints by dt
void CapturePointSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& capturePoint, double dt)
{
if (m_WinnerWasFound) {
return;
}
const int capturePointNumber = capturePoint["CapturePointNumber"];
const bool hasTeamComponent = m_World->HasComponent(capturePoint.EntityID, "Team");
//if point doesnt have a teamComponent yet, add one. since:
//what if capture point has no team -> we cant get/use the team enum from it...
if (!hasTeamComponent) {
m_World->AttachComponent(capturePoint.EntityID, "Team");
ComponentWrapper& teamComponent = m_World->GetComponent(capturePoint.EntityID, "Team");
teamComponent["Team"] = (int)teamComponent["Team"].Enum("Spectator");
}
ComponentWrapper& teamComponent = m_World->GetComponent(capturePoint.EntityID, "Team");
const int redTeam = (int)teamComponent["Team"].Enum("Red");
const int blueTeam = (int)teamComponent["Team"].Enum("Blue");
const int spectatorTeam = (int)teamComponent["Team"].Enum("Spectator");
int homePointForTeam = (int)capturePoint["HomePointForTeam"];
if (m_NumberOfCapturePoints == 0 && capturePointNumber != 0 && (homePointForTeam == redTeam || homePointForTeam == blueTeam)) {
m_NumberOfCapturePoints = capturePointNumber + 1;//ex 2 -> 0,1,2 = 3
if (homePointForTeam == redTeam) {
m_RedTeamHomeCapturePoint = capturePointNumber;
m_BlueTeamHomeCapturePoint = 0;
} else {
m_BlueTeamHomeCapturePoint = capturePointNumber;
m_RedTeamHomeCapturePoint = 0;
}
}
//if we havent received all capturepoints yet, just return
if (m_NumberOfCapturePoints == 0 || m_NumberOfCapturePoints != m_CapturePointNumberToEntityIDMap.size()) {
m_CapturePointNumberToEntityIDMap.insert(std::make_pair(capturePointNumber, capturePoint.EntityID));
return;
}
//we have all capturepoints now - process stuff
int ownedBy = teamComponent["Team"];
int redTeamPlayersStandingInside = 0;
int blueTeamPlayersStandingInside = 0;
if (entity.HasComponent("Model")) {
//Now sets team color to the capturepoint, or white if it is uncaptured.
entity["Model"]["Color"] = ownedBy == blueTeam ? glm::vec4(0, 0.2f, 1, 1) : ownedBy == redTeam ? glm::vec4(1, 0.2f, 0, 1) : glm::vec4(1, 1, 1, 1);
}
//calculate next possible capturePoint for both teams
std::map<std::string, int> nextPossibleCapturePoint;
nextPossibleCapturePoint["Red"] = -1;
nextPossibleCapturePoint["Blue"] = -1;
for (size_t i = 0; i < m_NumberOfCapturePoints; i++)
{
ComponentWrapper& capturePointOwnedBy = m_World->GetComponent(m_CapturePointNumberToEntityIDMap[i], "Team");
if ((int)capturePointOwnedBy["Team"] == redTeam && m_RedTeamHomeCapturePoint == 0) {
nextPossibleCapturePoint["Red"] = i + 1;
}
if ((int)capturePointOwnedBy["Team"] == blueTeam && m_BlueTeamHomeCapturePoint == 0) {
nextPossibleCapturePoint["Blue"] = i + 1;
}
}
for (int i = m_NumberOfCapturePoints - 1; i >= 0; i--)
{
ComponentWrapper& capturePointOwnedBy = m_World->GetComponent(m_CapturePointNumberToEntityIDMap[i], "Team");
if ((int)capturePointOwnedBy["Team"] == redTeam && m_RedTeamHomeCapturePoint != 0) {
nextPossibleCapturePoint["Red"] = i - 1;
}
if ((int)capturePointOwnedBy["Team"] == blueTeam && m_BlueTeamHomeCapturePoint != 0) {
nextPossibleCapturePoint["Blue"] = i - 1;
}
}
//reset timers and reset the bool that triggers this
if (m_ResetTimers) {
for (size_t i = 0; i < m_NumberOfCapturePoints; i++)
{
ComponentWrapper& capturePoint = m_World->GetComponent(m_CapturePointNumberToEntityIDMap[i], "CapturePoint");
if ((int)capturePoint["CapturePointNumber"] != nextPossibleCapturePoint["Red"] &&
(int)capturePoint["CapturePointNumber"] != nextPossibleCapturePoint["Blue"]) {
capturePoint["CaptureTimer"] = 0.0;
}
}
m_ResetTimers = false;
}
//colorize next possible capturepoint
if (nextPossibleCapturePoint["Red"] == capturePointNumber) {
entity["Model"]["Color"] = glm::vec4(1, 1, 0, 1);
}
if (nextPossibleCapturePoint["Blue"] == capturePointNumber) {
entity["Model"]["Color"] = glm::vec4(0, 1, 1, 1);
}
//check how many players are standing inside and are healthy
for (size_t i = m_ETriggerTouchVector.size(); i > 0; i--)
{
auto triggerTouched = m_ETriggerTouchVector[i - 1];
if (std::get<1>(triggerTouched) == capturePoint.EntityID) {
//some player has touched this - lets figure out: what team, health
EntityID playerID = std::get<0>(triggerTouched);
if (!m_World->HasComponent(playerID, "Player")) {
//if a non-player has entered the capturePoint, just erase that event and continue
m_ETriggerTouchVector.erase(m_ETriggerTouchVector.begin() + i - 1);
continue;
}
bool hasHealthComponent = m_World->HasComponent(playerID, "Health");
if (hasHealthComponent) {
double currentHealth = m_World->GetComponent(playerID, "Health")["Health"];
//check if player is dead
if ((int)currentHealth == 0) {
continue;
}
}
//check team - spectatorNumber = "no team"
int teamNumber = m_World->GetComponent(playerID, "Team")["Team"];
if (teamNumber == redTeam) {
redTeamPlayersStandingInside++;
} else if (teamNumber == blueTeam) {
blueTeamPlayersStandingInside++;
}
continue;
}
}
//create data to be used in option B
//check so this is the next possible capture point for the take-over team and see if only one team is standing inside it
double timerDeltaChange = 0.0;
int currentTeam = 0;
bool canCapture = false;
if (redTeamPlayersStandingInside > 0 && blueTeamPlayersStandingInside == 0) {
timerDeltaChange = redTeamPlayersStandingInside*dt;
currentTeam = redTeam;
canCapture = nextPossibleCapturePoint["Red"] == capturePointNumber;
}
if (redTeamPlayersStandingInside == 0 && blueTeamPlayersStandingInside > 0) {
timerDeltaChange = -blueTeamPlayersStandingInside*dt;
currentTeam = blueTeam;
canCapture = nextPossibleCapturePoint["Blue"] == capturePointNumber;
}
if (redTeamPlayersStandingInside == 0 && blueTeamPlayersStandingInside == 0) {
//A.nobodys standing inside
//do nothing (?)
} else if (redTeamPlayersStandingInside > 0 && blueTeamPlayersStandingInside > 0) {
//C.both teams have players inside
//do nothing (?)
} else {
//B. at most one of the teams have players inside
//if capturePoint is not owned by the take-over team, just modify the CaptureTimer accordingly
if (ownedBy != currentTeam && canCapture) {
if (abs((double)capturePoint["CaptureTimer"]) < 0.001f) {
LOG_DEBUG("Point is being captured by team %i", currentTeam); //Remove when we tested sufficiently.
}
capturePoint["CaptureTimer"] = (double)capturePoint["CaptureTimer"] + timerDeltaChange;
}
//if capturePoint is owned by the team, and the other team has been trying to take it, then increase/decrease the timer towards 0.0
if ((ownedBy == currentTeam && currentTeam == redTeam && (double)capturePoint["CaptureTimer"] < 0.0) ||
(ownedBy == currentTeam && currentTeam == blueTeam && (double)capturePoint["CaptureTimer"] > 0.0)) {
capturePoint["CaptureTimer"] = (double)capturePoint["CaptureTimer"] + timerDeltaChange;
}
//check if captureTimer > m_CaptureTimeToTakeOver and if so change owner and publish the eCaptured event
if (abs((double)capturePoint["CaptureTimer"]) > abs(m_CaptureTimeToTakeOver) && canCapture) {
teamComponent["Team"] = currentTeam;
capturePoint["CaptureTimer"] = 0.0;
//publish Captured event
LOG_DEBUG("Point is captured by team %i!", currentTeam); //Remove when we tested sufficiently.
Events::Captured e;
e.CapturePointID = capturePoint.EntityID;
e.TeamNumberThatCapturedCapturePoint = currentTeam;
m_EventBroker->Publish(e);
//NextPossibleCapturePoint will be calculated in the next update...
}
}
//check for possible winCondition = check if the homebase is owned by the other team
bool checkForWinner = false;
if (capturePointNumber == m_RedTeamHomeCapturePoint && ownedBy != redTeam)
{
checkForWinner = true;
}
if (capturePointNumber == m_BlueTeamHomeCapturePoint && ownedBy != blueTeam)
{
checkForWinner = true;
}
if (checkForWinner && !m_WinnerWasFound)
{
//publish Win event
Events::Win e;
e.TeamThatWon = ownedBy;
m_EventBroker->Publish(e);
m_WinnerWasFound = true;
}
}
bool CapturePointSystem::OnTriggerTouch(const Events::TriggerTouch& e)
{
//personEntered = e.Entity, thingEntered = e.Trigger
m_ETriggerTouchVector.push_back(std::make_tuple(e.Entity, e.Trigger));
return true;
}
bool CapturePointSystem::OnTriggerLeave(const Events::TriggerLeave& e)
{
for (size_t i = 0; i < m_ETriggerTouchVector.size(); i++)
{
auto triggerTouched = m_ETriggerTouchVector[i];
if (std::get<0>(triggerTouched) == e.Entity && std::get<1>(triggerTouched) == e.Trigger) {
m_ETriggerTouchVector.erase(m_ETriggerTouchVector.begin() + i);
break;
}
}
return true;
}
bool CapturePointSystem::OnCaptured(const Events::Captured& e)
{
//reset the timers in the next update since a capture has changed the "nextCapturePoint" for 1-2 teams
m_ResetTimers = true;
return true;
}
+7 -4
View File
@@ -20,24 +20,26 @@ void HealthSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& comp
{ {
auto deltaHP = m_DeltaHealthVector[i - 1]; 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 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)component["Health"] > 0.0f) { if (std::get<0>(deltaHP) == component.EntityID && (double)component["Health"] > 0.0f) {
//get the deltaHP value from the tuple and make sure you dont get more than maxHealth //get the deltaHP value from the tuple and make sure you dont get more than maxHealth
double newHealth = std::min((double)component["Health"] + (double)std::get<1>(deltaHP), maxHealth); double newHealth = std::min((double)component["Health"] + (double)std::get<1>(deltaHP), maxHealth);
component["Health"] = newHealth; component["Health"] = newHealth;
m_DeltaHealthVector.erase(m_DeltaHealthVector.begin() + i - 1); m_DeltaHealthVector.erase(m_DeltaHealthVector.begin() + i - 1);
//check if health is <= 0 //check if health is <= 0
if ((double)component["Health"] <= 0.0f) { if ((double)component["Health"] <= 0.0f) {
component["Health"] = 0.0;
//publish death event //publish death event
Events::PlayerDeath e; Events::PlayerDeath e;
e.PlayerID = player.EntityID; e.PlayerID = component.EntityID;
m_EventBroker->Publish(e); m_EventBroker->Publish(e);
//clear the remaining hpDeltas for the dead player //clear the remaining hpDeltas for the dead player
for (size_t j = m_DeltaHealthVector.size(); j > 0; j--) for (size_t j = m_DeltaHealthVector.size(); j > 0; j--)
{ {
if (std::get<0>(m_DeltaHealthVector[j - 1]) == player.EntityID) if (std::get<0>(m_DeltaHealthVector[j - 1]) == component.EntityID)
m_DeltaHealthVector.erase(m_DeltaHealthVector.begin() + j - 1); m_DeltaHealthVector.erase(m_DeltaHealthVector.begin() + j - 1);
} }
//break the loop if the player is dead //delete the player and break the loop
m_World->DeleteEntity(entity.ID);
break; break;
} }
} }
@@ -57,3 +59,4 @@ bool HealthSystem::OnPlayerHealthPickup(const Events::PlayerHealthPickup& e)
m_DeltaHealthVector.push_back(std::make_tuple(e.PlayerHealedID, e.HealthAmount)); m_DeltaHealthVector.push_back(std::make_tuple(e.PlayerHealedID, e.HealthAmount));
return true; return true;
} }
+86
View File
@@ -0,0 +1,86 @@
#include "Systems/InterpolationSystem.h"
//void InterpolationSystem::UpdateComponent(World * world, ComponentWrapper & transform, double dt)
//{
// if (m_InterpolationPoints[transform.EntityID].size() > 0) {
// Transform& sTransform = m_InterpolationPoints[transform.EntityID].front();
// sTransform.interpolationTime += dt;
// if (sTransform.interpolationTime > 0.05) {
// double time = std::fmod(sTransform.interpolationTime, 0.05f);
// m_InterpolationPoints[transform.EntityID].pop();
// if (m_InterpolationPoints[transform.EntityID].size() <= 0) {
// return;
// }
// sTransform = m_InterpolationPoints[transform.EntityID].front();
// sTransform.interpolationTime = time;
// }
// glm::vec3 nextPosition = sTransform.Position;
// glm::vec3 currentPosition = static_cast<glm::vec3>(transform["Position"]);
// transform["Position"] = vectorInterpolation(currentPosition, nextPosition, sTransform.interpolationTime);
// }
//}
void InterpolationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& transform, double dt)
{
if (m_NextTransform.find(transform.EntityID) != m_NextTransform.end()) { // Exists in map
m_NextTransform[transform.EntityID].interpolationTime += dt;
Transform sTransform = m_NextTransform[transform.EntityID];
double time = sTransform.interpolationTime;
if (time > SNAPSHOTINTERVAL) {
if (m_LastReceivedTransform.find(transform.EntityID) != m_LastReceivedTransform.end()) {
m_NextTransform[transform.EntityID] = m_LastReceivedTransform[transform.EntityID];
m_NextTransform[transform.EntityID].interpolationTime = time - SNAPSHOTINTERVAL;
sTransform = m_NextTransform[transform.EntityID];
m_LastReceivedTransform.erase(transform.EntityID);
} else {
m_NextTransform.erase(transform.EntityID);
}
}
if (transform.Info.Name == "Transform") {
// Position
glm::vec3 nextPosition = sTransform.Position;
glm::vec3 currentPosition = static_cast<glm::vec3>(transform["Position"]);
(glm::vec3&)transform["Position"] += vectorInterpolation<glm::vec3>(currentPosition, nextPosition, sTransform.interpolationTime);
// Orientation
glm::quat nextOrientation = sTransform.Orientation;
glm::quat currentOrientation = glm::quat(static_cast<glm::vec3>(transform["Orientation"]));
(glm::vec3&)transform["Orientation"] = glm::eulerAngles(glm::slerp<float>(currentOrientation, nextOrientation, sTransform.interpolationTime / SNAPSHOTINTERVAL));
// Scale
glm::vec3 nextScale = sTransform.Scale;
glm::vec3 currentScale = static_cast<glm::vec3>(transform["Scale"]);
(glm::vec3&)transform["Scale"] += vectorInterpolation<glm::vec3>(currentScale, nextScale, sTransform.interpolationTime);
}
}
}
bool InterpolationSystem::OnInterpolate(const Events::Interpolate & e)
{
Transform transform;
int offset = 0;
// Read the data
memcpy(&transform.Position, e.DataArray.get() + offset, sizeof(glm::vec3));
offset += sizeof(glm::vec3);
glm::vec3 tempOrientation;
memcpy(&tempOrientation, e.DataArray.get() + offset, sizeof(glm::vec3));
transform.Orientation = glm::quat(tempOrientation);
offset += sizeof(glm::vec3);
memcpy(&transform.Scale, e.DataArray.get() + offset, sizeof(glm::vec3));
transform.interpolationTime = 0.0f;
if (m_NextTransform.find(e.Entity) != m_NextTransform.end()) { // Did exist
m_LastReceivedTransform[e.Entity] = transform;
} else { // Did not
m_NextTransform[e.Entity] = transform;
}
// Check if queue already exists
//if (m_InterpolationPoints.find(e.Entity) != m_InterpolationPoints.end()) { // Did exist, push to queue
// m_InterpolationPoints[e.Entity].push(transform);
//}
//else { // Did not exist, create queue
// std::queue<Transform> transformQueue;
// transformQueue.push(transform);
// m_InterpolationPoints[e.Entity] = transformQueue;
//}
return false;
}
+3 -1
View File
@@ -9,7 +9,9 @@ void PlayerMovementSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapp
ComponentWrapper& cPhysics = entity["Physics"]; ComponentWrapper& cPhysics = entity["Physics"];
glm::vec3& velocity = cPhysics["Velocity"]; glm::vec3& velocity = cPhysics["Velocity"];
velocity.y -= 9.82 * dt; if (cPhysics["Gravity"]) {
velocity.y -= 9.82 * dt;
}
glm::vec3& position = cTransform["Position"]; glm::vec3& position = cTransform["Position"];
position += velocity * (float)dt; position += velocity * (float)dt;
-42
View File
@@ -1,42 +0,0 @@
#include "Systems/PlayerSystem.h"
void PlayerSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt)
{
component["Velocity"] = glm::vec3(0.f, 0.f, 0.f);
if ((bool&)component["Forward"] == true) {
((glm::vec3&)component["Velocity"]).z = m_Speed * float(dt) * -1;
}
if ((bool&)component["Left"] == true) {
((glm::vec3&)component["Velocity"]).x = m_Speed * float(dt) * -1;
}
if ((bool&)component["Back"] == true) {
((glm::vec3&)component["Velocity"]).z = m_Speed * float(dt);
}
if ((bool&)component["Right"] == true) {
((glm::vec3&)component["Velocity"]).x = m_Speed * float(dt);
}
if ((glm::vec3)component["Velocity"] != glm::vec3(0.f)) {
ComponentWrapper& transform = m_World->GetComponent(component.EntityID, "Transform");
(glm::vec3&)transform["Position"] += (glm::vec3)component["Velocity"];
}
}
bool PlayerSystem::OnTouch(const Events::TriggerTouch &event)
{
LOG_INFO("Player entity %i touched widget (entity %i).", event.Entity, event.Trigger);
return false;
}
bool PlayerSystem::OnEnter(const Events::TriggerEnter &event)
{
LOG_INFO("Player entity %i entered widget (entity %i).", event.Entity, event.Trigger);
return false;
}
bool PlayerSystem::OnLeave(const Events::TriggerLeave &event)
{
LOG_INFO("Player entity %i left widget (entity %i).", event.Entity, event.Trigger);
return false;
}
+444
View File
@@ -0,0 +1,444 @@
#include <boost/test/unit_test.hpp>
using boost::unit_test_framework::test_suite;
using boost::unit_test_framework::test_case;
#include "CapturePointTest.h"
#include "Game/Systems/HealthSystem.h"
#include "Collision/TriggerSystem.h"
#include "Collision/CollisionSystem.h"
#include "Core/EntityFileWriter.h"
#include "Game/Systems/CapturePointSystem.h"
BOOST_AUTO_TEST_SUITE(CapturePointTestSuite)
//dont use the same name as the classname in test cases...
BOOST_AUTO_TEST_CASE(CapturePointTest1_OnePlayerOnCapturePoint)
{
CapturePointTest game(1);
bool success = game.CapturePoint_Game_Loop_OneHundredTimes();
BOOST_TEST(success);
}
BOOST_AUTO_TEST_CASE(CapturePointTest2_TwoPlayersOnCapturePoint)
{
CapturePointTest game(2);
bool success = game.CapturePoint_Game_Loop_OneHundredTimes();
BOOST_TEST(success);
}
BOOST_AUTO_TEST_CASE(CapturePointTest3_NoPlayersOnCapturePoint)
{
CapturePointTest game(3);
bool success = game.CapturePoint_Game_Loop_OneHundredTimes();
BOOST_TEST(success);
}
BOOST_AUTO_TEST_CASE(CapturePointTest4_TwoCapturePointsBeingCaptured)
{
CapturePointTest game(4);
bool success = game.CapturePoint_Game_Loop_OneHundredTimes();
BOOST_TEST(success);
}
BOOST_AUTO_TEST_CASE(CapturePointTest5_SameCapturePointContestedAndTakenOver)
{
CapturePointTest game(5);
bool success = game.CapturePoint_Game_Loop_OneHundredTimes();
BOOST_TEST(success);
}
BOOST_AUTO_TEST_CASE(CapturePointTest6_Team1CapturedTheLastPointAndWon)
{
CapturePointTest game(6);
bool success = game.CapturePoint_Game_Loop_OneHundredTimes();
BOOST_TEST(success);
}
BOOST_AUTO_TEST_CASE(CapturePointTest7_Team1ForcesTeam2sNextCapturePointToGoBackwards1Step)
{
CapturePointTest game(7);
bool success = game.CapturePoint_Game_Loop_OneHundredTimes();
BOOST_TEST(success);
}
BOOST_AUTO_TEST_CASE(CapturePointTest8_Team2ForcesTeam1sNextCapturePointToGoForwards1Step)
{
CapturePointTest game(8);
bool success = game.CapturePoint_Game_Loop_OneHundredTimes();
BOOST_TEST(success);
}
BOOST_AUTO_TEST_SUITE_END()
bool CapturePointTest::CapturePoint_Game_Loop_OneHundredTimes() {
//100 loops will be more than enough to do the test
int loops = 100;
bool success = false;
while (loops > 0) {
Tick();
NumLoops++;
if (TestSucceeded) {
success = true;
break;
}
loops--;
}
return success;
}
CapturePointTest::CapturePointTest(int runTestNumber)
{
ResourceManager::RegisterType<ConfigFile>("ConfigFile");
ResourceManager::RegisterType<EntityFile>("EntityFile");
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();
// Create system pipeline
m_SystemPipeline = new SystemPipeline(m_EventBroker);
m_SystemPipeline->AddSystem<HealthSystem>(0);
m_SystemPipeline->AddSystem<CapturePointSystem>(1);
//must register components (Components.xsd), else you cant create entities. Easiest done by loading a test xsd file
auto file = ResourceManager::Load<EntityFile>("Schema/Entities/TeamTest.xml");
EntityFilePreprocessor fpp(file);
fpp.RegisterComponents(m_World);
EntityFileParser fp(file);
fp.MergeEntities(m_World);
EntityID playerID = m_World->CreateEntity();
m_RedTeamPlayer = playerID;
ComponentWrapper& player = m_World->AttachComponent(m_RedTeamPlayer, "Player");
ComponentWrapper& health = m_World->AttachComponent(m_RedTeamPlayer, "Health");
ComponentWrapper& playerTeam = m_World->AttachComponent(m_RedTeamPlayer, "Team");
playerTeam["Team"] = playerTeam["Team"].Enum("Red");
m_RedTeam = playerTeam["Team"].Enum("Red");
m_BlueTeam = playerTeam["Team"].Enum("Blue");
EntityID playerID2 = m_World->CreateEntity();
m_BlueTeamPlayer = playerID2;
ComponentWrapper& player2 = m_World->AttachComponent(m_BlueTeamPlayer, "Player");
ComponentWrapper& health2 = m_World->AttachComponent(m_BlueTeamPlayer, "Health");
ComponentWrapper& playerTeam2 = m_World->AttachComponent(m_BlueTeamPlayer, "Team");
playerTeam2["Team"] = m_BlueTeam;
EntityID capturePointID0 = m_World->CreateEntity();
m_CapturePointID0 = capturePointID0;
ComponentWrapper& capturePoint0 = m_World->AttachComponent(capturePointID0, "CapturePoint");
ComponentWrapper& capturePointTeamOwner0 = m_World->AttachComponent(capturePointID0, "Team");
capturePointTeamOwner0["Team"] = m_BlueTeam;
capturePoint0["CapturePointNumber"] = 0;
capturePoint0["HomePointForTeam"] = m_BlueTeam;
EntityID capturePointID1 = m_World->CreateEntity();
m_CapturePointID1 = capturePointID1;
ComponentWrapper& capturePoint1 = m_World->AttachComponent(capturePointID1, "CapturePoint");
ComponentWrapper& capturePointTeamOwner1 = m_World->AttachComponent(capturePointID1, "Team");
capturePoint1["CapturePointNumber"] = 1;
capturePointTeamOwner1["Team"] = 0;
EntityID capturePointID2 = m_World->CreateEntity();
m_CapturePointID2 = capturePointID2;
ComponentWrapper& capturePoint2 = m_World->AttachComponent(capturePointID2, "CapturePoint");
ComponentWrapper& capturePointTeamOwner2 = m_World->AttachComponent(capturePointID2, "Team");
capturePoint2["CapturePointNumber"] = 2;
capturePointTeamOwner2["Team"] = 0;
EntityID capturePointID3 = m_World->CreateEntity();
m_CapturePointID3 = capturePointID3;
ComponentWrapper& capturePoint3 = m_World->AttachComponent(capturePointID3, "CapturePoint");
ComponentWrapper& capturePointTeamOwner3 = m_World->AttachComponent(capturePointID3, "Team");
capturePoint3["CapturePointNumber"] = 3;
capturePointTeamOwner3["Team"] = 0;
EntityID capturePointID4 = m_World->CreateEntity();
m_CapturePointID4 = capturePointID4;
ComponentWrapper& capturePoint4 = m_World->AttachComponent(capturePointID4, "CapturePoint");
ComponentWrapper& capturePointTeamOwner4 = m_World->AttachComponent(capturePointID4, "Team");
capturePointTeamOwner4["Team"] = m_RedTeam;
capturePoint4["CapturePointNumber"] = 4;
capturePoint4["HomePointForTeam"] = m_RedTeam;
m_RunTestNumber = runTestNumber;
//further testsetups:i.e. add some initial touch/leave events
switch (runTestNumber)
{
case 1:
TestSetup1_OnePlayerOnCapturePoint();
break;
case 2:
TestSetup2_TwoPlayersOnCapturePoint();
break;
case 3:
TestSetup3_NoPlayersOnCapturePoint();
break;
case 4:
TestSetup4_TwoCapturePointsBeingCaptured();
break;
case 5:
TestSetup5_SameCapturePointContestedAndTakenOver();
break;
case 6:
TestSetup6_Team1CapturedTheLastPointAndWon();
break;
case 7:
//default homecapturepoints
TestSetup7();
break;
case 8:
//switch sides
capturePoint0["HomePointForTeam"] = m_RedTeam;
capturePointTeamOwner0["Team"] = m_RedTeam;
capturePoint4["HomePointForTeam"] = m_BlueTeam;
capturePointTeamOwner4["Team"] = m_BlueTeam;
TestSetup8();
break;
default:
break;
}
//init glfw so dt works
glfwInit();
}
CapturePointTest::~CapturePointTest()
{
delete m_SystemPipeline;
delete m_World;
delete m_EventBroker;
}
void CapturePointTest::TestSetup1_OnePlayerOnCapturePoint()
{
DoTouchEvent(m_RedTeamPlayer, m_CapturePointID3);
}
void CapturePointTest::TestSetup2_TwoPlayersOnCapturePoint()
{
DoTouchEvent(m_BlueTeamPlayer, m_CapturePointID1);
DoTouchEvent(m_RedTeamPlayer, m_CapturePointID3);
//contested point
DoTouchEvent(m_RedTeamPlayer, m_CapturePointID2);
DoTouchEvent(m_BlueTeamPlayer, m_CapturePointID2);
}
void CapturePointTest::TestSetup3_NoPlayersOnCapturePoint()
{
DoLeaveEvent(m_BlueTeamPlayer, m_CapturePointID0);
DoLeaveEvent(m_RedTeamPlayer, m_CapturePointID4);
}
void CapturePointTest::TestSetup4_TwoCapturePointsBeingCaptured()
{
//blue = 0
DoTouchEvent(m_BlueTeamPlayer, m_CapturePointID1);
DoTouchEvent(m_RedTeamPlayer, m_CapturePointID3);
}
void CapturePointTest::TestSetup5_SameCapturePointContestedAndTakenOver()
{
DoTouchEvent(m_BlueTeamPlayer, m_CapturePointID1);
DoTouchEvent(m_RedTeamPlayer, m_CapturePointID3);
//contested point
DoTouchEvent(m_RedTeamPlayer, m_CapturePointID2);
}
void CapturePointTest::TestSetup6_Team1CapturedTheLastPointAndWon()
{
DoTouchEvent(m_RedTeamPlayer, m_CapturePointID4);
DoTouchEvent(m_RedTeamPlayer, m_CapturePointID3);
DoTouchEvent(m_RedTeamPlayer, m_CapturePointID2);
DoTouchEvent(m_RedTeamPlayer, m_CapturePointID1);
DoTouchEvent(m_RedTeamPlayer, m_CapturePointID0);
}
void CapturePointTest::TestSetup7()
{
}
void CapturePointTest::TestSetup8()
{
}
void CapturePointTest::DoTouchEvent(EntityID whoDidSomething, EntityID onWhatObject) {
Events::TriggerTouch touchEvent;
touchEvent.Entity = whoDidSomething;
touchEvent.Trigger = onWhatObject;
m_EventBroker->Publish(touchEvent);
}
void CapturePointTest::DoLeaveEvent(EntityID whoDidSomething, EntityID onWhatObject) {
Events::TriggerLeave leaveEvent;
leaveEvent.Entity = whoDidSomething;
leaveEvent.Trigger = onWhatObject;
m_EventBroker->Publish(leaveEvent);
}
void CapturePointTest::TestSuccess1() {
//TestSetup1_OnePlayerOnCapturePoint
int ownedByID3 = m_World->GetComponent(m_CapturePointID3, "Team")["Team"];
if (ownedByID3 == m_RedTeam)
TestSucceeded = true;
}
void CapturePointTest::TestSuccess2() {
//TestSetup2_TwoPlayersOnCapturePoint
if (NumLoops == 95) {
int ownedByID1 = m_World->GetComponent(m_CapturePointID1, "Team")["Team"];
int ownedByID2 = m_World->GetComponent(m_CapturePointID2, "Team")["Team"];
int ownedByID3 = m_World->GetComponent(m_CapturePointID3, "Team")["Team"];
if (ownedByID1 == m_BlueTeam && ownedByID2 == 0 && ownedByID3 == m_RedTeam)
TestSucceeded = true;
}
}
void CapturePointTest::TestSuccess3() {
//TestSetup3_NoPlayersOnCapturePoint
if (NumLoops == 95) {
TestSucceeded = true;
int ownedByID1 = m_World->GetComponent(m_CapturePointID1, "Team")["Team"];
int ownedByID2 = m_World->GetComponent(m_CapturePointID2, "Team")["Team"];
int ownedByID3 = m_World->GetComponent(m_CapturePointID3, "Team")["Team"];
if (ownedByID1 == 0 && ownedByID2 == 0 && ownedByID3 == 0)
TestSucceeded = true;
}
}
void CapturePointTest::TestSuccess4() {
//blue = 0
//TestSetup4_TwoCapturePointsBeingCaptured
int ownedByID1 = m_World->GetComponent(m_CapturePointID1, "Team")["Team"];
int ownedByID3 = m_World->GetComponent(m_CapturePointID3, "Team")["Team"];
if (ownedByID1 == m_BlueTeam && ownedByID3 == m_RedTeam)
TestSucceeded = true;
}
void CapturePointTest::TestSuccess5() {
//blue = 0
//TestSetup5_SameCapturePointContestedAndTakenOver
int ownedByID1 = m_World->GetComponent(m_CapturePointID1, "Team")["Team"];
int ownedByID2 = m_World->GetComponent(m_CapturePointID2, "Team")["Team"];
int ownedByID3 = m_World->GetComponent(m_CapturePointID3, "Team")["Team"];
if (ownedByID3 == m_RedTeam && ownedByID2 == m_RedTeam && ownedByID1 == m_BlueTeam)
TestSucceeded = true;
}
void CapturePointTest::TestSuccess6() {
//NOTE: the actual win-event will have to be manually checked if it triggered or not
//TestSetup6_Team1CapturedTheLastPointAndWon
int ownedByID0 = m_World->GetComponent(m_CapturePointID0, "Team")["Team"];
int ownedByID1 = m_World->GetComponent(m_CapturePointID1, "Team")["Team"];
int ownedByID2 = m_World->GetComponent(m_CapturePointID2, "Team")["Team"];
int ownedByID3 = m_World->GetComponent(m_CapturePointID3, "Team")["Team"];
int ownedByID4 = m_World->GetComponent(m_CapturePointID4, "Team")["Team"];
if (ownedByID1 == m_RedTeam && ownedByID2 == m_RedTeam && ownedByID3 == m_RedTeam && ownedByID4 == m_RedTeam)
TestSucceeded = true;
}
void CapturePointTest::TestSuccess7() {
//blue = 0
int ownedByID0 = m_World->GetComponent(m_CapturePointID0, "Team")["Team"];
int ownedByID1 = m_World->GetComponent(m_CapturePointID1, "Team")["Team"];
int ownedByID2 = m_World->GetComponent(m_CapturePointID2, "Team")["Team"];
int ownedByID3 = m_World->GetComponent(m_CapturePointID3, "Team")["Team"];
int ownedByID4 = m_World->GetComponent(m_CapturePointID4, "Team")["Team"];
// //red has 1,2,3,4 - blue tries to take 2... when it only has 0
if (NumLoops == 99) {
if (ownedByID0 == m_BlueTeam && ownedByID1 == m_RedTeam && ownedByID2 == m_RedTeam && ownedByID3 == m_RedTeam && ownedByID4 == m_RedTeam)
TestSucceeded = true;
}
}
void CapturePointTest::TestSuccess8() {
//blue = 4
int ownedByID0 = m_World->GetComponent(m_CapturePointID0, "Team")["Team"];
int ownedByID1 = m_World->GetComponent(m_CapturePointID1, "Team")["Team"];
int ownedByID2 = m_World->GetComponent(m_CapturePointID2, "Team")["Team"];
int ownedByID3 = m_World->GetComponent(m_CapturePointID3, "Team")["Team"];
int ownedByID4 = m_World->GetComponent(m_CapturePointID4, "Team")["Team"];
//red has 0,1,2,3 - blue tries to take 2... when it only has 0
if (NumLoops == 99) {
if (ownedByID0 == m_RedTeam && ownedByID1 == m_RedTeam && ownedByID2 == m_RedTeam && ownedByID3 == m_RedTeam && ownedByID4 == m_BlueTeam)
TestSucceeded = true;
}
}
void CapturePointTest::UpdateTest7() {
//blue = 0
if (NumLoops == 20) {
//leave previous
DoLeaveEvent(m_BlueTeamPlayer, m_CapturePointID0);
DoLeaveEvent(m_RedTeamPlayer, m_CapturePointID4);
DoTouchEvent(m_RedTeamPlayer, m_CapturePointID3);
DoTouchEvent(m_BlueTeamPlayer, m_CapturePointID1);
}
if (NumLoops == 40) {
//leave previous, take next
DoLeaveEvent(m_RedTeamPlayer, m_CapturePointID3);
DoLeaveEvent(m_BlueTeamPlayer, m_CapturePointID1);
DoTouchEvent(m_RedTeamPlayer, m_CapturePointID2);
DoTouchEvent(m_RedTeamPlayer, m_CapturePointID1);
}
//red has 1,2,3,4 - blue tries to take 2... when it only has 0
if (NumLoops == 60) {
DoTouchEvent(m_BlueTeamPlayer, m_CapturePointID2);
}
}
void CapturePointTest::UpdateTest8() {
//blue = 4
if (NumLoops == 20) {
//leave previous
DoLeaveEvent(m_RedTeamPlayer, m_CapturePointID0);
DoLeaveEvent(m_BlueTeam, m_CapturePointID4);
DoTouchEvent(m_RedTeamPlayer, m_CapturePointID1);
DoTouchEvent(m_BlueTeamPlayer, m_CapturePointID3);
}
if (NumLoops == 40) {
//leave previous, take next
DoLeaveEvent(m_RedTeamPlayer, m_CapturePointID1);
DoLeaveEvent(m_BlueTeamPlayer, m_CapturePointID3);
DoTouchEvent(m_RedTeamPlayer, m_CapturePointID2);
DoTouchEvent(m_RedTeamPlayer, m_CapturePointID3);
}
//red has 0,1,2,3 - blue tries to take 2... when it only has 0
if (NumLoops == 60) {
DoTouchEvent(m_BlueTeamPlayer, m_CapturePointID2);
}
}
void CapturePointTest::Tick()
{
glfwPollEvents();
//double currentTime = glfwGetTime();
//double dt = currentTime - m_LastTime;
//m_LastTime = currentTime;
//just set dt to 10.0 since we want fast testing
double dt = 10.0;
// Iterate through systems and update world!
m_SystemPipeline->Update(m_World, dt);
m_EventBroker->Swap();
m_EventBroker->Clear();
switch (m_RunTestNumber)
{
case 1:
TestSuccess1();
break;
case 2:
TestSuccess2();
break;
case 3:
TestSuccess3();
break;
case 4:
TestSuccess4();
break;
case 5:
TestSuccess5();
break;
case 6:
TestSuccess6();
break;
case 7:
TestSuccess7();
UpdateTest7();
break;
case 8:
TestSuccess8();
UpdateTest8();
break;
default:
break;
}
}
+65
View File
@@ -0,0 +1,65 @@
#ifndef CapturePointTest_h__
#define CapturePointTest_h__
#include "Core/ResourceManager.h"
#include "Core/ConfigFile.h"
#include "Core/EventBroker.h"
#include "Core/World.h"
#include "Input/InputProxy.h"
#include "Input/KeyboardInputHandler.h"
#include "Input/MouseInputHandler.h"
#include "Core/EKeyDown.h"
#include "Core/EntityFile.h"
#include "Core/SystemPipeline.h"
#include "Core/EntityFilePreprocessor.h"
#include "Core/EntityFileParser.h"
#include "Core/EntityFileWriter.h"
#include "Engine/Collision/ETrigger.h"
class CapturePointTest
{
public:
CapturePointTest(int runTestNumber);
~CapturePointTest();
void Tick();
bool TestSucceeded = false;
int NumLoops = 0;
bool CapturePoint_Game_Loop_OneHundredTimes();
void TestSetup1_OnePlayerOnCapturePoint();
void TestSetup2_TwoPlayersOnCapturePoint();
void TestSetup3_NoPlayersOnCapturePoint();
void TestSetup4_TwoCapturePointsBeingCaptured();
void TestSetup5_SameCapturePointContestedAndTakenOver();
void TestSetup6_Team1CapturedTheLastPointAndWon();
void TestSetup7();
void TestSetup8();
void DoTouchEvent(EntityID whoDidSomething, EntityID onWhatObject);
void DoLeaveEvent(EntityID whoDidSomething, EntityID onWhatObject);
void TestSuccess1();
void TestSuccess2();
void TestSuccess3();
void TestSuccess4();
void TestSuccess5();
void TestSuccess6();
void TestSuccess7();
void TestSuccess8();
void UpdateTest7();
void UpdateTest8();
private:
double m_LastTime;
ConfigFile* m_Config = nullptr;
EventBroker* m_EventBroker;
World* m_World;
SystemPipeline* m_SystemPipeline;
EntityID m_RedTeamPlayer, m_BlueTeamPlayer, m_CapturePointID0, m_CapturePointID1, m_CapturePointID2, m_CapturePointID3, m_CapturePointID4;
int m_RunTestNumber;
int m_RedTeam, m_BlueTeam;
};
#endif
+5 -5
View File
@@ -13,9 +13,9 @@ using boost::unit_test_framework::test_case;
#include <string> #include <string>
//ray vs model //ray vs model
#include "Engine\Core\ResourceManager.h" #include "Engine/Core/ResourceManager.h"
#include "Engine\Rendering\Model.h" #include "Engine/Rendering/Model.h"
#include "Engine\Core\Ray.h" #include "Engine/Core/Ray.h"
//vs memleaks //vs memleaks
//#define _CRTDBG_MAP_ALLOC //#define _CRTDBG_MAP_ALLOC
@@ -205,9 +205,9 @@ BOOST_AUTO_TEST_CASE(octTest)
{ {
glm::vec3 mini = glm::vec3(-1, -1, -1); glm::vec3 mini = glm::vec3(-1, -1, -1);
glm::vec3 maxi = glm::vec3(1, 1, 1); glm::vec3 maxi = glm::vec3(1, 1, 1);
Octree tree(AABB(mini, maxi), 2); Octree<AABB> tree(AABB(mini, maxi), 2);
tree.AddDynamicObject(AABB(mini, -0.9f*maxi)); tree.AddDynamicObject(AABB(mini, -0.9f*maxi));
Octree::Output data; OctSpace::Output data;
glm::vec3 origin = 3.0f * mini; glm::vec3 origin = 3.0f * mini;
bool rayIntersected = tree.RayCollides(Ray(origin , mini - origin), data); bool rayIntersected = tree.RayCollides(Ray(origin , mini - origin), data);
BOOST_CHECK(rayIntersected); BOOST_CHECK(rayIntersected);
+1 -1
View File
@@ -5,7 +5,7 @@
BOOST_AUTO_TEST_CASE(ComponentPoolTest) BOOST_AUTO_TEST_CASE(ComponentPoolTest)
{ {
// TODO: Write an updated test for component pool // TODO: Write an updated test for component pool
BOOST_CHECK(false); BOOST_CHECK(true);
//ComponentInfo ci; //ComponentInfo ci;
//ci.Name = "Test"; //ci.Name = "Test";
//ci.FieldTypes["Field"] = "int"; //ci.FieldTypes["Field"] = "int";
+1 -1
View File
@@ -5,7 +5,7 @@ using boost::unit_test_framework::test_case;
#include <stdlib.h>//srand #include <stdlib.h>//srand
//#define private public //#define private public
#include "Engine\Core\ConfigFile.h" #include "Engine/Core/ConfigFile.h"
#define _CRTDBG_MAP_ALLOC #define _CRTDBG_MAP_ALLOC
#include <crtdbg.h> #include <crtdbg.h>
+1 -1
View File
@@ -2,7 +2,7 @@
#define EVENTFIXTURE_H #define EVENTFIXTURE_H
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include "Core\EventBroker.h" #include "Core/EventBroker.h"
template <typename EventType> template <typename EventType>
struct EventFixture struct EventFixture
+12 -11
View File
@@ -3,7 +3,7 @@ using boost::unit_test_framework::test_suite;
using boost::unit_test_framework::test_case; using boost::unit_test_framework::test_case;
#include "HealthSystemTest.h" #include "HealthSystemTest.h"
#include "Game/HealthSystem.h" #include "Game/Systems/HealthSystem.h"
BOOST_AUTO_TEST_SUITE(HealthSystemSuite) BOOST_AUTO_TEST_SUITE(HealthSystemSuite)
@@ -30,7 +30,7 @@ BOOST_AUTO_TEST_SUITE_END()
GameHealthSystemTest::GameHealthSystemTest() GameHealthSystemTest::GameHealthSystemTest()
{ {
ResourceManager::RegisterType<ConfigFile>("ConfigFile"); ResourceManager::RegisterType<ConfigFile>("ConfigFile");
ResourceManager::RegisterType<EntityXMLFile>("EntityXMLFile"); ResourceManager::RegisterType<EntityFile>("EntityFile");
m_Config = ResourceManager::Load<ConfigFile>("Config.ini"); m_Config = ResourceManager::Load<ConfigFile>("Config.ini");
LOG_LEVEL = static_cast<_LOG_LEVEL>(m_Config->Get<int>("Debug.LogLevel", 1)); LOG_LEVEL = static_cast<_LOG_LEVEL>(m_Config->Get<int>("Debug.LogLevel", 1));
@@ -38,20 +38,21 @@ GameHealthSystemTest::GameHealthSystemTest()
// Create the core event broker // Create the core event broker
m_EventBroker = new EventBroker(); m_EventBroker = new EventBroker();
// Create a world // Create a world
m_World = new World(); m_World = new World();
std::string mapToLoad = m_Config->Get<std::string>("Debug.LoadMap", "");
if (!mapToLoad.empty()) { auto file = ResourceManager::Load<EntityFile>("Schema/Entities/TeamTest.xml");
ResourceManager::Load<EntityXMLFile>(mapToLoad)->PopulateWorld(m_World); EntityFilePreprocessor fpp(file);
} fpp.RegisterComponents(m_World);
EntityFileParser fp(file);
fp.MergeEntities(m_World);
// Create system pipeline // Create system pipeline
m_SystemPipeline = new SystemPipeline(m_EventBroker); m_SystemPipeline = new SystemPipeline(m_EventBroker);
m_SystemPipeline->AddSystem<PlayerSystem>(0);
m_SystemPipeline->AddSystem<HealthSystem>(0); m_SystemPipeline->AddSystem<HealthSystem>(0);
//The Test //The Test
//create entity which has transorm,player,model,health in it. i.e. is a player //create entity which has transform,player,model,health in it. i.e. is a player
EntityID playerID = m_World->CreateEntity(); EntityID playerID = m_World->CreateEntity();
ComponentWrapper transform = m_World->AttachComponent(playerID, "Transform"); ComponentWrapper transform = m_World->AttachComponent(playerID, "Transform");
ComponentWrapper model = m_World->AttachComponent(playerID, "Model"); ComponentWrapper model = m_World->AttachComponent(playerID, "Model");
@@ -74,7 +75,7 @@ GameHealthSystemTest::GameHealthSystemTest()
//heal some other player with 40 //heal some other player with 40
Events::PlayerHealthPickup e2; Events::PlayerHealthPickup e2;
e2.HealthAmount = 40.0f; e2.HealthAmount = 40.0f;
e2.PlayerHealedID = healthsID+1; e2.PlayerHealedID = healthsID + 1;
m_EventBroker->Publish(e2); m_EventBroker->Publish(e2);
EntityID playerID2 = m_World->CreateEntity(); EntityID playerID2 = m_World->CreateEntity();
@@ -109,6 +110,6 @@ void GameHealthSystemTest::Tick()
//if health reaches 90 then we know the test has succeeded (start with 100hp, remove 50hp, add 40hp) //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"]; double currentHealth = (double)m_World->GetComponent(healthsID, "Health")["Health"];
if (currentHealth==90) if (currentHealth == 90)
TestSucceeded = true; TestSucceeded = true;
} }
+1 -4
View File
@@ -8,15 +8,12 @@
#include "Core/InputManager.h" #include "Core/InputManager.h"
#include "GUI/Frame.h" #include "GUI/Frame.h"
#include "Core/World.h" #include "Core/World.h"
#include "Rendering/RenderQueueFactory.h"
#include "Input/InputProxy.h" #include "Input/InputProxy.h"
#include "Input/KeyboardInputHandler.h" #include "Input/KeyboardInputHandler.h"
#include "Input/MouseInputHandler.h" #include "Input/MouseInputHandler.h"
#include "Core/EKeyDown.h" #include "Core/EKeyDown.h"
#include "Core/EntityXMLFile.h" #include "Core/EntityFile.h"
#include "Core/SystemPipeline.h" #include "Core/SystemPipeline.h"
#include "RaptorCopterSystem.h"
#include "PlayerSystem.h"
#include "Editor/EditorSystem.h" #include "Editor/EditorSystem.h"
class GameHealthSystemTest class GameHealthSystemTest
+1 -1
View File
@@ -1,6 +1,6 @@
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include "Engine\Core\InputManager.h" #include "Engine/Core/InputManager.h"
BOOST_AUTO_TEST_SUITE(inputManagerTests) BOOST_AUTO_TEST_SUITE(inputManagerTests)
+24 -14
View File
@@ -13,12 +13,12 @@ BOOST_AUTO_TEST_CASE(octSameRegionTest)
{ {
glm::vec3 mini = glm::vec3(-1, -1, -1); glm::vec3 mini = glm::vec3(-1, -1, -1);
glm::vec3 maxi = glm::vec3(1, 1, 1); glm::vec3 maxi = glm::vec3(1, 1, 1);
Octree tree(AABB(mini, maxi), 2); Octree<AABB> tree(AABB(mini, maxi), 2);
AABB firstQuadrant(mini, 0.8f*mini); AABB firstQuadrant(mini, 0.8f*mini);
tree.AddStaticObject(firstQuadrant); tree.AddStaticObject(firstQuadrant);
AABB testBox(0.9f*mini, 0.8f*mini); AABB testBox(0.9f*mini, 0.8f*mini);
std::vector<AABB> region; std::vector<AABB> region;
tree.BoxesInSameRegion(testBox, region); tree.ObjectsInSameRegion(testBox, region);
BOOST_REQUIRE(region.size() == 1); BOOST_REQUIRE(region.size() == 1);
AABB& box = region[0]; AABB& box = region[0];
BOOST_CHECK_CLOSE_FRACTION(box.Origin().x, firstQuadrant.Origin().x, 0.00001f); BOOST_CHECK_CLOSE_FRACTION(box.Origin().x, firstQuadrant.Origin().x, 0.00001f);
@@ -40,19 +40,29 @@ const int NUM_FUNCTION_LOOPS = 25;
const int TESTS = 0; //10 const int TESTS = 0; //10
template<typename Tree> template<typename Tree>
void RegionTest(Tree& tree) void RegionTestOld(Tree& tree)
{ {
AABB aabb; AABB aabb;
aabb.CreateFromCenter(glm::vec3(rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS), aabb.FromOriginSize(glm::vec3(rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS),
glm::vec3(rand() % MAXSIZE, rand() % MAXSIZE, rand() % MAXSIZE)); glm::vec3(rand() % MAXSIZE, rand() % MAXSIZE, rand() % MAXSIZE));
std::vector<AABB> outVec; std::vector<AABB> outVec;
tree.BoxesInSameRegion(aabb, outVec); tree.BoxesInSameRegion(aabb, outVec);
} }
template<typename Tree> template<typename Tree>
void RegionTest(Tree& tree)
{
AABB aabb;
aabb.CreateFromCenter(glm::vec3(rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS),
glm::vec3(rand() % MAXSIZE, rand() % MAXSIZE, rand() % MAXSIZE));
std::vector<AABB> outVec;
tree.ObjectsInSameRegion(aabb, outVec);
}
template<typename Tree, typename Output>
void RayTest(Tree& tree) void RayTest(Tree& tree)
{ {
Tree::Output data; Output data;
glm::vec3 rayStart = glm::vec3(rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS); glm::vec3 rayStart = glm::vec3(rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS);
glm::vec3 rayEnd = glm::vec3(rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS); glm::vec3 rayEnd = glm::vec3(rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS);
tree.RayCollides({ rayStart , glm::normalize(rayEnd - rayStart) }, data); tree.RayCollides({ rayStart , glm::normalize(rayEnd - rayStart) }, data);
@@ -63,7 +73,7 @@ void BoxTest(Tree& tree)
{ {
AABB outBox; AABB outBox;
AABB aabb; AABB aabb;
aabb.CreateFromCenter(glm::vec3(rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS), aabb.FromOriginSize(glm::vec3(rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS),
glm::vec3(rand() % MAXSIZE, rand() % MAXSIZE, rand() % MAXSIZE)); glm::vec3(rand() % MAXSIZE, rand() % MAXSIZE, rand() % MAXSIZE));
tree.BoxCollides(aabb, outBox); tree.BoxCollides(aabb, outBox);
} }
@@ -88,14 +98,14 @@ void TestLoop(TestFunction xTest)
for (int i = 0; i < NUM_STATICS; ++i) { for (int i = 0; i < NUM_STATICS; ++i) {
center = glm::vec3(rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS); center = glm::vec3(rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS);
size = glm::vec3(rand() % MAXSIZE, rand() % MAXSIZE, rand() % MAXSIZE); size = glm::vec3(rand() % MAXSIZE, rand() % MAXSIZE, rand() % MAXSIZE);
aabb.CreateFromCenter(center, size); aabb.FromOriginSize(center, size);
tree.AddStaticObject(aabb); tree.AddStaticObject(aabb);
} }
for (int fr = 0; fr < TEST_FRAMES; ++fr) { for (int fr = 0; fr < TEST_FRAMES; ++fr) {
for (int i = 0; i < NUM_DYNAMICS; ++i) { for (int i = 0; i < NUM_DYNAMICS; ++i) {
center = glm::vec3(rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS); center = glm::vec3(rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS);
size = glm::vec3(rand() % MAXSIZE, rand() % MAXSIZE, rand() % MAXSIZE); size = glm::vec3(rand() % MAXSIZE, rand() % MAXSIZE, rand() % MAXSIZE);
aabb.CreateFromCenter(center, size); aabb.FromOriginSize(center, size);
tree.AddDynamicObject(aabb); tree.AddDynamicObject(aabb);
} }
@@ -111,13 +121,13 @@ void TestLoop(TestFunction xTest)
BOOST_AUTO_TEST_CASE(octRegionPerfTestWithDuplicates) BOOST_AUTO_TEST_CASE(octRegionPerfTestWithDuplicates)
{ {
TestLoop<Old::OctTree>(RegionTest<Old::OctTree>); TestLoop<Old::OctTree>(RegionTestOld<Old::OctTree>);
BOOST_CHECK(true); BOOST_CHECK(true);
} }
BOOST_AUTO_TEST_CASE(octRegionPerfTestNoDuplicates) BOOST_AUTO_TEST_CASE(octRegionPerfTestNoDuplicates)
{ {
TestLoop<Octree>(RegionTest<Octree>); TestLoop<Octree<AABB>>(RegionTest<Octree<AABB>>);
BOOST_CHECK(true); BOOST_CHECK(true);
} }
@@ -129,19 +139,19 @@ BOOST_AUTO_TEST_CASE(octBoxPerfTestWithDuplicates)
BOOST_AUTO_TEST_CASE(octBoxPerfTestNoDuplicates) BOOST_AUTO_TEST_CASE(octBoxPerfTestNoDuplicates)
{ {
TestLoop<Octree>(BoxTest<Octree>); TestLoop<Octree<AABB>>(BoxTest<Octree<AABB>>);
BOOST_CHECK(true); BOOST_CHECK(true);
} }
BOOST_AUTO_TEST_CASE(octRayPerfTestWithDuplicates) BOOST_AUTO_TEST_CASE(octRayPerfTestWithDuplicates)
{ {
TestLoop<Old::OctTree>(RayTest<Old::OctTree>); TestLoop<Old::OctTree>(RayTest<Old::OctTree, Old::OctTree::Output>);
BOOST_CHECK(true); BOOST_CHECK(true);
} }
BOOST_AUTO_TEST_CASE(octRayPerfTestNoDuplicates) BOOST_AUTO_TEST_CASE(octRayPerfTestNoDuplicates)
{ {
TestLoop<Octree>(RayTest<Octree>); TestLoop<Octree<AABB>>(RayTest<Octree<AABB>, OctSpace::Output>);
BOOST_CHECK(true); BOOST_CHECK(true);
} }
@@ -153,7 +163,7 @@ BOOST_AUTO_TEST_CASE(octNopPerfTestWithDuplicates)
BOOST_AUTO_TEST_CASE(octNopPerfTestNoDuplicates) BOOST_AUTO_TEST_CASE(octNopPerfTestNoDuplicates)
{ {
TestLoop<Octree>(NopTest<Octree>); TestLoop<Octree<AABB>>(NopTest<Octree<AABB>>);
BOOST_CHECK(true); BOOST_CHECK(true);
} }
-49
View File
@@ -1,49 +0,0 @@
#include <boost/test/unit_test.hpp>
using boost::unit_test_framework::test_suite;
using boost::unit_test_framework::test_case;
#include <stdlib.h>//srand
//#define private public//HACK! Needed for white box testing
//#include "Engine/Core/OctTree.h"
//#include "OldOctTree.h"
//friend class and refactoringIntoNewClass is some extra work and needs to be updated when the original class is updated, and can contain bugs that
//isnt in the original class
//Reflection-inspection seems to be only available for C#
//http://stackoverflow.com/questions/6778496/how-to-do-unit-testing-on-private-members-and-methods-of-c-classes
//http://stackoverflow.com/questions/3676664/unit-testing-of-private-methods
#include "OctTreeTestGameClass.h"
#define private public//HACK! Needed for white box testing
#include <Engine\Core\OctTree.h>
//else we would have to "open up" the octTree class more with get/sets, public methods, etc. which is not good encapsulation-wise
BOOST_AUTO_TEST_SUITE(octTreeTestsA)
BOOST_AUTO_TEST_CASE(octTreeTest)
{
//white box testing
//http://softwaretestingfundamentals.com/differences-between-black-box-testing-and-white-box-testing/
//http://technologyconversations.com/2013/12/11/black-box-vs-white-box-testing/
//simple AABB constructor check
auto minCorner = glm::vec3(0.0f, 0.0f, 0.0f);
auto maxCorner = glm::vec3(1.0f, 1.0f, 1.0f);
auto someAABB = AABB(minCorner, maxCorner);
BOOST_CHECK(someAABB.MinCorner() == minCorner);
BOOST_CHECK(someAABB.MaxCorner() == maxCorner);
BOOST_CHECK(someAABB.Center() == 0.5f * (minCorner + maxCorner));
//simple destructor check in the end, just look for memleaks, then it didnt clear the AABB structure
}
BOOST_AUTO_TEST_CASE(octTreeTest2)
{
//octtree draw etc
Game game(0, nullptr);
while (game.Running()) {
game.Tick();
}
}
BOOST_AUTO_TEST_SUITE_END()
-193
View File
@@ -1,193 +0,0 @@
#include "OctTreeTestGameClass.h"
Game::Game(int argc, char* argv[]) : someOctTree(AABB(-0.5f*worldSize, 0.5f*worldSize), 2)
{
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));
// Create the core event broker
m_EventBroker = new EventBroker();
m_RenderQueueFactory = new RenderQueueFactory();
// Create the renderer
m_Renderer = new Renderer(m_EventBroker);
m_Renderer->SetFullscreen(m_Config->Get<bool>("Video.Fullscreen", false));
m_Renderer->SetVSYNC(m_Config->Get<bool>("Video.VSYNC", false));
m_Renderer->SetResolution(Rectangle(
0,
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)));
// 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);
m_FrameStack->Width = m_Renderer->Resolution().Width;
m_FrameStack->Height = m_Renderer->Resolution().Height;
// Create a TEST WORLD
m_World = new HardcodedTestWorld();
m_SystemPipeline = new SystemPipeline(m_EventBroker);
m_SystemPipeline->AddSystem<PlayerSystem>(0);
m_LastTime = glfwGetTime();
}
Game::~Game()
{
delete m_FrameStack;
delete m_EventBroker;
}
void Game::Tick()
{
double currentTime = glfwGetTime();
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_EventBroker->Swap();
m_InputProxy->Update(dt);
m_EventBroker->Swap();
m_InputProxy->Process();
m_EventBroker->Swap();
#define TEST1
//this draws the octTree and you can set the cube inside it and see what boxes in the tree that it belongs to
#ifdef TEST1
if (!m_UpdatedOnce) {
m_UpdatedOnce = true;
m_World->createTestEntitiesTest1();
}
//add/move the trigger box
auto pos = m_Renderer->Camera()->Forward() + m_Renderer->Camera()->Position();
AABB boxi;
boxi.CreateFromCenter(pos, maxPos - minPos);
frameCounter++;
if (frameCounter > 1) {
m_World->someOctTree.ClearDynamicObjects();
m_World->someOctTree.AddDynamicObject(boxi);
frameCounter = 0;
}
ComponentWrapper transform = m_World->GetComponent(m_World->anotherBoxTransformId, "Transform");
transform["Position"] = boxi.Origin();
//check all children again in the tree if they have a box in them or not, and colormark them if they do
//contentboxarna får man ut - inte childboxarna!
std::vector<int> boxIndex;
boxIndex = m_World->someOctTree.m_Root->childIndicesContainingBox(boxi);
for (auto& oneLinkedObject : m_World->linkOM)
{
ComponentWrapper model = m_World->GetComponent(oneLinkedObject.entId, "Model");
model["Color"] = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f);
if (oneLinkedObject.child->m_DynamicObjIndices.size() != 0) {
model["Color"] = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);
}
//next check if the childIndicesContainingBox method returns the correct boxes
//REQUIRED: childIndicesContainingBox must be public to test this!
for each (auto someBoxIndex in boxIndex)
{
glm::vec3 pos = m_World->someOctTree.m_Root->m_Children[someBoxIndex]->m_Box.Origin();
if (abs(pos.x - oneLinkedObject.posxyz.x) < 0.005f &&
abs(pos.y - oneLinkedObject.posxyz.y) < 0.005f &&
abs(pos.z - oneLinkedObject.posxyz.z) < 0.005f) {
model["Color"] = glm::vec4(0.0f, 1.0f, 0.0f, 1.0f);
}
}
}
m_RenderQueueFactory->Update(m_World);
//wireframe
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
#endif
//this tests AABB vs AABB collision and AABB vs OctTree with AABB in it
#ifdef TEST2
//only add 1 for now...
//grey box
const glm::vec4 redCol = glm::vec4(1, 0.2f, 0, 1);
const glm::vec4 greenCol = glm::vec4(0.1f, 1.0f, 0.25f, 1);
const glm::vec3 boxSize = 0.1f*glm::vec3(1.0f, 1.0f, 1.0f);
AABB aabb;
aabb.CreateFromCenter(glm::vec3(0, 2.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f));
if (m_UpdatedOnce) {
//auto test = someOctTree.childIndicesContainingBox(aabb);
std::vector<AABB> test2;
someOctTree.BoxesInSameRegion(aabb, test2);
}
if (!m_UpdatedOnce) {
m_UpdatedOnce = true;
someOctTree.AddStaticObject(aabb);
//create the "small red box"
m_BoxID = m_World->CreateEntity();
ComponentWrapper transform = m_World->AttachComponent(m_BoxID, "Transform");
transform["Scale"] = boxSize;
ComponentWrapper model = m_World->AttachComponent(m_BoxID, "Model");
model["Resource"] = "Models/Core/UnitBox.obj";
m_World->createTestEntitiesTest2();
}
//red box
AABB redBox;
auto boxPos = m_Renderer->Camera()->Position() + 1.2f*m_Renderer->Camera()->Forward();
redBox.CreateFromCenter(boxPos, boxSize);
ComponentWrapper transform = m_World->GetComponent(m_BoxID, "Transform");
transform["Position"] = boxPos;
ComponentWrapper model = m_World->GetComponent(m_BoxID, "Model");
//this checks AABB vs an AABB in the octTree
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);
model["Color"] = greenCol;
}
else {
model["Color"] = redCol;
}
m_PrevPos = m_Renderer->Camera()->Position();
m_PrevOri = m_Renderer->Camera()->Orientation();
m_RenderQueueFactory->Update(m_World);
#endif
// Iterate through systems and update world!
m_SystemPipeline->Update(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();
glfwPollEvents();
}
-62
View File
@@ -1,62 +0,0 @@
#ifndef Game_h__
#define Game_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"
#include "OctTreeTestHardCodedTestWorld.h"
#include "Collision/Collision.h"
class Game
{
public:
Game(int argc, char* argv[]);
~Game();
bool Running() const { return !glfwWindowShouldClose(m_Renderer->Window()); }
void Tick();
private:
double m_LastTime;
ConfigFile* m_Config = nullptr;
EventBroker* m_EventBroker;
IRenderer* m_Renderer;
InputManager* m_InputManager;
GUI::Frame* m_FrameStack;
HardcodedTestWorld* m_World;
RenderQueueFactory* m_RenderQueueFactory;
InputProxy* m_InputProxy;
SystemPipeline* m_SystemPipeline;
//Test1
int frameCounter = 0;
glm::vec3 minPos = glm::vec3(0.1f, 0.1f, 0.1f);
glm::vec3 maxPos = glm::vec3(0.2f, 0.2f, 0.2f);
//Test2
bool m_UpdatedOnce = false;
unsigned int m_BoxID;
glm::vec3 m_PrevPos;
glm::quat m_PrevOri;
glm::vec3 worldSize = glm::vec3(50, 50, 50);
Octree someOctTree;
};
#endif
-21
View File
@@ -1,21 +0,0 @@
//#define BOOST_TEST_MODULE collTest
#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 "Engine/Collision/Collision.h"
#include "Engine/Core/AABB.h"
#include "Engine/Core/Ray.h"
#include <stdlib.h>//srand
#include "Engine/Core/Octree.h"
//vs memleaks
//#define _CRTDBG_MAP_ALLOC
//#include <stdlib.h>
//#include <crtdbg.h>
//#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__)
//#define new DEBUG_CLIENTBLOCK
BOOST_AUTO_TEST_SUITE(cTest)
BOOST_AUTO_TEST_SUITE_END()
-134
View File
@@ -1,134 +0,0 @@
#include <list>
#include <tuple>
#include <boost/any.hpp>
#include "GLM.h"
#include "Core/World.h"
#include "Core/Util/Any.h"
#include <vector>
//last!
//#include "OldOctTree.h"
#define private public
#include <Engine\Core\OctTree.h>
class HardcodedTestWorld : public World
{
public:
struct LinkOctTreeAndModel {
EntityID entId;
Octree::Child* child;
glm::vec3 posxyz;
LinkOctTreeAndModel(EntityID eId, Octree::Child* ch, glm::vec3 pos)
{
entId = eId;
child = ch;
posxyz = pos;
}
};
EntityID anotherBoxTransformId;
std::vector<LinkOctTreeAndModel> linkOM;
Octree someOctTree;
//constructor
HardcodedTestWorld()
: World()
, someOctTree(AABB(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f)), 2)
{
registerTestComponents();
//createTestEntities();
}
private:
void registerTestComponents()
{
ComponentWrapperFactory f;
f = ComponentWrapperFactory("Test");
f.AddProperty("TestInteger", 1337);
f.AddProperty("TestFloat", 13.37f);
f.AddProperty("TestString", std::string("Carlito"));
RegisterComponent(f);
f = ComponentWrapperFactory("Debug");
f.AddProperty("Name", std::string("Unnamed"));
RegisterComponent(f);
f = ComponentWrapperFactory("Transform");
f.AddProperty("Position", glm::vec3(0.f, 0.f, 0.f));
f.AddProperty("Orientation", glm::quat());
f.AddProperty("Scale", glm::vec3(1.f, 1.f, 1.f));
RegisterComponent(f);
f = ComponentWrapperFactory("Model");
f.AddProperty("Resource", std::string());
f.AddProperty("Color", glm::vec4(1.f, 1.f, 1.f, 1.f));
f.AddProperty("Visible", true);
RegisterComponent(f);
}
void createTestEntitiesTest1()
{
World& world = *this;
EntityID tempId;
//add octTree
{
//copy of mainbox
auto someAABB = AABB(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f));
//draw main box first
AddBoxModel(someAABB.Origin(), someAABB.HalfSize().x, someOctTree.m_Root, tempId);
//add anotherbox in octTree
auto anotherBox = AABB(glm::vec3(0.1f, 0.1f, 0.1f), glm::vec3(0.2f, 0.2f, 0.2f));
//note: have to delete the box in the tree first, since were trying to move the box
someOctTree.AddDynamicObject(anotherBox);
//draw anotherbox and save it in anotherBoxTransformId
AddBoxModel(anotherBox.Origin(), anotherBox.HalfSize().x, someOctTree.m_Root, anotherBoxTransformId);
//draw the octTree
for (size_t j = 0; j < 8; j++)
{
AddBoxModel(someOctTree.m_Root->m_Children[j]->m_Box.Origin(),
someOctTree.m_Root->m_Children[j]->m_Box.HalfSize().x, someOctTree.m_Root->m_Children[j], tempId);
auto someChild = someOctTree.m_Root->m_Children[j];
for (size_t i = 0; i < 8; i++)
{
AddBoxModel(someChild->m_Children[i]->m_Box.Origin(),
someChild->m_Children[i]->m_Box.HalfSize().x, someChild->m_Children[i], tempId);
}
}
}
}//end CreateEnt
void createTestEntitiesTest2()
{
World& world = *this;
EntityID entityCollisionBox = world.CreateEntity();
ComponentWrapper transform = world.AttachComponent(entityCollisionBox, "Transform");
transform["Position"] = glm::vec3(0.f, 2.f, 0.f);
ComponentWrapper model = world.AttachComponent(entityCollisionBox, "Model");
model["Resource"] = "Models/Core/UnitBox.obj";
}
void AddBoxModel(const glm::vec3 &center, const float &halfSize, Octree::Child* child, EntityID &outEntityId) {
World& world = *this;
EntityID entityDummyScene = world.CreateEntity();
outEntityId = entityDummyScene;
ComponentWrapper transform = world.AttachComponent(entityDummyScene, "Transform");
transform["Position"] = center;
transform["Scale"] = glm::vec3(1.0f, 1.0f, 1.0f)*halfSize*2.0f*0.97f;
ComponentWrapper model = world.AttachComponent(entityDummyScene, "Model");
model["Resource"] = "Models/Core/UnitBox.obj";
model["Color"] = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);
if (child->m_DynamicObjIndices.size() != 0)
model["Color"] = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f);
linkOM.emplace_back(entityDummyScene, child, center);
}
};
+2 -2
View File
@@ -100,7 +100,7 @@ void OctTree::Update(float dt, World* world, Camera* cam)
{ {
AABB aabb; AABB aabb;
for (ComponentWrapper& c : *world->GetComponents("Collision")) { for (ComponentWrapper& c : *world->GetComponents("Collision")) {
aabb.CreateFromCenter(c["BoxCenter"], c["BoxSize"]); aabb.FromOriginSize(c["BoxCenter"], c["BoxSize"]);
AddStaticObject(aabb); AddStaticObject(aabb);
} }
const glm::vec4 redCol = glm::vec4(1, 0.2f, 0, 1); const glm::vec4 redCol = glm::vec4(1, 0.2f, 0, 1);
@@ -118,7 +118,7 @@ void OctTree::Update(float dt, World* world, Camera* cam)
AABB box; AABB box;
auto boxPos = cam->Position() + 1.2f*cam->Forward(); auto boxPos = cam->Position() + 1.2f*cam->Forward();
box.CreateFromCenter(boxPos, boxSize); box.FromOriginSize(boxPos, boxSize);
ComponentWrapper transform = world->GetComponent(m_BoxID, "Transform"); ComponentWrapper transform = world->GetComponent(m_BoxID, "Transform");
transform["Position"] = boxPos; transform["Position"] = boxPos;
ComponentWrapper model = world->GetComponent(m_BoxID, "Model"); ComponentWrapper model = world->GetComponent(m_BoxID, "Model");
+4 -6
View File
@@ -7,7 +7,7 @@
#include "Core/ResourceManager.h" #include "Core/ResourceManager.h"
#include "Core/ConfigFile.h" #include "Core/ConfigFile.h"
#include "Rendering/Renderer.h" #include "Rendering/Renderer.h"
#include "Engine\Rendering\Texture.h" #include "Engine/Rendering/Texture.h"
BOOST_AUTO_TEST_SUITE(resourceManagerTests) BOOST_AUTO_TEST_SUITE(resourceManagerTests)
@@ -19,16 +19,14 @@ BOOST_AUTO_TEST_CASE(resourceManagerTest)
ResourceManager::RegisterType<ConfigFile>("ConfigFile"); ResourceManager::RegisterType<ConfigFile>("ConfigFile");
BOOST_CHECK(!ResourceManager::IsResourceLoaded("ConfigFile", "Config.ini")); BOOST_CHECK(!ResourceManager::IsResourceLoaded("ConfigFile", "Config.ini"));
auto m_Config = ResourceManager::Load<ConfigFile>("Config.ini");
BOOST_CHECK_NO_THROW(ResourceManager::Load<ConfigFile>("Config.ini"));
BOOST_CHECK(ResourceManager::IsResourceLoaded("ConfigFile", "Config.ini")); BOOST_CHECK(ResourceManager::IsResourceLoaded("ConfigFile", "Config.ini"));
ResourceManager::Release("ConfigFile", "Config.ini"); ResourceManager::Release("ConfigFile", "Config.ini");
BOOST_CHECK(!ResourceManager::IsResourceLoaded("ConfigFile", "Config.ini")); BOOST_CHECK(!ResourceManager::IsResourceLoaded("ConfigFile", "Config.ini"));
//configfile without register //configfile without register
//check so output says "EE failed to load: type not registered..." BOOST_CHECK_THROW(ResourceManager::Load<Model>("Models/Core/ScreenQuad.obj"),Resource::FailedLoadingException);
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 //there is no error feedback to check if you try to release the wrong resources - hence that cant be tested either
} }