I'm making an RPG game where players and enemies can collide with walls. Right now it pushes the player off the wall when he tries to 'go through' it. However, I detect which way he should be pushed based on his current direction. This means that enemies can still push him through walls. Also if the player moves diagonally, detection doesn't work properly. This is a problem...
I'm using SFML and these Collison-Detection methods: https://github.com/LaurentGomila/SFML/wiki/Source:-Simple-Collision-Detection-for-SFML-2
Specifically I'm using this method:
bool BoundingBoxTest(const sf::Sprite& Object1, const sf::Sprite& Object2)
{
OrientedBoundingBox OBB1 (Object1);
OrientedBoundingBox OBB2 (Object2);
// Create the four distinct axes that are perpendicular to the edges of the two rectangles
sf::Vector2f Axes[4] = {
sf::Vector2f (OBB1.Points[1].x-OBB1.Points[0].x,
OBB1.Points[1].y-OBB1.Points[0].y),
sf::Vector2f (OBB1.Points[1].x-OBB1.Points[2].x,
OBB1.Points[1].y-OBB1.Points[2].y),
sf::Vector2f (OBB2.Points[0].x-OBB2.Points[3].x,
OBB2.Points[0].y-OBB2.Points[3].y),
sf::Vector2f (OBB2.Points[0].x-OBB2.Points[1].x,
OBB2.Points[0].y-OBB2.Points[1].y)
};
for (int i = 0; i<4; i++) // For each axis...
{
float MinOBB1, MaxOBB1, MinOBB2, MaxOBB2;
// ... project the points of both OBBs onto the axis ...
OBB1.ProjectOntoAxis(Axes[i], MinOBB1, MaxOBB1);
OBB2.ProjectOntoAxis(Axes[i], MinOBB2, MaxOBB2);
// ... and check whether the outermost projected points of both OBBs overlap.
// If this is not the case, the Seperating Axis Theorem states that there can be no collision between the rectangles
if (!((MinOBB2<=MaxOBB1)&&(MaxOBB2>=MinOBB1)))
{
return false;
}
}
return true;
}
Note that the method only checks if the sprites collide, not how or where they collide. I don't know how exactly the collision detection works, I've tried printing out the OBB values but they're nonsensical to me.
Should I somehow modify the function, or is there another way of doing collision direction detection? I'm stuck here.
UPDATE
I managed to actually check for which direction the player was colliding with the wall. I have a really odd problem now: It only works properly on the last wall I place.
- I have 4 booleans (canWalkUp, canWalkDown, canWalkLeft, canWalkRight) to check for if the player is holding down both left and right, or up and down - so they don't negate each other. This prevents wonky movement.
- I also have 4 booleans to check if the player is currently colliding with a wall.
The code which handles player-boundary collision is as follows:
void EventHandler::collisionPlayerBoundary(std::shared_ptr<Entity> player, std::shared_ptr<Entity> boundary)
{
std::vector<sf::Vector2f> distances = Collision::BoundingBoxDistance(player->sprite, boundary->sprite);
float pushSpeed = 75;
if(distances.at(0).y < 20) //push left!
{
std::cout << "pushing left" << std::endl;
player->pushX = -pushSpeed;
player->canWalkRight = false;
player->collidingRight = true;
}
if(distances.at(1).y < 20) //push down!
{
std::cout << "pushing down" << std::endl;
player->pushY = pushSpeed;
player->canWalkUp = false;
player->collidingUp = true;
}
if(distances.at(0).x < 20) //push right!
{
std::cout << "pushing right" << std::endl;
player->pushX = pushSpeed;
player->canWalkLeft = false;
player->collidingLeft = true;
}
if(distances.at(2).x < 20) //push up!
{
std::cout << "pushing up" << std::endl;
player->pushY = -pushSpeed;
player->canWalkDown = false;
player->collidingDown = true;
}
}
distances.at(2).x
a typo? There only seem to be two Vector2f objects stored in the std::vector so I assume you are trying to access index 1 and not 2 for the vertical movement (as with your code for pushing down). \$\endgroup\$