From 76bda0ace4d7e7fa7deb377a0361a4700a9ebf59 Mon Sep 17 00:00:00 2001 From: Thraix Date: Mon, 5 Jun 2023 21:52:32 +0200 Subject: [PATCH] Add Collide System - Fix AssetRef unload leak --- CopiumEngine/CopiumEngine.vcxproj | 6 +- CopiumEngine/CopiumEngine.vcxproj.filters | 18 ++-- CopiumEngine/src/copium/asset/AssetRef.cpp | 21 ++-- CopiumEngine/src/copium/asset/AssetRef.h | 5 +- CopiumEngine/src/copium/core/Scene.cpp | 42 +++++++- .../src/copium/ecs/ComponentListener.cpp | 0 CopiumEngine/src/copium/ecs/Signal.h | 12 +++ .../src/copium/example/CollideSignal.h | 30 ++++++ .../src/copium/example/ColliderSystem.h | 102 ++++++++++++++++++ CopiumEngine/src/copium/example/Components.h | 17 +++ .../copium/example/HealthComponentListener.h | 1 - .../src/copium/example/PhysicsSystem.h | 3 +- .../src/copium/example/PickupSystem.h | 37 +++++++ .../copium/example/PlayerControllerSystem.h | 27 +++-- CopiumEngine/src/copium/util/RefCounter.cpp | 72 ------------- CopiumEngine/src/copium/util/RefCounter.h | 24 ----- 16 files changed, 280 insertions(+), 137 deletions(-) delete mode 100644 CopiumEngine/src/copium/ecs/ComponentListener.cpp create mode 100644 CopiumEngine/src/copium/example/CollideSignal.h create mode 100644 CopiumEngine/src/copium/example/ColliderSystem.h create mode 100644 CopiumEngine/src/copium/example/PickupSystem.h delete mode 100644 CopiumEngine/src/copium/util/RefCounter.cpp delete mode 100644 CopiumEngine/src/copium/util/RefCounter.h diff --git a/CopiumEngine/CopiumEngine.vcxproj b/CopiumEngine/CopiumEngine.vcxproj index 08bf85e..8f37933 100644 --- a/CopiumEngine/CopiumEngine.vcxproj +++ b/CopiumEngine/CopiumEngine.vcxproj @@ -180,7 +180,6 @@ - @@ -214,7 +213,6 @@ - @@ -258,6 +256,7 @@ + @@ -290,6 +289,7 @@ + @@ -303,12 +303,12 @@ + - diff --git a/CopiumEngine/CopiumEngine.vcxproj.filters b/CopiumEngine/CopiumEngine.vcxproj.filters index 76a1787..af482b7 100644 --- a/CopiumEngine/CopiumEngine.vcxproj.filters +++ b/CopiumEngine/CopiumEngine.vcxproj.filters @@ -219,12 +219,6 @@ Source Files - - Source Files - - - Source Files - @@ -497,14 +491,20 @@ Header Files - - Header Files - Header Files Header Files + + Header Files + + + Header Files + + + Header Files + \ No newline at end of file diff --git a/CopiumEngine/src/copium/asset/AssetRef.cpp b/CopiumEngine/src/copium/asset/AssetRef.cpp index 8fea83a..897e58f 100644 --- a/CopiumEngine/src/copium/asset/AssetRef.cpp +++ b/CopiumEngine/src/copium/asset/AssetRef.cpp @@ -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(new AssetHandle{handle}, AssetHandleUnloader{})} + {} AssetRef::operator AssetHandle() const { - return handle; - + return *handle; } } diff --git a/CopiumEngine/src/copium/asset/AssetRef.h b/CopiumEngine/src/copium/asset/AssetRef.h index 3cf4dea..699fbc6 100644 --- a/CopiumEngine/src/copium/asset/AssetRef.h +++ b/CopiumEngine/src/copium/asset/AssetRef.h @@ -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 handle; public: AssetRef(AssetHandle handle); - ~AssetRef(); operator AssetHandle() const; }; diff --git a/CopiumEngine/src/copium/core/Scene.cpp b/CopiumEngine/src/copium/core/Scene.cpp index 33a87c4..52a7378 100644 --- a/CopiumEngine/src/copium/core/Scene.cpp +++ b/CopiumEngine/src/copium/core/Scene.cpp @@ -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 #include @@ -33,6 +35,8 @@ namespace Copium ecs->AddSystem(); ecs->AddSystem(); + ecs->AddSystem(); + ecs->AddSystem(); ecs->AddSystem(); ecs->AddSystem(); ecs->AddSystem(); @@ -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(glm::vec2{-10.0f + 0.4f, -11.0f + y * 1.6 + 0.4f}, glm::vec2{0.8f, 0.8f}); + entity.AddComponent(AssetRef{AssetManager::LoadAsset("fox.meta")}, glm::vec2{0.0f, 0.0f}, glm::vec2{1.0f, 1.0f}); + entity.AddComponent(true); + } + { + Entity entity = Entity::Create(ecs.get()); + entity.AddComponent(glm::vec2{10.0f - 0.4f, -10.0f + y * 1.6 + 0.4f}, glm::vec2{0.8f, 0.8f}); + entity.AddComponent(AssetRef{AssetManager::LoadAsset("fox.meta")}, glm::vec2{0.0f, 0.0f}, glm::vec2{1.0f, 1.0f}); + entity.AddComponent(true); + } + } + for (int x = 0; x < 10; x++) + { + { + Entity entity = Entity::Create(ecs.get()); + entity.AddComponent(glm::vec2{-11.0f + x * 1.6 + 0.4f, -10.0f + 0.4f, }, glm::vec2{0.8f, 0.8f}); + entity.AddComponent(AssetRef{AssetManager::LoadAsset("fox.meta")}, glm::vec2{0.0f, 0.0f}, glm::vec2{1.0f, 1.0f}); + entity.AddComponent(true); + } + { + Entity entity = Entity::Create(ecs.get()); + entity.AddComponent(glm::vec2{-11.0f + x * 1.6 + 0.4f, 10.0f - 0.4f, }, glm::vec2{0.8f, 0.8f}); + entity.AddComponent(AssetRef{AssetManager::LoadAsset("fox.meta")}, glm::vec2{0.0f, 0.0f}, glm::vec2{1.0f, 1.0f}); + entity.AddComponent(true); + } + } + for (int y = 0; y < 10; y++) { for (int x = 0; x < 10; x++) { Entity entity = Entity::Create(ecs.get()); entity.AddComponent(glm::vec2{-10.0f + x * 1.6f + 0.4f, -10.0f + y * 1.6 + 0.4f}, glm::vec2{0.8f, 0.8f}); entity.AddComponent(glm::vec3{x * 0.1f, y * 0.1f, 1.0f}); + entity.AddComponent(false); + entity.AddComponent(); } } @@ -57,10 +93,13 @@ namespace Copium Entity entityFox = Entity::Create(ecs.get()); entityFox.AddComponent(glm::vec2{-0.9f, -0.4f}, glm::vec2{0.8f, 0.8f}); entityFox.AddComponent(AssetRef{AssetManager::LoadAsset("fox.meta")}, glm::vec2{0.0f, 0.0f}, glm::vec2{1.0f, 1.0f}); + entityFox.AddComponent(true); Entity entityFontAtlas = Entity::Create(ecs.get()); entityFontAtlas.AddComponent(glm::vec2{0.1f, -0.4f}, glm::vec2{0.8, 0.8}); entityFontAtlas.AddComponent(AssetRef{AssetManager::LoadAsset("font.meta")}, glm::vec2{0.0f, 0.0f}, glm::vec2{1.0f, 1.0f}); + entityFontAtlas.AddComponent(false); + entityFontAtlas.AddComponent(); Entity entityMouse = Entity::Create(ecs.get()); entityMouse.AddComponent(glm::vec2(0.1), glm::vec2{0.2}); @@ -80,8 +119,9 @@ namespace Copium entityPlayer.AddComponent(entityCamera); entityPlayer.AddComponent(10, 10); entityPlayer.AddComponent(0.1f, glm::vec2{0.0f, 0.0f}, glm::vec2{0.0f, 0.0f}); - entityPlayer.AddComponent(glm::vec2{0.0f}, glm::vec2{1.0f}); + entityPlayer.AddComponent(glm::vec2{0.0f, 2.0f}, glm::vec2{1.0f}); entityPlayer.AddComponent(AssetRef{AssetManager::LoadAsset("fox2.meta")}, glm::vec2{0.0f, 0.0f}, glm::vec2{1.0f, 1.0f}); + entityPlayer.AddComponent(false, glm::vec2{0.0f}); } void Scene::Update() diff --git a/CopiumEngine/src/copium/ecs/ComponentListener.cpp b/CopiumEngine/src/copium/ecs/ComponentListener.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/CopiumEngine/src/copium/ecs/Signal.h b/CopiumEngine/src/copium/ecs/Signal.h index 389661f..be13820 100644 --- a/CopiumEngine/src/copium/ecs/Signal.h +++ b/CopiumEngine/src/copium/ecs/Signal.h @@ -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 diff --git a/CopiumEngine/src/copium/example/CollideSignal.h b/CopiumEngine/src/copium/example/CollideSignal.h new file mode 100644 index 0000000..262cf7e --- /dev/null +++ b/CopiumEngine/src/copium/example/CollideSignal.h @@ -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(); + }; +} diff --git a/CopiumEngine/src/copium/example/ColliderSystem.h b/CopiumEngine/src/copium/example/ColliderSystem.h new file mode 100644 index 0000000..008410c --- /dev/null +++ b/CopiumEngine/src/copium/example/ColliderSystem.h @@ -0,0 +1,102 @@ +#pragma once + +#include "copium/ecs/System.h" +#include "copium/example/Components.h" +#include "copium/example/CollideSignal.h" + +#include + +namespace Copium +{ + class ColliderSystem : public System + { + std::queue 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()) + firstEntity.GetComponent().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()) + firstEntity.GetComponent().velocity.y = 0; + } + } + } + + void RunEntity(Entity entity, DynamicColliderC& dynamicCollider, TransformC& transform) override + { + manager->Each( + [&](EntityId otherEntity, DynamicColliderC& otherDynamicCollider, TransformC& otherTransform) + { + CollideCheckDynamic(entity, transform, Entity{manager, otherEntity}, otherTransform); + } + ); + manager->Each( + [&](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(); + } + } + }; +} \ No newline at end of file diff --git a/CopiumEngine/src/copium/example/Components.h b/CopiumEngine/src/copium/example/Components.h index a7dab89..339ae33 100644 --- a/CopiumEngine/src/copium/example/Components.h +++ b/CopiumEngine/src/copium/example/Components.h @@ -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 + { + + }; } \ No newline at end of file diff --git a/CopiumEngine/src/copium/example/HealthComponentListener.h b/CopiumEngine/src/copium/example/HealthComponentListener.h index cd64a12..112718d 100644 --- a/CopiumEngine/src/copium/example/HealthComponentListener.h +++ b/CopiumEngine/src/copium/example/HealthComponentListener.h @@ -31,5 +31,4 @@ namespace Copium health.foreground.Destroy(); } }; - } diff --git a/CopiumEngine/src/copium/example/PhysicsSystem.h b/CopiumEngine/src/copium/example/PhysicsSystem.h index f2f8a3f..19dee26 100644 --- a/CopiumEngine/src/copium/example/PhysicsSystem.h +++ b/CopiumEngine/src/copium/example/PhysicsSystem.h @@ -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}; } diff --git a/CopiumEngine/src/copium/example/PickupSystem.h b/CopiumEngine/src/copium/example/PickupSystem.h new file mode 100644 index 0000000..d50fab5 --- /dev/null +++ b/CopiumEngine/src/copium/example/PickupSystem.h @@ -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(signal); + if (collideSignal.GetFirst().HasComponent()) + { + if (collideSignal.GetSecond().HasComponent()) + { + collideSignal.GetFirst().Destroy(); + } + } + else if (collideSignal.GetSecond().HasComponent()) + { + if (collideSignal.GetFirst().HasComponent()) + { + collideSignal.GetSecond().Destroy(); + collideSignal.GetFirst().GetComponent().current++; + collideSignal.GetSecond().Destroy(); + } + } + } + } + }; +} diff --git a/CopiumEngine/src/copium/example/PlayerControllerSystem.h b/CopiumEngine/src/copium/example/PlayerControllerSystem.h index 4ff3235..5268688 100644 --- a/CopiumEngine/src/copium/example/PlayerControllerSystem.h +++ b/CopiumEngine/src/copium/example/PlayerControllerSystem.h @@ -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)) { diff --git a/CopiumEngine/src/copium/util/RefCounter.cpp b/CopiumEngine/src/copium/util/RefCounter.cpp deleted file mode 100644 index 9229303..0000000 --- a/CopiumEngine/src/copium/util/RefCounter.cpp +++ /dev/null @@ -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; - } -} diff --git a/CopiumEngine/src/copium/util/RefCounter.h b/CopiumEngine/src/copium/util/RefCounter.h deleted file mode 100644 index f286c25..0000000 --- a/CopiumEngine/src/copium/util/RefCounter.h +++ /dev/null @@ -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; - }; -}