Add Collide System

- Fix AssetRef unload leak
This commit is contained in:
Thraix
2023-06-05 21:52:32 +02:00
parent 3ec9bcd152
commit 76bda0ace4
16 changed files with 280 additions and 137 deletions
+3 -3
View File
@@ -180,7 +180,6 @@
<ClCompile Include="src\copium\core\Scene.cpp" />
<ClCompile Include="src\copium\core\Vulkan.cpp" />
<ClCompile Include="src\copium\core\Window.cpp" />
<ClCompile Include="src\copium\ecs\ComponentListener.cpp" />
<ClCompile Include="src\copium\ecs\ComponentPoolBase.cpp" />
<ClCompile Include="src\copium\ecs\ECSManager.cpp" />
<ClCompile Include="src\copium\ecs\Entity.cpp" />
@@ -214,7 +213,6 @@
<ClCompile Include="src\copium\pipeline\DescriptorSet.cpp" />
<ClCompile Include="src\copium\sampler\Font.cpp" />
<ClCompile Include="src\copium\util\BoundingBox.cpp" />
<ClCompile Include="src\copium\util\RefCounter.cpp" />
<ClCompile Include="src\copium\util\RuntimeException.cpp" />
<ClCompile Include="src\copium\util\FileSystem.cpp" />
<ClCompile Include="src\copium\buffer\Framebuffer.cpp" />
@@ -258,6 +256,7 @@
<ClInclude Include="src\copium\ecs\ECSManager.h" />
<ClInclude Include="src\copium\ecs\Entity.h" />
<ClInclude Include="src\copium\ecs\EntitySet.h" />
<ClInclude Include="src\copium\example\PickupSystem.h" />
<ClInclude Include="src\copium\ecs\Signal.h" />
<ClInclude Include="src\copium\ecs\System.h" />
<ClInclude Include="src\copium\ecs\SystemBase.h" />
@@ -290,6 +289,7 @@
<ClInclude Include="src\copium\example\PlayerControllerSystem.h" />
<ClInclude Include="src\copium\example\RenderSystem.h" />
<ClInclude Include="src\copium\example\MouseFollowSystem.h" />
<ClInclude Include="src\copium\example\ColliderSystem.h" />
<ClInclude Include="src\copium\mesh\Mesh.h" />
<ClInclude Include="src\copium\pipeline\ShaderBinding.h" />
<ClInclude Include="src\copium\renderer\Batch.h" />
@@ -303,12 +303,12 @@
<ClInclude Include="src\copium\sampler\Font.h" />
<ClInclude Include="src\copium\sampler\Glyph.h" />
<ClInclude Include="src\copium\util\BoundingBox.h" />
<ClInclude Include="src\copium\example\CollideSignal.h" />
<ClInclude Include="src\copium\util\Common.h" />
<ClInclude Include="src\copium\core\DebugMessenger.h" />
<ClInclude Include="src\copium\pipeline\DescriptorSet.h" />
<ClInclude Include="src\copium\pipeline\DescriptorPool.h" />
<ClInclude Include="src\copium\util\Enum.h" />
<ClInclude Include="src\copium\util\RefCounter.h" />
<ClInclude Include="src\copium\util\RuntimeException.h" />
<ClInclude Include="src\copium\util\FileSystem.h" />
<ClInclude Include="src\copium\buffer\Framebuffer.h" />
+9 -9
View File
@@ -219,12 +219,6 @@
<ClCompile Include="src\copium\event\Input.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\copium\util\RefCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\copium\ecs\ComponentListener.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\copium\sampler\DepthAttachment.h">
@@ -497,14 +491,20 @@
<ClInclude Include="src\copium\example\HealthChangeSystem.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\copium\util\RefCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\copium\ecs\ComponentListener.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\copium\example\HealthComponentListener.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\copium\example\ColliderSystem.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\copium\example\CollideSignal.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\copium\example\PickupSystem.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
+9 -12
View File
@@ -4,21 +4,18 @@
namespace Copium
{
AssetRef::AssetRef(AssetHandle handle)
: handle{handle}
{}
struct AssetHandleUnloader {
void operator()(AssetHandle* handle) {
AssetManager::UnloadAsset(*handle);
}
};
AssetRef::~AssetRef()
{
if (refCounter.LastRef())
{
AssetManager::UnloadAsset(handle);
}
}
AssetRef::AssetRef(AssetHandle handle)
: handle{std::shared_ptr<AssetHandle>(new AssetHandle{handle}, AssetHandleUnloader{})}
{}
AssetRef::operator AssetHandle() const
{
return handle;
return *handle;
}
}
+1 -4
View File
@@ -1,19 +1,16 @@
#pragma once
#include "copium/asset/AssetMeta.h"
#include "copium/util/RefCounter.h"
namespace Copium
{
class AssetRef
{
private:
AssetHandle handle;
RefCounter refCounter;
std::shared_ptr<AssetHandle> handle;
public:
AssetRef(AssetHandle handle);
~AssetRef();
operator AssetHandle() const;
};
+41 -1
View File
@@ -15,9 +15,11 @@
#include "copium/example/HealthComponentListener.h"
#include "copium/example/HealthDisplaySystem.h"
#include "copium/example/MouseFollowSystem.h"
#include "copium/example/ColliderSystem.h"
#include "copium/example/PhysicsSystem.h"
#include "copium/example/PlayerControllerSystem.h"
#include "copium/example/RenderSystem.h"
#include "copium/example/PickupSystem.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
@@ -33,6 +35,8 @@ namespace Copium
ecs->AddSystem<PlayerControllerSystem>();
ecs->AddSystem<PhysicsSystem>();
ecs->AddSystem<ColliderSystem>();
ecs->AddSystem<PickupSystem>();
ecs->AddSystem<HealthChangeSystem>();
ecs->AddSystem<HealthDisplaySystem>();
ecs->AddSystem<CameraFollowPlayerSystem>();
@@ -44,12 +48,44 @@ namespace Copium
// TODO: Load from scene file
for (int y = 0; y < 10; y++)
{
{
Entity entity = Entity::Create(ecs.get());
entity.AddComponent<TransformC>(glm::vec2{-10.0f + 0.4f, -11.0f + y * 1.6 + 0.4f}, glm::vec2{0.8f, 0.8f});
entity.AddComponent<TextureC>(AssetRef{AssetManager::LoadAsset("fox.meta")}, glm::vec2{0.0f, 0.0f}, glm::vec2{1.0f, 1.0f});
entity.AddComponent<StaticColliderC>(true);
}
{
Entity entity = Entity::Create(ecs.get());
entity.AddComponent<TransformC>(glm::vec2{10.0f - 0.4f, -10.0f + y * 1.6 + 0.4f}, glm::vec2{0.8f, 0.8f});
entity.AddComponent<TextureC>(AssetRef{AssetManager::LoadAsset("fox.meta")}, glm::vec2{0.0f, 0.0f}, glm::vec2{1.0f, 1.0f});
entity.AddComponent<StaticColliderC>(true);
}
}
for (int x = 0; x < 10; x++)
{
{
Entity entity = Entity::Create(ecs.get());
entity.AddComponent<TransformC>(glm::vec2{-11.0f + x * 1.6 + 0.4f, -10.0f + 0.4f, }, glm::vec2{0.8f, 0.8f});
entity.AddComponent<TextureC>(AssetRef{AssetManager::LoadAsset("fox.meta")}, glm::vec2{0.0f, 0.0f}, glm::vec2{1.0f, 1.0f});
entity.AddComponent<StaticColliderC>(true);
}
{
Entity entity = Entity::Create(ecs.get());
entity.AddComponent<TransformC>(glm::vec2{-11.0f + x * 1.6 + 0.4f, 10.0f - 0.4f, }, glm::vec2{0.8f, 0.8f});
entity.AddComponent<TextureC>(AssetRef{AssetManager::LoadAsset("fox.meta")}, glm::vec2{0.0f, 0.0f}, glm::vec2{1.0f, 1.0f});
entity.AddComponent<StaticColliderC>(true);
}
}
for (int y = 0; y < 10; y++)
{
for (int x = 0; x < 10; x++)
{
Entity entity = Entity::Create(ecs.get());
entity.AddComponent<TransformC>(glm::vec2{-10.0f + x * 1.6f + 0.4f, -10.0f + y * 1.6 + 0.4f}, glm::vec2{0.8f, 0.8f});
entity.AddComponent<ColorC>(glm::vec3{x * 0.1f, y * 0.1f, 1.0f});
entity.AddComponent<StaticColliderC>(false);
entity.AddComponent<PickupC>();
}
}
@@ -57,10 +93,13 @@ namespace Copium
Entity entityFox = Entity::Create(ecs.get());
entityFox.AddComponent<TransformC>(glm::vec2{-0.9f, -0.4f}, glm::vec2{0.8f, 0.8f});
entityFox.AddComponent<TextureC>(AssetRef{AssetManager::LoadAsset("fox.meta")}, glm::vec2{0.0f, 0.0f}, glm::vec2{1.0f, 1.0f});
entityFox.AddComponent<StaticColliderC>(true);
Entity entityFontAtlas = Entity::Create(ecs.get());
entityFontAtlas.AddComponent<TransformC>(glm::vec2{0.1f, -0.4f}, glm::vec2{0.8, 0.8});
entityFontAtlas.AddComponent<TextureC>(AssetRef{AssetManager::LoadAsset("font.meta")}, glm::vec2{0.0f, 0.0f}, glm::vec2{1.0f, 1.0f});
entityFontAtlas.AddComponent<StaticColliderC>(false);
entityFontAtlas.AddComponent<PickupC>();
Entity entityMouse = Entity::Create(ecs.get());
entityMouse.AddComponent<TransformC>(glm::vec2(0.1), glm::vec2{0.2});
@@ -80,8 +119,9 @@ namespace Copium
entityPlayer.AddComponent<PlayerC>(entityCamera);
entityPlayer.AddComponent<HealthC>(10, 10);
entityPlayer.AddComponent<PhysicsC>(0.1f, glm::vec2{0.0f, 0.0f}, glm::vec2{0.0f, 0.0f});
entityPlayer.AddComponent<TransformC>(glm::vec2{0.0f}, glm::vec2{1.0f});
entityPlayer.AddComponent<TransformC>(glm::vec2{0.0f, 2.0f}, glm::vec2{1.0f});
entityPlayer.AddComponent<TextureC>(AssetRef{AssetManager::LoadAsset("fox2.meta")}, glm::vec2{0.0f, 0.0f}, glm::vec2{1.0f, 1.0f});
entityPlayer.AddComponent<DynamicColliderC>(false, glm::vec2{0.0f});
}
void Scene::Update()
+12
View File
@@ -1,5 +1,17 @@
#pragma once
#define CP_SIGNAL_DECLERATION_DEFINITION() \
static int GetIdStatic() \
{ \
static int id = GetAllocatedId(); \
return id; \
} \
\
int GetId() const \
{ \
return GetIdStatic(); \
}
#define CP_SIGNAL_DECLERATION(SignalClass) \
static int GetIdStatic(); \
int GetId() const override
@@ -0,0 +1,30 @@
#pragma once
#include "copium/ecs/Signal.h"
#include "copium/ecs/Entity.h"
namespace Copium
{
class CollideSignal : public Signal
{
private:
Entity first;
Entity second;
public:
CollideSignal(Entity first, Entity second)
: first{first}, second{second}
{}
Entity GetFirst() const
{
return first;
}
Entity GetSecond() const
{
return second;
}
CP_SIGNAL_DECLERATION_DEFINITION();
};
}
@@ -0,0 +1,102 @@
#pragma once
#include "copium/ecs/System.h"
#include "copium/example/Components.h"
#include "copium/example/CollideSignal.h"
#include <queue>
namespace Copium
{
class ColliderSystem : public System<DynamicColliderC, TransformC>
{
std::queue<CollideSignal> signals;
bool Overlap(TransformC& firstTransform, TransformC& secondTransform)
{
if (firstTransform.position.x >= secondTransform.position.x + secondTransform.size.x)
return false;
if (firstTransform.position.y >= secondTransform.position.y + secondTransform.size.y)
return false;
if (firstTransform.position.x + firstTransform.size.x <= secondTransform.position.x)
return false;
if (firstTransform.position.y + firstTransform.size.y <= secondTransform.position.y)
return false;
return true;
}
void CollideCheckDynamic(Entity firstEntity, TransformC& firstTransform, Entity secondEntity, TransformC& secondTransform)
{
if (firstEntity.GetId() >= secondEntity.GetId())
return;
if (!Overlap(firstTransform, secondTransform))
return;
signals.emplace(firstEntity, secondEntity);
}
void CollideCheckStatic(Entity firstEntity, DynamicColliderC& dynamicCollider, TransformC& firstTransform, Entity secondEntity, StaticColliderC& secondStaticCollider, TransformC& secondTransform)
{
if (!Overlap(firstTransform, secondTransform))
return;
signals.emplace(firstEntity, secondEntity);
if (!secondStaticCollider.resolveCollision)
return;
if (firstTransform.position.x != dynamicCollider.oldPosition.x)
{
TransformC transform = firstTransform;
transform.position.y = dynamicCollider.oldPosition.y;
if (Overlap(transform, secondTransform))
{
if (dynamicCollider.oldPosition.x < firstTransform.position.x)
firstTransform.position.x = secondTransform.position.x - firstTransform.size.x;
else
firstTransform.position.x = secondTransform.position.x + secondTransform.size.x;
if (firstEntity.HasComponent<PhysicsC>())
firstEntity.GetComponent<PhysicsC>().velocity.x = 0;
}
}
if (firstTransform.position.y != dynamicCollider.oldPosition.y)
{
TransformC transform = firstTransform;
transform.position.x = dynamicCollider.oldPosition.x;
if (Overlap(transform, secondTransform))
{
if (dynamicCollider.oldPosition.y < firstTransform.position.y)
firstTransform.position.y = secondTransform.position.y - firstTransform.size.y;
else
firstTransform.position.y = secondTransform.position.y + secondTransform.size.y;
if (firstEntity.HasComponent<PhysicsC>())
firstEntity.GetComponent<PhysicsC>().velocity.y = 0;
}
}
}
void RunEntity(Entity entity, DynamicColliderC& dynamicCollider, TransformC& transform) override
{
manager->Each<DynamicColliderC, TransformC>(
[&](EntityId otherEntity, DynamicColliderC& otherDynamicCollider, TransformC& otherTransform)
{
CollideCheckDynamic(entity, transform, Entity{manager, otherEntity}, otherTransform);
}
);
manager->Each<StaticColliderC, TransformC>(
[&](EntityId otherEntity, StaticColliderC& otherStaticCollider, TransformC& otherTransform)
{
CollideCheckStatic(entity, dynamicCollider, transform, Entity{manager, otherEntity}, otherStaticCollider, otherTransform);
}
);
dynamicCollider.oldPosition = transform.position;
while (!signals.empty())
{
manager->UpdateSystems(signals.front());
signals.pop();
}
}
};
}
@@ -56,6 +56,7 @@ namespace Copium
struct PlayerC
{
Entity camera;
Timer jumpTimer;
};
struct HealthC
@@ -66,4 +67,20 @@ namespace Copium
Entity background;
Entity foreground;
};
struct StaticColliderC
{
bool resolveCollision;
};
struct DynamicColliderC
{
bool resolveCollision;
glm::vec2 oldPosition;
};
struct PickupC
{
};
}
@@ -31,5 +31,4 @@ namespace Copium
health.foreground.Destroy();
}
};
}
@@ -10,9 +10,10 @@ namespace Copium
public:
void RunEntity(Entity entity, PhysicsC& physics, TransformC& transform) override
{
physics.force.y -= 4; // Apply gravity
float timespan = 1 / 165.0f; // My main monitor refresh rate, should be based on the frame rate
physics.velocity += physics.force / physics.mass * timespan;
physics.velocity *= 0.7; // friction
physics.velocity.x *= 0.7; // friction
transform.position += physics.velocity * timespan;
physics.force = glm::vec2{0.0f};
}
@@ -0,0 +1,37 @@
#pragma once
#include "copium/ecs/System.h"
#include "copium/example/Components.h"
#include "copium/example/CollideSignal.h"
namespace Copium
{
class PickupSystem : public SystemBase
{
void Run() override {}
void Run(const Signal& signal) override
{
if (signal.GetId() == CollideSignal::GetIdStatic())
{
const CollideSignal& collideSignal = static_cast<const CollideSignal&>(signal);
if (collideSignal.GetFirst().HasComponent<PickupC>())
{
if (collideSignal.GetSecond().HasComponent<PlayerC>())
{
collideSignal.GetFirst().Destroy();
}
}
else if (collideSignal.GetSecond().HasComponent<PickupC>())
{
if (collideSignal.GetFirst().HasComponent<PlayerC>())
{
collideSignal.GetSecond().Destroy();
collideSignal.GetFirst().GetComponent<HealthC>().current++;
collideSignal.GetSecond().Destroy();
}
}
}
}
};
}
@@ -11,18 +11,25 @@ namespace Copium
public:
void RunEntity(Entity entity, PlayerC& player, PhysicsC& physics) override
{
float magnitude = 200.0f;
glm::vec2 force{0.0f};
if (Input::IsKeyDown(CP_KEY_W)) force.y += 1.0f;
if (Input::IsKeyDown(CP_KEY_S)) force.y -= 1.0f;
if (Input::IsKeyDown(CP_KEY_A)) force.x -= 1.0f;
if (Input::IsKeyDown(CP_KEY_D)) force.x += 1.0f;
if (force.x != 0 || force.y != 0)
const float MAX_JUMP_TIME = 0.2;
float force = 0.0f;
if (Input::IsKeyPressed(CP_KEY_SPACE))
{
force = glm::normalize(force);
physics.force += force * magnitude;
player.jumpTimer.Start();
physics.velocity.y += 15;
}
else if (!Input::IsKeyDown(CP_KEY_SPACE))
{
if (physics.velocity.y > 0)
{
physics.force.y -= 12;
}
}
if (Input::IsKeyDown(CP_KEY_A)) force -= 1.0f;
if (Input::IsKeyDown(CP_KEY_D)) force += 1.0f;
float magnitude = 75.0f;
physics.force.x += force * magnitude;
if (Input::IsKeyPressed(CP_KEY_H))
{
@@ -1,72 +0,0 @@
#include "copium/util/RefCounter.h"
#include "copium/util/Common.h"
namespace Copium
{
RefCounter::RefCounter()
: refCounter{new int{1}}
{}
RefCounter::~RefCounter()
{
if (Valid())
{
(*refCounter)--;
if (*refCounter == 0)
{
delete refCounter;
refCounter = nullptr;
}
}
}
RefCounter::RefCounter(RefCounter&& rhs)
: refCounter(rhs.refCounter)
{
CP_ASSERT(Valid(), "RefCounter : Moving a deleted RefCounter");
rhs.refCounter = nullptr;
}
RefCounter::RefCounter(const RefCounter& rhs)
: refCounter{rhs.refCounter}
{
CP_ASSERT(Valid(), "RefCounter : Copying a deleted RefCounter");
(*refCounter)++;
}
RefCounter& RefCounter::operator=(RefCounter&& rhs)
{
CP_ASSERT(Valid(), "operator= : Moving a deleted RefCounter");
refCounter = rhs.refCounter;
rhs.refCounter = nullptr;
return *this;
}
RefCounter& RefCounter::operator=(const RefCounter& rhs)
{
CP_ASSERT(Valid(), "operator= : Copying a deleted RefCounter");
refCounter = rhs.refCounter;
(*refCounter)++;
return *this;
}
bool RefCounter::Valid() const
{
return refCounter != nullptr;
}
bool RefCounter::LastRef() const
{
return Valid() && *refCounter == 1;
}
int RefCounter::Counter() const
{
CP_ASSERT(Valid(), "Counter : referencing a deleted RefCounter");
return *refCounter;
}
}
-24
View File
@@ -1,24 +0,0 @@
#pragma once
namespace Copium
{
class RefCounter final
{
private:
int* refCounter;
public:
RefCounter();
~RefCounter();
RefCounter(RefCounter&& rhs);
RefCounter(const RefCounter& rhs);
RefCounter& operator=(RefCounter&& rhs);
RefCounter& operator=(const RefCounter& rhs);
bool Valid() const;
bool LastRef() const;
int Counter() const;
};
}