108 lines
4.0 KiB
C++
108 lines
4.0 KiB
C++
#include <object/components/boxcollider.hpp>
|
|
#include <object/entity.hpp>
|
|
#include <renderer/texture.hpp>
|
|
|
|
#include <algorithm>
|
|
|
|
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<Entity*> currentCollisions;
|
|
std::vector<Entity*> 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<BoxCollider>();
|
|
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);
|
|
}
|
|
} |