I'm making a platformer and trying to implement swept AABB collision so that an entity's velocity doesn't cause it to skip over something it should collide with from one frame to the next. I'm using this tutorial:
https://www.gamedev.net/resources/_/technical/game-programming/swept-aabb-collision-detection-and-response-r3084I've modified the code from that for SFML usage. It works in the vertical axis, but it doesn't in the horizontal axis. It just doesn't trigger a collision (it doesn't return a value between 0 and 1, which is how a collision is indicated). The code for the function is like so:
float sweptAABB(Character* character, sf::Sprite* world, float& normalx, float& normaly) {
float xInvEntry, yInvEntry;
float xInvExit, yInvExit;
sf::FloatRect worldBox = world->getGlobalBounds();
sf::FloatRect charBox = character->getSprite()->getGlobalBounds();
// find the distance between the objects on the near and far sides for both x and y
if (character->getXVelocity() > 0.0f) {
xInvEntry = worldBox.left - (charBox.left + charBox.width);
xInvExit = (worldBox.left + worldBox.width) - charBox.left;
}
else {
xInvEntry = (worldBox.left + worldBox.width) - charBox.left;
xInvExit = worldBox.left - (charBox.left + charBox.width);
}
if (character->getYVelocity() > 0.0f) {
yInvEntry = worldBox.top - (charBox.top + charBox.height);
yInvExit = (worldBox.top + worldBox.height) - charBox.top;
}
else {
yInvEntry = (worldBox.top + worldBox.height) - charBox.top;
yInvExit = worldBox.top - (charBox.top + charBox.height);
}
// find time of collision and time of leaving for each axis (if statement is to prevent divide by zero)
float xEntry, yEntry;
float xExit, yExit;
if (character->getXVelocity() == 0.0f) {
xEntry = -std::numeric_limits<float>::infinity();
xExit = std::numeric_limits<float>::infinity();
}
else {
xEntry = xInvEntry / character->getXVelocity();
xExit = xInvExit / character->getXVelocity();
}
if (character->getYVelocity() == 0.0f) {
yEntry = -std::numeric_limits<float>::infinity();
yExit = std::numeric_limits<float>::infinity();
}
else {
yEntry = yInvEntry / character->getYVelocity();
yExit = yInvExit / character->getYVelocity();
}
// find the earliest/latest times of collision
float entryTime = std::max(xEntry, yEntry);
float exitTime = std::min(xExit, yExit);
// if there was no collision
if (entryTime > exitTime || (xEntry < 0.0f && yEntry < 0.0f) || xEntry > 1.0f || yEntry > 1.0f) {
normalx = 0.0f;
normaly = 0.0f;
return 1.0f;
}
// if there was a collision
else{
// calculate normal of collided surface
if (xEntry > yEntry) {
if (xInvEntry < 0.0f) {
normalx = 1.0f;
normaly = 0.0f;
}
else {
normalx = -1.0f;
normaly = 0.0f;
}
}
else {
if (yInvEntry < 0.0f) {
normalx = 0.0f;
normaly = 1.0f;
}
else {
normalx = 0.0f;
normaly = -1.0f;
}
}
// return the time of collision
return entryTime;
}
}
Originally it was detecting collision on the horizontal axis, but it was doing so even when there was no collision on the y axis (i.e. the block could be well above the character and it would still stop it as if it was in front of the character) but after implementing the broadphase check (in that article tutorial I linked) that fixed that problem, but now it doesn't detect horizontal collision at all.
Been tinkering for past few days and can't figure out why this is
if needed I can post code from other sections but I get the feeling that this function is the one not working as it triggers in y axis but not x axis. Any insight would be greatly appreciated!