diff --git a/FluffyEngine/CollidersHandler.cpp b/FluffyEngine/CollidersHandler.cpp new file mode 100644 index 0000000..6e7c3a1 --- /dev/null +++ b/FluffyEngine/CollidersHandler.cpp @@ -0,0 +1,57 @@ +#include "CollidersHandler.h" +#include "RectColliderComponent.h" +#include +#include + +namespace Fluffy +{ + void CollidersHandler::RegisterCollisionLayers(const std::vector& layerNames, const std::unordered_map> layersInteractions) + { + m_CollisionLayers.clear(); + m_LayerInteractions.clear(); + + for (const std::string& layerName : layerNames) + { + if (m_CollisionLayers.size() == 32) + throw std::out_of_range("Can't hold this many layers! (unsigned int has only 32 bits to work with)"); + + // associate each layer name with a bit position + m_CollisionLayers.emplace(layerName, 1 << (unsigned int)m_CollisionLayers.size()); + } + + for (const auto& layerInteractions : layersInteractions) + { + unsigned int interactionMask{ 0 }; + + for (const std::string& layerName : layerInteractions.second) + { + // add all the layer bits together to create the bitfield/mask + interactionMask |= m_CollisionLayers.at(layerName); + } + + m_LayerInteractions.emplace(layerInteractions.first, interactionMask); + } + } + + void CollidersHandler::UnregisterColliderComponent(class RectColliderComponent* pCollider) + { + const auto& componentIt{ m_ColliderComponents.find(pCollider) }; + if (componentIt != m_ColliderComponents.end()) + m_ColliderComponents.erase(componentIt); + } + + std::vector CollidersHandler::GetInteractableColliders(const std::string& layerName) const + { + std::vector colliders{}; + + const unsigned int interactionsLayerMaks{ m_LayerInteractions.at(layerName) }; + + std::ranges::copy_if(m_ColliderComponents, std::back_inserter(colliders), [this, interactionsLayerMaks](const auto& collider) + { + // check all existing colliders, get their layer name's associated bit position and check if it is in interactionsLayerMaks + return interactionsLayerMaks & m_CollisionLayers.at(collider->GetCollisionLayerName()); + }); + + return colliders; + } +} diff --git a/FluffyEngine/CollidersHandler.h b/FluffyEngine/CollidersHandler.h index b79fa42..80b01d3 100644 --- a/FluffyEngine/CollidersHandler.h +++ b/FluffyEngine/CollidersHandler.h @@ -1,30 +1,25 @@ #pragma once #include "Singleton.h" #include +#include +#include namespace Fluffy { class CollidersHandler final : public Singleton { public: - inline void RegisterCollisionLayer(const std::string& layerName) - { - m_CollisionLayers.emplace(layerName, 1 << (unsigned int)m_CollisionLayers.size()); - } + void RegisterCollisionLayers(const std::vector& layerNames, const std::unordered_map> layersInteractions); inline void RegisterColliderComponent(class RectColliderComponent* pCollider) { m_ColliderComponents.insert(pCollider); } - inline void UnregisterColliderComponent(class RectColliderComponent* pCollider) - { - const auto& componentIt{ m_ColliderComponents.find(pCollider) }; - if (componentIt != m_ColliderComponents.end()) - m_ColliderComponents.erase(componentIt); - } + void UnregisterColliderComponent(class RectColliderComponent* pCollider); inline const std::unordered_set& GetAllColliderComponents() const { return m_ColliderComponents; } + std::vector GetInteractableColliders(const std::string& layerName) const; inline void Clear() { @@ -34,5 +29,8 @@ namespace Fluffy private: std::unordered_set m_ColliderComponents{}; std::unordered_map m_CollisionLayers{}; + + // layerMask here defines all the layers the [key] interacts with (for example 01101001, where each 1 is a layer, defined in m_CollisionLayers) + std::unordered_map m_LayerInteractions{}; }; } diff --git a/FluffyEngine/FluffyEngine.vcxproj b/FluffyEngine/FluffyEngine.vcxproj index 2fde173..a6d53e7 100644 --- a/FluffyEngine/FluffyEngine.vcxproj +++ b/FluffyEngine/FluffyEngine.vcxproj @@ -232,6 +232,7 @@ + diff --git a/FluffyEngine/FluffyEngine.vcxproj.filters b/FluffyEngine/FluffyEngine.vcxproj.filters index 263f30a..c51aaa3 100644 --- a/FluffyEngine/FluffyEngine.vcxproj.filters +++ b/FluffyEngine/FluffyEngine.vcxproj.filters @@ -179,5 +179,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/FluffyEngine/RectColliderComponent.cpp b/FluffyEngine/RectColliderComponent.cpp index 0d81f10..d7766a6 100644 --- a/FluffyEngine/RectColliderComponent.cpp +++ b/FluffyEngine/RectColliderComponent.cpp @@ -6,6 +6,7 @@ #include "IEventParam.h" #include #include +#include namespace Fluffy { @@ -30,7 +31,7 @@ namespace Fluffy void RectColliderComponent::Update(const float /*deltaTime*/) { - const auto& colliders{ CollidersHandler::GetInstance().GetAllColliderComponents() }; + const auto& colliders{ CollidersHandler::GetInstance().GetInteractableColliders(m_CollisionLayerName) }; std::vector currentCollisions{}; for (const auto& pCollider : colliders) @@ -45,9 +46,14 @@ namespace Fluffy } std::vector exitCollisions{}; - std::ranges::set_difference(m_CurrentCollisions, currentCollisions, std::back_inserter(exitCollisions)); + std::ranges::copy_if(m_CurrentCollisions, std::back_inserter(exitCollisions), + [¤tCollisions](const auto& pCollision) + { + // find all the colliders that are still in m_CurrentCollisions (old collisions) but NOT in currentCollisions + return std::ranges::find(currentCollisions, pCollision) == currentCollisions.end(); + }); - std::ranges::for_each(exitCollisions, [this](RectColliderComponent* pCollider) + std::ranges::for_each(exitCollisions, [this, currentCollisions](RectColliderComponent* pCollider) { const CollisionParam param{ this, pCollider }; m_OnCollisionExit.Invoke(¶m); @@ -76,7 +82,7 @@ namespace Fluffy return false; // If one rectangle is under the other - if (r1.bottom > r2.Top() || r2.bottom > r1.Top()) + if (r1.top > r2.Bottom() || r2.top > r1.Bottom()) return false; return true; diff --git a/FluffyEngine/Rectf.h b/FluffyEngine/Rectf.h index cdd898b..c668224 100644 --- a/FluffyEngine/Rectf.h +++ b/FluffyEngine/Rectf.h @@ -11,30 +11,30 @@ namespace Fluffy { } - Rectf(float left, float bottom, float width, float height) + Rectf(float left, float top, float width, float height) : left{ left } - , bottom{ bottom } + , top{ top } , width{ width } , height{ height } { } - Rectf(const glm::vec2& bottomLeft, const glm::vec2& size) - : left{ bottomLeft.x } - , bottom{ bottomLeft.y } + Rectf(const glm::vec2& topLeft, const glm::vec2& size) + : left{ topLeft.x } + , top{ topLeft.y } , width{ size.x } , height{ size.y } { } float left; - float bottom; + float top; float width; float height; - float Top() const + float Bottom() const { - return bottom + height; + return top + height; } float Right() const @@ -44,7 +44,7 @@ namespace Fluffy glm::vec2 Center() const { - return { left + (width / 2.0f), bottom + (height / 2.0f) }; + return { left + (width / 2.0f), top + (height / 2.0f) }; } }; } diff --git a/Galaga/CollisionLayers.h b/Galaga/CollisionLayers.h index e4daae4..17d9209 100644 --- a/Galaga/CollisionLayers.h +++ b/Galaga/CollisionLayers.h @@ -1,10 +1,28 @@ #pragma once #include +#include +#include namespace CollisionLayers { - const std::string ENEMY{ "Enemy" }; const std::string PLAYER{ "Player" }; + const std::string ENEMY{ "Enemy" }; const std::string BULLET{ "Bullet" }; const std::string PLAYABLE_AREA{ "PlayableArea" }; + + const std::vector LAYERS + { + PLAYER, + ENEMY, + BULLET, + PLAYABLE_AREA, + }; + + const std::unordered_map> LAYER_INTERACTIONS + { + { PLAYER, { ENEMY, BULLET } }, + { ENEMY, { PLAYER, BULLET } }, + { BULLET, { } }, // Bullet doesn't need to check any collisions itself; the PLAYER and ENEMIES will check bullets + { PLAYABLE_AREA, { BULLET } }, + }; } diff --git a/Galaga/HealthDisplayComponent.h b/Galaga/HealthDisplayComponent.h index 9a0f6aa..0e04e36 100644 --- a/Galaga/HealthDisplayComponent.h +++ b/Galaga/HealthDisplayComponent.h @@ -8,9 +8,6 @@ namespace Fluffy class Component; class GameObject; class Sprite; - class IEventListener; - class Event; - class Text; } class HealthDisplayComponent final : public Fluffy::Component, Fluffy::IEventListener diff --git a/Galaga/Main.cpp b/Galaga/Main.cpp index 5600bab..04b1ee6 100644 --- a/Galaga/Main.cpp +++ b/Galaga/Main.cpp @@ -31,6 +31,8 @@ #include "MoveCommand.h" #include "ShootCommand.h" #include "BulletsManager.h" +#include "CollidersHandler.h" +#include "CollisionLayers.h" #include "Structs.h" /* #include "SDLSoundSystem.h" @@ -40,6 +42,8 @@ using namespace Fluffy; static void CreateLevel1() { + CollidersHandler::GetInstance().RegisterCollisionLayers(CollisionLayers::LAYERS, CollisionLayers::LAYER_INTERACTIONS); + auto& scene = SceneManager::GetInstance().CreateScene("Level1"); const auto font{ ResourceManager::GetInstance().LoadFont("Lingua.otf", 15) }; @@ -103,7 +107,6 @@ static void CreateLevel1() ServiceLocator::GetSoundSystem()->AddSFX("../Data/sound.wav", 1); ServiceLocator::GetSoundSystem()->Play(1, 30);*/ - CharactersManager::GetInstance()->StartLevel1(); }