3
\$\begingroup\$

I've been writing this collision detection system using a tutorial from an article I read and I just cannot for the life of me get it to function 100% correctly. Here's the code for starters:

BoundingBox aBox;
aBox.Convert(a);
BoundingBox bBox;
bBox.Convert(b);

Vector2 aMin = aBox.GetTopLeft();
Vector2 aMax = aBox.GetBotRight();
Vector2 bMin = bBox.GetTopLeft();
Vector2 bMax = bBox.GetBotRight();

Vector2 minDistance;

float left = (bMin.x - aMax.x);
float right = (bMax.x - aMin.x);
float top = (bMin.y - aMax.y);
float bottom = (bMax.y - aMin.y);

// Check for intersection internally
if (left > 0 || right < 0) return;
if (top > 0 || bottom < 0) return;

// Find the minDistance
if (abs(left) < right)
    minDistance.x = left;
else
    minDistance.x = right;

if (abs(top) < bottom)
    minDistance.y = top;
else
    minDistance.y = bottom;

// Null axis with biggest value
if (abs(minDistance.x) < abs(minDistance.y))
    minDistance.y = 0;
else
    minDistance.x = 0;

The problem right now is that the character is fine walking and hugging the top of a block and the bottom of a block, but once he has to walk UP two blocks, he gets stuck in between them. Coincidentally, walking down works perfectly fine. Just wondering if anyone has a solution to this problem, it would be much appreciated!

Here's a gif to better display the problem:

enter image description here

\$\endgroup\$
1
\$\begingroup\$

I think what is happening is this:

+---+
| A |
+---+
| B |P (player)
+---+
(A, B are wall "blocks")

When the player is attempting to walk to the top-left, and run the collision resolution with blocks A then B, this is what happens:

+\--+
| A |  ----- "A: You're hitting me from below! Go left!"
+--\+
    \P

 \
  \
+--\+
| B \P ----- "B: You're hitting me from the right! Go up!"
+---+

But since you deal with A first, you "listen to" it (go left), and by the time you get to B and attempt to move left, you get stopped dead.

Notice that if you had done this in the reverse order (B then A) it would have worked, which explains why this bug appears only if you're moving up and not down.

Solution

I think there may be many ways to solve this, but one simple method is this:

  • Run collision detection (not resolution) using the original motion vector, on all obstacles in the vicinity (e.g. moving top-left, A says "no", B says "no")
  • Since we're moving top-left, try moving top-only and left-only, again running full collision detection:
    • Top: A says "yes", B says "yes"
    • Left: A says "yes", B says "no"

Since moving to the top works, we'll do that.

Note also that this is a method that only works when everything is AABB - all your walls are horizontal/vertical and so on. In the general case, such as when you have diagonal walls, you will need to work out which way the walls go, in order to "slide along" them.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.