#pragma once #include #include #include #include #include #include #include #include #include #include namespace Game::Renderer { class Renderer; class Texture; } namespace Game::Object { class Entity { public: Entity(std::string name, std::shared_ptr tex, Transform transform) : mName(name), mTex(tex), mTransform(transform), mIsActive(true) { LOG("Created Entity: " << mName); } // I will define the copy and move constructors later - just deleted for now Entity(const Entity&); Entity& operator=(const Entity&); Entity(Entity&&) noexcept; Entity& operator=(Entity&&) noexcept; virtual ~Entity() = 0; // Destructor // Start is called when the entity is spawned virtual void start() = 0; // Update is called every update cycle; deltaTime is the time (in seconds) since the last update call virtual void update(float deltaTime) = 0; virtual void onWindowResized(int newWidth, int newHeight) {} // Called when the window is resized, with the new width and height in pixels virtual void destroyed() {}; // Pre-destruction call void render(Game::Renderer::Renderer* renderer, Game::Renderer::RendererConfig config); // Collision calls // Called once when a collision begins virtual void onCollisionEnter(Entity* other) {} // Called every update while a collision continues virtual void onCollisionStay(Entity* other) {} // Called once when a collision ends virtual void onCollisionExit(Entity* other) {} // Setters and getters void setTexture(std::shared_ptr tex) { mTex = tex; } void setName(const std::string& name) { mName = name; } void setTransform(const Transform& transform) { mTransform = transform; } void setActive(bool active) { mIsActive = active; } std::shared_ptr getTexture() { return mTex; } std::string getName() { return mName; } Transform* getTransform() { return &mTransform; } bool isActive() { return mIsActive; } int getZIndex() const { return mZIndex; } // Component management template T* addComponent(Args&&... args); template T* getComponent(); template bool removeComponent(); void updateComponents(float deltaTime); protected: std::string mName; std::shared_ptr mTex; Transform mTransform; bool mIsFlipped = false; // Whether the texture should be rendered flipped horizontally or not bool mIsActive = true; bool mIsVisible = true; int mZIndex = 0; // For rendering order; higher zIndex renders on top of lower zIndex float mTiledScale = 1.f; // Only used if the texture is tiled, to determine how much to scale the texture when rendering (since the entire texture is rendered as a single tile, this is necessary to be able to have different sized tiles) std::vector> mComponents; // Components attached to this entity; TODO private: }; template T* Entity::addComponent(Args&&... args) { static_assert(std::is_base_of_v, "T must derive from Component"); auto component = std::make_unique(std::forward(args)...); T* componentPtr = component.get(); mComponents.push_back(std::move(component)); return componentPtr; } template T* Entity::getComponent() { static_assert(std::is_base_of_v, "T must derive from Component"); for (const auto& component : mComponents) { if (auto casted = dynamic_cast(component.get())) { return casted; } } return nullptr; } template bool Entity::removeComponent() { static_assert(std::is_base_of_v, "T must derive from Component"); for (auto it = mComponents.begin(); it != mComponents.end(); it++) { if (dynamic_cast(it->get())) { mComponents.erase(it); return true; } } return false; } }