From adaed679af74e6f320bbefb5fdcf8fc8b6f2f0b9 Mon Sep 17 00:00:00 2001 From: Benedikt Galbavy Date: Sat, 22 Mar 2025 14:38:26 +0100 Subject: [PATCH] InteractionManager + proof of concept --- include/Entity.h | 143 ++++++++++++++------------- include/EventListener.h | 11 --- include/EventManager.h | 11 ++- include/GameInternal.h | 6 +- include/InputManager.h | 10 +- include/InteractionEventdataStruct.h | 15 +++ include/InteractionListener.h | 17 ++++ include/InteractionManager.h | 35 +++++++ include/PowerupComponent.h | 23 +++-- include/RenderObject.h | 4 +- include/SpriteComponent.h | 5 + include/TextureManager.h | 6 ++ include/VEGO_Event.h | 8 +- src/AssetManager.cpp | 2 + src/Entity.cpp | 4 +- src/EventManager.cpp | 23 +++-- src/GameInternal.cpp | 17 ++-- src/InputManager.cpp | 7 +- src/InteractionManager.cpp | 90 +++++++++++++++++ src/PowerupComponent.cpp | 16 +++ src/RenderObject.cpp | 6 +- src/SpriteComponent.cpp | 2 +- src/TextureManager.cpp | 3 + 23 files changed, 339 insertions(+), 125 deletions(-) delete mode 100644 include/EventListener.h create mode 100644 include/InteractionEventdataStruct.h create mode 100644 include/InteractionListener.h create mode 100644 include/InteractionManager.h create mode 100644 src/InteractionManager.cpp diff --git a/include/Entity.h b/include/Entity.h index 5f8f3cc..978a9ac 100644 --- a/include/Entity.h +++ b/include/Entity.h @@ -35,85 +35,90 @@ class Entity { public: - /*! - * \brief Used for rendering order (last is highest) or retrieving entities of group - * \todo Label used in singular entity shouldn't use plural - * \todo HEARTS are rendered above POWERUPS, missleading order - * \todo PROJECTILE are rendered above POWERUPS, missleading order - * \todo Generalize HEARTS as UI or similar - */ - enum class GroupLabel - { - MAPTILES, //!< Entity using TileComponent - PLAYERS, //!< Primary entity in player controll - ENEMIES, //!< \deprecated All players now grouped as Entity::PLAYERS - COLLIDERS, //!< Fixed collider entity, e.g. a wall - PROJECTILE, //!< \todo Document - HEARTS, //!< \todo Document - POWERUPS //!< \todo Document - }; + /*! + * \brief Used for rendering order (last is highest) or retrieving entities of group + * \todo Label used in singular entity shouldn't use plural + * \todo HEARTS are rendered above POWERUPS, missleading order + * \todo PROJECTILE are rendered above POWERUPS, missleading order + * \todo Generalize HEARTS as UI or similar + */ + enum class GroupLabel + { + MAPTILES, //!< Entity using TileComponent + PLAYERS, //!< Primary entity in player controll + ENEMIES, //!< \deprecated All players now grouped as Entity::PLAYERS + COLLIDERS, //!< Fixed collider entity, e.g. a wall + PROJECTILE, //!< \todo Document + HEARTS, //!< \todo Document + POWERUPS //!< \todo Document + }; - /*! - * \todo Document - */ - explicit Entity(Manager& mManager) : - manager(mManager) { }; + /*! + * \todo Document + */ + explicit Entity(Manager& mManager) : + manager(mManager) { }; - void update(uint_fast16_t diffTime) const; //!< Call each frame to update all components + void update(uint_fast16_t diffTime) const; //!< Call each frame to update all components - bool isActive() const { return this->active; } //!< \sa destroy() - //! Mark for destruction for Manager::refresh() and disables collision - //! \sa ColliderComponent - void destroy() { - this->active = false; - if (this->hasComponent()) { - this->getComponent().removeCollision(); - } - } + bool isActive() const { return this->active; } //!< \sa destroy() + //! Mark for destruction for Manager::refresh() and disables collision + //! \sa ColliderComponent + void destroy() { + this->active = false; + if (this->hasComponent()) { + this->getComponent().removeCollision(); + } + } - bool hasGroup(Group mGroup); //!< \sa GroupLabel - void addGroup(Group mGroup); //!< \sa GroupLabel - void delGroup(Group mGroup); //!< \sa GroupLabel - //! \returns bitset with true on position GroupLabel if the entity belongs to group - //! \sa GroupLabel - std::bitset getGroupBitSet(); + bool hasGroup(Group mGroup); //!< \sa GroupLabel + void addGroup(Group mGroup); //!< \sa GroupLabel + void delGroup(Group mGroup); //!< \sa GroupLabel + //! \returns bitset with true on position GroupLabel if the entity belongs to group + //! \sa GroupLabel + std::bitset getGroupBitSet(); - //! \sa Manager - Manager& getManager() { return manager; }; + //! \sa Manager + Manager& getManager() { return manager; }; - template bool hasComponent() const //! \sa Component - { - return componentBitSet[getComponentTypeID()]; - } + template bool hasComponent() const //! \sa Component + { + return componentBitSet[getComponentTypeID()]; + } - //! \brief Adds specified type as component and calls Component::init() - //! \param mArgs Constructor arguments of component - template T& addComponent(TArgs&&...mArgs) - { - T* c(new T(std::forward(mArgs)...)); - c->entity = this; - std::unique_ptr uPtr{ c }; - this->components.emplace_back(std::move(uPtr)); + //! \brief Adds specified type as component and calls Component::init() + //! \param mArgs Constructor arguments of component + template T& addComponent(TArgs&&...mArgs) + { + T* c(new T(std::forward(mArgs)...)); + c->entity = this; + std::shared_ptr uPtr{ c }; + this->components.at(getComponentTypeID()) = std::move(uPtr); - componentArray[getComponentTypeID()] = c; - componentBitSet[getComponentTypeID()] = true; + componentArray[getComponentTypeID()] = c; + componentBitSet[getComponentTypeID()] = true; - c->init(); - return *c; - }; - - template T& getComponent() const //!< \todo: rewrite to use optionals - { - auto ptr(componentArray[getComponentTypeID()]); - return *static_cast(ptr); - } + c->init(); + return *c; + }; + + template T& getComponent() const //!< \todo: rewrite to use optionals + { + auto ptr(componentArray[getComponentTypeID()]); + return *static_cast(ptr); + } + + template std::shared_ptr getComponentAsPointer() const + { + return std::static_pointer_cast(components.at(getComponentTypeID())); + } private: - Manager& manager; - bool active = true; - std::vector> components; + Manager& manager; + bool active = true; + std::array, MAX_COMPONENTS> components; - ComponentArray componentArray = {}; - ComponentBitSet componentBitSet; - GroupBitSet groupBitSet; + ComponentArray componentArray = {}; + ComponentBitSet componentBitSet; + GroupBitSet groupBitSet; }; \ No newline at end of file diff --git a/include/EventListener.h b/include/EventListener.h deleted file mode 100644 index 5bdddc7..0000000 --- a/include/EventListener.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include -#include - -class EventListener { -public: - virtual SDL_AppResult handleEvent(SDL_EventType type, SDL_Event* const event) = 0; - EventListener() {}; - virtual ~EventListener() {}; -}; \ No newline at end of file diff --git a/include/EventManager.h b/include/EventManager.h index 1e48b16..3a4f0b4 100644 --- a/include/EventManager.h +++ b/include/EventManager.h @@ -1,7 +1,6 @@ #pragma once -#include "EventListener.h" - +#include #include #include #include @@ -9,10 +8,14 @@ #include "SDL3/SDL_events.h" #include "SDL3/SDL_init.h" +typedef std::function EventListener; + class EventManager { public: - void registerListener(EventListener* listener, std::initializer_list eventTypes); + EventManager(); + + void registerListener(EventListener listener, std::initializer_list eventTypes); SDL_AppResult handleEvent(SDL_Event* const event); private: - std::map> eventListeners = std::map>(); + std::map> eventListeners = std::map>(); }; \ No newline at end of file diff --git a/include/GameInternal.h b/include/GameInternal.h index 4dead69..8e046bb 100644 --- a/include/GameInternal.h +++ b/include/GameInternal.h @@ -8,6 +8,7 @@ #include #include "EventManager.h" +#include "InteractionManager.h" #include "Manager.h" #include "SDL3/SDL_events.h" #include "SDL3/SDL_init.h" @@ -49,10 +50,11 @@ public: /* static */ TextureManager* textureManager; /* static */ SoundManager* soundManager; /* static */ InputManager* inputManager; + RenderManager* renderManager; + EventManager* eventManager; + InteractionManager* interactionManager; Manager manager; - RenderManager renderManager; - EventManager eventManager; Map* map; // game specific, might not be needed for all types of games ConfigLoader* config; diff --git a/include/InputManager.h b/include/InputManager.h index b1f10e9..ebc6272 100644 --- a/include/InputManager.h +++ b/include/InputManager.h @@ -1,8 +1,7 @@ #pragma once -#include "EventListener.h" -#include "SDL3/SDL_events.h" -#include "SDL3/SDL_init.h" +#include +#include #include #include #include @@ -10,7 +9,7 @@ #include #include -class InputManager : public EventListener { +class InputManager { public: enum class EventType { KeyDown, @@ -121,6 +120,8 @@ public: std::vector getBindings(const std::string& actionName, const std::string& context) const; std::vector getActionsByKey(const Key key) const; + SDL_AppResult handleEvent(SDL_EventType type, SDL_Event* const event); + private: // TODO: flesh this out to avoid loops in process actions // additionally to actionsByContext, not instead @@ -131,7 +132,6 @@ private: std::string activeContext; void initKeyMap(); - SDL_AppResult handleEvent(SDL_EventType type, SDL_Event* const event) override; }; std::ostream& operator<<(std::ostream& os, InputManager::Key key); diff --git a/include/InteractionEventdataStruct.h b/include/InteractionEventdataStruct.h new file mode 100644 index 0000000..036f03c --- /dev/null +++ b/include/InteractionEventdataStruct.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Entity.h" +#include "InteractionListener.h" +#include "Vector2D.h" +#include +#include + +struct InteractionEventdataStruct { + void* actor; // suggestion, can also be used for other arbitrary data + void* data; + std::weak_ptr target = std::weak_ptr(); + std::shared_ptr targetingReference; // required without explicit target + uint8_t strategy = 0; // required without explicit target, defaults to none +}; \ No newline at end of file diff --git a/include/InteractionListener.h b/include/InteractionListener.h new file mode 100644 index 0000000..06216db --- /dev/null +++ b/include/InteractionListener.h @@ -0,0 +1,17 @@ +#pragma once + +#include "Vector2D.h" +#include + +class InteractionListener { +public: + InteractionListener() { }; + virtual ~InteractionListener() { }; + + virtual void interact(void* actor, void* data) = 0; + virtual std::shared_ptr getPosition() // required for targeting strategy, return null to only allow explicit targeting + { + return nullptr; + } + +}; \ No newline at end of file diff --git a/include/InteractionManager.h b/include/InteractionManager.h new file mode 100644 index 0000000..f465fcb --- /dev/null +++ b/include/InteractionManager.h @@ -0,0 +1,35 @@ +#pragma once + +#include "InteractionListener.h" + +#include "SDL3/SDL_events.h" +#include "SDL3/SDL_init.h" +#include +#include +#include +#include +#include + +// TODO: ranges concept to avoid to in cpp +typedef std::function(Vector2D*, std::vector>)> TargetingFunc; + +class InteractionManager { +public: + InteractionManager(); + InteractionManager (const InteractionManager&) = delete; + InteractionManager& operator= (const InteractionManager&) = delete; + + enum class TargetingStrategy : uint8_t { + none = 0, + closest, + manhattenDistance + }; + + SDL_AppResult handleInteract(SDL_EventType type, SDL_Event* const event); + void registerListener(std::weak_ptr listener); + uint8_t registerTargetingFunc(TargetingFunc func); +private: + + std::vector> listeners; + std::array targetingFuncs; +}; \ No newline at end of file diff --git a/include/PowerupComponent.h b/include/PowerupComponent.h index 7229283..f7bef62 100644 --- a/include/PowerupComponent.h +++ b/include/PowerupComponent.h @@ -2,19 +2,24 @@ #include #include "Component.h" +#include "InteractionListener.h" -class PowerupComponent : public Component +class PowerupComponent : public Component, public InteractionListener { public: - /** - * @brief Construct a new Powerup Component object - * @param func The function to be called when the powerup is picked up - */ - PowerupComponent(std::function func); - ~PowerupComponent() {}; + /** + * @brief Construct a new Powerup Component object + * @param func The function to be called when the powerup is picked up + */ + PowerupComponent(std::function func); + ~PowerupComponent() {}; - void update(uint_fast16_t diffTime) override; + void update(uint_fast16_t diffTime) override; + + + void interact(void* actor, void* data) override; + std::shared_ptr getPosition() override; private: - std::function pickupFunc; + std::function pickupFunc; }; \ No newline at end of file diff --git a/include/RenderObject.h b/include/RenderObject.h index ba4b929..9b3e881 100644 --- a/include/RenderObject.h +++ b/include/RenderObject.h @@ -7,7 +7,7 @@ class RenderObject public: virtual void draw() = 0; - RenderObject(int zIndex, RenderManager& renderManager); + RenderObject(int zIndex, RenderManager* renderManager); ~RenderObject(); int getZIndex() { return this->zIndex; }; @@ -23,5 +23,5 @@ private: int zIndex = 0; protected: - RenderManager& renderManager; + RenderManager* renderManager; }; \ No newline at end of file diff --git a/include/SpriteComponent.h b/include/SpriteComponent.h index 7a82487..247a063 100644 --- a/include/SpriteComponent.h +++ b/include/SpriteComponent.h @@ -40,6 +40,11 @@ private: const char* path; //!< empty string if texture has a texture enum value, otherwise the path of the texture public: + //debug + Textures getTexture() { return this->textureEnum; } + + + SpriteComponent(Textures texture, int zIndex); SpriteComponent(Textures texture, int xOffset, int yOffset, int zIndex); SpriteComponent(const char* path, int xOffset, int yOffset, int zIndex); diff --git a/include/TextureManager.h b/include/TextureManager.h index 17f0903..a7f1e29 100644 --- a/include/TextureManager.h +++ b/include/TextureManager.h @@ -83,9 +83,15 @@ class TextureManager */ SDL_Texture* loadMapTileTexture(const char* path); + std::string getTexturePath(Textures texture) { + return this->texture_references.at(texture); + } + private: SDL_ScaleMode scaleMode = SDL_SCALEMODE_NEAREST; Manager* manager; std::map texture_cache; std::map mapTile_texture_cache; + + std::map texture_references; }; \ No newline at end of file diff --git a/include/VEGO_Event.h b/include/VEGO_Event.h index b74e1a2..a90d46a 100644 --- a/include/VEGO_Event.h +++ b/include/VEGO_Event.h @@ -1,5 +1,7 @@ #pragma once -enum VEGO_Event { - VEGO_Event_Interaction = SDL_EVENT_USER -}; \ No newline at end of file +#include + +namespace vego { + extern Uint32 VEGO_Event_Interaction; +} \ No newline at end of file diff --git a/src/AssetManager.cpp b/src/AssetManager.cpp index c4ae91d..ee589e0 100644 --- a/src/AssetManager.cpp +++ b/src/AssetManager.cpp @@ -37,6 +37,8 @@ void AssetManager::createPowerup(Vector2D pos, std::function pic powerups.addComponent("powerup", 0.6f); powerups.addComponent(pickupFunc); powerups.addGroup((size_t)Entity::GroupLabel::POWERUPS); + + VEGO_Game().interactionManager->registerListener(powerups.getComponentAsPointer()); } Vector2D AssetManager::calculateSpawnPosition() diff --git a/src/Entity.cpp b/src/Entity.cpp index 987626d..8a4a0e9 100644 --- a/src/Entity.cpp +++ b/src/Entity.cpp @@ -6,7 +6,9 @@ void Entity::update(uint_fast16_t diffTime) const { - for (auto const& c : components) c->update(diffTime); + for (auto const& c : components) + if (c) + c->update(diffTime); } bool Entity::hasGroup(Group mGroup) diff --git a/src/EventManager.cpp b/src/EventManager.cpp index 93e760b..049a8b0 100644 --- a/src/EventManager.cpp +++ b/src/EventManager.cpp @@ -1,16 +1,27 @@ #include "EventManager.h" -#include "EventListener.h" #include "SDL3/SDL_events.h" #include "SDL3/SDL_init.h" +#include "SDL3/SDL_stdinc.h" +#include "VEGO_Event.h" #include +#include #include #include -void EventManager::registerListener(EventListener* listener, std::initializer_list eventTypes) +Uint32 vego::VEGO_Event_Interaction; + +EventManager::EventManager() { - std::ranges::for_each(eventTypes.begin(), eventTypes.end(), [this, &listener](const SDL_EventType& eventType) { + + /// \TODO: from c++26 you (should be able to) can get the amount of name values in an enum + vego::VEGO_Event_Interaction = SDL_RegisterEvents(1); // TODO: error handling +} + +void EventManager::registerListener(EventListener listener, std::initializer_list eventTypes) +{ + std::ranges::for_each(eventTypes.begin(), eventTypes.end(), [this, &listener](const Uint32& eventType) { if (!this->eventListeners.contains(eventType)) { - this->eventListeners.insert({eventType, std::vector()}); + this->eventListeners.insert({eventType, std::vector()}); } this->eventListeners.at(eventType).emplace_back(listener); }); @@ -21,8 +32,8 @@ SDL_AppResult EventManager::handleEvent(SDL_Event* event) SDL_EventType type = (SDL_EventType) event->type; if (this->eventListeners.contains(type)) { auto results = this->eventListeners.at(type) | std::views::transform( - [&event](EventListener* listener) { - return listener->handleEvent((SDL_EventType) event->type, event); + [&event](EventListener listener) { + return listener((SDL_EventType) event->type, event); }); if (std::ranges::contains(results, SDL_APP_FAILURE)) return SDL_APP_FAILURE; diff --git a/src/GameInternal.cpp b/src/GameInternal.cpp index e57c4c7..d4aea1a 100644 --- a/src/GameInternal.cpp +++ b/src/GameInternal.cpp @@ -2,6 +2,9 @@ #include "CollisionHandler.h" #include "AssetManager.h" +#include "EventManager.h" +#include "InputManager.h" +#include "InteractionManager.h" #include "RenderManager.h" #include #include "SDL3/SDL_events.h" @@ -17,12 +20,12 @@ #include #include +#include #include "ConfigLoader.h" GameInternal::GameInternal() : manager(this), - renderManager(), tiles(manager.getGroup((size_t)Entity::GroupLabel::MAPTILES)), players(manager.getGroup((size_t)Entity::GroupLabel::PLAYERS)), projectiles(manager.getGroup((size_t)Entity::GroupLabel::PROJECTILE)), @@ -48,10 +51,12 @@ SDL_AppResult GameInternal::init() GameInternal::collisionHandler = new CollisionHandler(manager); // why does this use a referrence, but AssetManager a pointer? GameInternal::inputManager = new InputManager(); - this->eventManager.registerListener(inputManager, { SDL_EVENT_KEY_DOWN, SDL_EVENT_KEY_UP }); + GameInternal::renderManager = new RenderManager(); + GameInternal::eventManager = new EventManager(); + GameInternal::interactionManager = new InteractionManager(); - /// \TODO: from c++26 you (should be able to) can loop through all values of an enum - SDL_RegisterEvents(VEGO_Event_Interaction); + this->eventManager->registerListener(std::bind_front(&InputManager::handleEvent, this->inputManager), { SDL_EVENT_KEY_DOWN, SDL_EVENT_KEY_UP }); + this->eventManager->registerListener(std::bind_front(&InteractionManager::handleInteract, VEGO_Game().interactionManager), { vego::VEGO_Event_Interaction }); int flags = 0; if (finalConfig.at("fullscreen")) @@ -122,7 +127,7 @@ SDL_AppResult GameInternal::init() } SDL_AppResult GameInternal::handleEvent(SDL_Event* event) { - SDL_AppResult result = this->eventManager.handleEvent(event); + SDL_AppResult result = this->eventManager->handleEvent(event); if (event->type == SDL_EVENT_QUIT) { this->clean(); @@ -147,7 +152,7 @@ void GameInternal::update(Uint64 frameTime) void GameInternal::render() { SDL_RenderClear(renderer); - this->renderManager.renderAll(); + this->renderManager->renderAll(); SDL_RenderPresent(renderer); } diff --git a/src/InputManager.cpp b/src/InputManager.cpp index bb57541..6542ec3 100644 --- a/src/InputManager.cpp +++ b/src/InputManager.cpp @@ -1,7 +1,11 @@ #include "InputManager.h" +#include "InteractionEventdataStruct.h" #include "SDL3/SDL_events.h" #include "SDL3/SDL_init.h" #include +#include "SDL3/SDL_stdinc.h" +#include "VEGO.h" +#include "VEGO_Event.h" std::ostream& operator<<(std::ostream& os, InputManager::Key key) { static const std::unordered_map keyToString { @@ -342,14 +346,11 @@ std::string InputManager::getActiveContext() const { } SDL_AppResult InputManager::handleEvent(SDL_EventType type, SDL_Event* const event) { - std::cout << "in handleEvent" << std::endl; if (type != SDL_EVENT_KEY_DOWN) { - std::cout << "ignore key up" << std::endl; return SDL_APP_CONTINUE; } if (event->key.repeat) { - std::cout << "ignore key repeat" << std::endl; return SDL_APP_CONTINUE; } diff --git a/src/InteractionManager.cpp b/src/InteractionManager.cpp new file mode 100644 index 0000000..5c74ae9 --- /dev/null +++ b/src/InteractionManager.cpp @@ -0,0 +1,90 @@ +#include "InteractionManager.h" + +#include "InteractionEventdataStruct.h" +#include "InteractionListener.h" +#include "SDL3/SDL_init.h" +#include "VEGO_Event.h" +#include "Vector2D.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +InteractionManager::InteractionManager() +{ + this->targetingFuncs.fill(nullptr); + this->targetingFuncs.at(static_cast::type>(InteractionManager::TargetingStrategy::closest)) = [](Vector2D* reference, std::vector> input) { + return std::shared_ptr(); + }; + this->targetingFuncs.at(static_cast::type>(InteractionManager::TargetingStrategy::closest)) = [](Vector2D* reference, std::vector> input) { + auto min = std::ranges::min_element(input, [&reference](std::shared_ptr& a, std::shared_ptr& b) { + std::shared_ptr coordA = a->getPosition(); + std::shared_ptr coordB = b->getPosition(); + + if (coordB == nullptr) return true; + if (coordA == nullptr) return false; + + return std::sqrt(std::pow(coordA->x - reference->x, 2) + std::pow(coordA->y - reference->y, 2)) < std::sqrt(std::pow(coordB->x - reference->x, 2) + std::pow(coordB->y - reference->y, 2)); + }); + return min == std::ranges::end(input) ? nullptr : *min; + }; + this->targetingFuncs.at(static_cast::type>(InteractionManager::TargetingStrategy::manhattenDistance)) = [](Vector2D* reference, std::vector> input) { + auto min = std::ranges::min_element(input, [&reference](std::shared_ptr& a, std::shared_ptr& b) { + std::shared_ptr coordA = a->getPosition(); + std::shared_ptr coordB = b->getPosition(); + + if (coordB == nullptr) return true; + if (coordA == nullptr) return false; + + return (std::abs(coordA->x - reference->x) + std::abs(coordA->y - reference->y)) < (std::abs(coordB->x - reference->x) + std::abs(coordB->y - reference->y)); + }); + return min == std::ranges::end(input) ? nullptr : *min; + }; +} + +SDL_AppResult InteractionManager::handleInteract(SDL_EventType type, SDL_Event* const event) +{ + if (type != vego::VEGO_Event_Interaction) { // error handling + return SDL_APP_CONTINUE; + } + + InteractionEventdataStruct* data = static_cast(event->user.data1); + + std::shared_ptr listener = data->target.lock(); + + if (data->strategy != static_cast::type>(InteractionManager::TargetingStrategy::none)) { + listener = this->targetingFuncs.at(data->strategy)( + data->targetingReference.get(), + this->listeners + | std::views::transform(&std::weak_ptr::lock) + | std::views::filter(&std::shared_ptr::operator bool) + | std::ranges::to() + ); + } + + if (listener) { + listener->interact(data->actor, data->data); + } + + return SDL_APP_CONTINUE; +} + +void InteractionManager::registerListener(std::weak_ptr listener) +{ + this->listeners.emplace_back(listener); +} + +uint8_t InteractionManager::registerTargetingFunc(TargetingFunc func) +{ + auto it = std::ranges::find_if(this->targetingFuncs, [](const auto& func) { + return !func; + }); + (*it) = func; + return std::distance(this->targetingFuncs.begin(), it); +} \ No newline at end of file diff --git a/src/PowerupComponent.cpp b/src/PowerupComponent.cpp index 4db3f95..0e16c64 100644 --- a/src/PowerupComponent.cpp +++ b/src/PowerupComponent.cpp @@ -3,9 +3,13 @@ #include "CollisionHandler.h" #include "Entity.h" #include "HealthComponent.h" +#include "SpriteComponent.h" #include "StatEffectsComponent.h" #include "Constants.h" +#include "TextureManager.h" +#include "TransformComponent.h" #include +#include "VEGO.h" PowerupComponent::PowerupComponent(std::function func) { @@ -23,4 +27,16 @@ void PowerupComponent::update(uint_fast16_t diffTime) (this->pickupFunc)(player); this->entity->destroy(); } +} + + +void PowerupComponent::interact(void* actor, void* data) +{ + std::cout << VEGO_Game().textureManager->getTexturePath(this->entity->getComponent().getTexture()) << std::endl; +} + + +std::shared_ptr PowerupComponent::getPosition() +{ + return std::make_shared(this->entity->getComponent().position); } \ No newline at end of file diff --git a/src/RenderObject.cpp b/src/RenderObject.cpp index 5c21ee9..897940e 100644 --- a/src/RenderObject.cpp +++ b/src/RenderObject.cpp @@ -1,10 +1,10 @@ #include "RenderObject.h" #include "RenderManager.h" -RenderObject::RenderObject(int zIndex, RenderManager& renderManager) : zIndex(zIndex), renderManager(renderManager) { - renderManager.add(this); +RenderObject::RenderObject(int zIndex, RenderManager* renderManager) : zIndex(zIndex), renderManager(renderManager) { + renderManager->add(this); } RenderObject::~RenderObject() { - this->renderManager.remove(this); + this->renderManager->remove(this); } \ No newline at end of file diff --git a/src/SpriteComponent.cpp b/src/SpriteComponent.cpp index 0cc29c7..8bd341a 100644 --- a/src/SpriteComponent.cpp +++ b/src/SpriteComponent.cpp @@ -18,7 +18,7 @@ SpriteComponent::SpriteComponent(Textures texture, int zIndex) : RenderObject(zIndex, VEGO_Game().renderManager), textureXOffset(0), textureYOffset(0) { this->textureEnum = texture; - this->path = ""; + this->path = ""; } SpriteComponent::SpriteComponent(Textures texture, int xOffset, int yOffset, int zIndex) : RenderObject(zIndex, VEGO_Game().renderManager), textureXOffset(xOffset), textureYOffset(yOffset) diff --git a/src/TextureManager.cpp b/src/TextureManager.cpp index ee8fceb..02707a7 100644 --- a/src/TextureManager.cpp +++ b/src/TextureManager.cpp @@ -15,6 +15,9 @@ void TextureManager::addSingleTexture(Textures texture, const char* filePath) { SDL_SetTextureScaleMode(sdlTexture, this->scaleMode); // linear scaling results in blurry images this->texture_cache.emplace(texture, sdlTexture); + if (filePath != nullptr) { + this->texture_references.emplace(texture, std::string(filePath)); + } std::cout << "Loaded texture at " << filePath << std::endl; }