Commit, fix boxcollider
This commit is contained in:
@@ -8,5 +8,7 @@
|
|||||||
|
|
||||||
namespace Game::AGame {
|
namespace Game::AGame {
|
||||||
GAME_ENTITY(Enemy)
|
GAME_ENTITY(Enemy)
|
||||||
|
public:
|
||||||
|
void onCollisionEnter(Object::Entity* other) override;
|
||||||
END_GAME_ENTITY()
|
END_GAME_ENTITY()
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <object/components/component.hpp>
|
#include <object/components/component.hpp>
|
||||||
#include <state/gamestate.hpp>
|
#include <state/gamestate.hpp>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
namespace Game::Object::Components {
|
namespace Game::Object::Components {
|
||||||
struct BoxColliderBounds {
|
struct BoxColliderBounds {
|
||||||
@@ -21,10 +22,10 @@ namespace Game::Object::Components {
|
|||||||
void update(float deltaTime, Object::Entity* thisEntity) override;
|
void update(float deltaTime, Object::Entity* thisEntity) override;
|
||||||
|
|
||||||
BoxColliderBounds getBounds() const { return mBounds; }
|
BoxColliderBounds getBounds() const { return mBounds; }
|
||||||
bool isColliding() const { return mIsColliding; }
|
bool isColliding() const { return !mCollidingWith.empty(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BoxColliderBounds mBounds;
|
BoxColliderBounds mBounds{0.f, 0.f, 0.f, 0.f};
|
||||||
bool mIsColliding = false; // Whether this collider is currently colliding with another collider; used to determine whether to call onCollisionEnter vs onCollisionStay, and to call onCollisionExit when collisions end
|
std::unordered_set<Object::Entity*> mCollidingWith; // Track collisions per-entity so enter/stay/exit callbacks remain correct with multiple colliders
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,19 @@
|
|||||||
#include <game/agame/enemy.hpp>
|
#include <game/agame/enemy.hpp>
|
||||||
|
#include <object/components/boxcollider.hpp>
|
||||||
|
|
||||||
namespace Game::AGame {
|
namespace Game::AGame {
|
||||||
void Enemy::start() {
|
void Enemy::start() {
|
||||||
mZIndex = 20;
|
mZIndex = 20;
|
||||||
|
addComponent<Object::Components::BoxCollider>();
|
||||||
|
LOG("Enemy started: " << getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Enemy::update(float deltaTime) {
|
void Enemy::update(float deltaTime) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Enemy::onCollisionEnter(Object::Entity* other) {
|
||||||
|
LOG("Enemy '" << getName() << "' collided with '" << other->getName() << "' (onCollisionEnter); Killing myself now!");
|
||||||
|
GameManager::setSharedData("enemyActiveCount", GameManager::getSharedData<int>("enemyActiveCount") - 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
#include <object/components/boxcollider.hpp>
|
#include <object/components/boxcollider.hpp>
|
||||||
#include <object/entity.hpp>
|
#include <object/entity.hpp>
|
||||||
|
#include <renderer/texture.hpp>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace Game::Object::Components {
|
namespace Game::Object::Components {
|
||||||
BoxCollider::BoxCollider(const BoxCollider& other) : Component(other) {
|
BoxCollider::BoxCollider(const BoxCollider& other) : Component(other) {
|
||||||
@@ -32,44 +35,68 @@ namespace Game::Object::Components {
|
|||||||
|
|
||||||
void BoxCollider::update(float deltaTime, Object::Entity* thisEntity) {
|
void BoxCollider::update(float deltaTime, Object::Entity* thisEntity) {
|
||||||
// Collision detection and response logic can go here
|
// Collision detection and response logic can go here
|
||||||
|
(void)deltaTime;
|
||||||
|
|
||||||
|
if (!thisEntity) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Make box bounds
|
// Make box bounds
|
||||||
Transform* transform = thisEntity->getTransform();
|
Transform* transform = thisEntity->getTransform();
|
||||||
float halfWidth = transform->scaleX * UNIVERSAL_SCALE_COEFFICIENT * 0.5f;
|
if (!transform) {
|
||||||
float halfHeight = transform->scaleY * UNIVERSAL_SCALE_COEFFICIENT * 0.5f;
|
return;
|
||||||
float left = transform->x - halfWidth;
|
}
|
||||||
float right = transform->x + halfWidth;
|
|
||||||
float top = transform->y - halfHeight;
|
float width = 1.f;
|
||||||
float bottom = transform->y + halfHeight;
|
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};
|
mBounds = {left, right, top, bottom};
|
||||||
|
|
||||||
// Check for collisions with other entities that have box colliders
|
// Check for collisions with other entities that have box colliders
|
||||||
// For simplicity, just check each
|
// For simplicity, just check each
|
||||||
|
std::unordered_set<Entity*> currentCollisions;
|
||||||
std::vector<Entity*> entities = State::GameState::getInstance().getEntitiesSnapshot();
|
std::vector<Entity*> entities = State::GameState::getInstance().getEntitiesSnapshot();
|
||||||
for (Entity* other : entities) {
|
for (Entity* other : entities) {
|
||||||
if (other == thisEntity) continue; // Don't check collision with self
|
if (!other || other == thisEntity || !other->isActive()) continue; // Don't check collision with self/inactive entities
|
||||||
BoxCollider* otherCollider = other->getComponent<BoxCollider>();
|
BoxCollider* otherCollider = other->getComponent<BoxCollider>();
|
||||||
if (!otherCollider) continue; // No collider, skip
|
if (!otherCollider || !otherCollider->isActive()) continue; // No active collider, skip
|
||||||
BoxColliderBounds otherBounds = otherCollider->getBounds();
|
BoxColliderBounds otherBounds = otherCollider->getBounds();
|
||||||
if (left < otherBounds.right && right > otherBounds.left && top < otherBounds.bottom && bottom > otherBounds.top) {
|
bool isOverlapping = left < otherBounds.right && right > otherBounds.left && top < otherBounds.bottom && bottom > otherBounds.top;
|
||||||
|
if (isOverlapping) {
|
||||||
|
currentCollisions.insert(other);
|
||||||
// Collision detected
|
// Collision detected
|
||||||
if (!mIsColliding) {
|
if (!mCollidingWith.contains(other)) {
|
||||||
mIsColliding = true;
|
|
||||||
thisEntity->onCollisionEnter(other);
|
thisEntity->onCollisionEnter(other);
|
||||||
other->onCollisionEnter(thisEntity);
|
//other->onCollisionEnter(thisEntity);
|
||||||
} else {
|
} else {
|
||||||
thisEntity->onCollisionStay(other);
|
thisEntity->onCollisionStay(other);
|
||||||
other->onCollisionStay(thisEntity);
|
//other->onCollisionStay(thisEntity);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// No collision
|
|
||||||
if (mIsColliding) {
|
|
||||||
mIsColliding = false;
|
|
||||||
thisEntity->onCollisionExit(other);
|
|
||||||
other->onCollisionExit(thisEntity);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (Entity* wasColliding : mCollidingWith) {
|
||||||
|
if (!currentCollisions.contains(wasColliding)) {
|
||||||
|
thisEntity->onCollisionExit(wasColliding);
|
||||||
|
//wasColliding->onCollisionExit(thisEntity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mCollidingWith = std::move(currentCollisions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user