#include #include #include #include namespace Game::Object::Components { BoxCollider::BoxCollider(const BoxCollider& other) : Component(other) { LOG("Copied BoxCollider Component: " << mName); } BoxCollider& BoxCollider::operator=(const BoxCollider& other) { if (this != &other) { Component::operator=(other); } return *this; } BoxCollider::BoxCollider(BoxCollider&& other) noexcept : Component(std::move(other)) { LOG("Moved BoxCollider Component: " << mName); } BoxCollider& BoxCollider::operator=(BoxCollider&& other) noexcept { if (this != &other) { Component::operator=(std::move(other)); } return *this; } BoxCollider::~BoxCollider() = default; void BoxCollider::start(Object::Entity* thisEntity) { // Initialization code for the box collider can go here } void BoxCollider::update(float deltaTime, Object::Entity* thisEntity) { // Collision detection and response logic can go here (void)deltaTime; if (!thisEntity) { return; } // Make box bounds Transform* transform = thisEntity->getTransform(); if (!transform) { return; } float width = 1.f; float height = 1.f; if (const auto tex = thisEntity->getTexture()) { width = tex->getWidth() * transform->scaleX * UNIVERSAL_SCALE_COEFFICIENT; height = tex->getHeight() * transform->scaleY * UNIVERSAL_SCALE_COEFFICIENT; } else { width = transform->scaleX * UNIVERSAL_SCALE_COEFFICIENT; height = transform->scaleY * UNIVERSAL_SCALE_COEFFICIENT; } width = std::max(1.f, width); height = std::max(1.f, height); // Transform position is used as top-left in rendering, so match that convention for collision bounds. float left = transform->x; float right = transform->x + width; float top = transform->y; float bottom = transform->y + height; mBounds = {left, right, top, bottom}; // Check for collisions with other entities that have box colliders // For simplicity, just check each std::unordered_set currentCollisions; std::vector entities = State::GameState::getInstance().getEntitiesSnapshot(); for (Entity* other : entities) { if (!other || other == thisEntity || !other->isActive()) continue; // Don't check collision with self/inactive entities BoxCollider* otherCollider = other->getComponent(); if (!otherCollider || !otherCollider->isActive()) continue; // No active collider, skip BoxColliderBounds otherBounds = otherCollider->getBounds(); bool isOverlapping = left < otherBounds.right && right > otherBounds.left && top < otherBounds.bottom && bottom > otherBounds.top; if (isOverlapping) { currentCollisions.insert(other); // Collision detected if (!mCollidingWith.contains(other)) { thisEntity->onCollisionEnter(other); if (!thisEntity->isActive()) { return; } //other->onCollisionEnter(thisEntity); } else { thisEntity->onCollisionStay(other); if (!thisEntity->isActive()) { return; } //other->onCollisionStay(thisEntity); } } } for (Entity* wasColliding : mCollidingWith) { if (!currentCollisions.contains(wasColliding)) { thisEntity->onCollisionExit(wasColliding); //wasColliding->onCollisionExit(thisEntity); } } mCollidingWith = std::move(currentCollisions); } }