0
\$\begingroup\$

I have a 2-part question:

1: I have 2 rectangles, A and B. B is a wall and A is moving. My simple logic here is every time A moves, it moves based on some (x,y) offset and then checks if it collided with something. If it is colliding with something, roll back bit by bit in the opposite direction until it is not colliding anymore.

The problem here is if A moves in large chunks, it might skip over B entirely.

The intended behavior is to find out where A should be when it first touched one of B's faces and then roll back to that point and apply collision resolution.

2: What if B is moving as well?

What I'm currently doing to side step this issue is to create large enough collision boxes and make sure moving objects do not exceed some maximum. This approach seems like it will be limiting in the future.

I assume there is a mathematical way to solve this but I wasn't able to find any answers from my searches. Any tips/suggestions are greatly appreciated.

Thanks!

\$\endgroup\$
  • 1
    \$\begingroup\$ Try searching for key phrases like "minimum translation vector" or "time of collision / impact / first contact" (each ways of calculating what you call the "rollback point"), "tunnelling" (the problem of skipping over narrow collisions with fast objects), and "continuous collision detection / swept collision detection" (strategies to detect & stop tunnelling without making the colliders too big / the speeds & timesteps too small). I think all the answers you need are already out there, you might just be missing the usual vocabulary for describing the situation to find them. \$\endgroup\$ – DMGregory Feb 14 at 12:41
0
\$\begingroup\$

What you're looking for is called swept or dynamic AABB collision detection.

When dealing with a static and a dynamic (moving) object, you need to take the velocity of the latter in both x and y axes and divide the distance from the static rectangle on the axes by them. Then choose the one that's lower and it should be the time it takes for the rectangle to reach the static one:

if moving.vel.x < 0 then
    distX = static.right - moving.left
else
    distX = static.left - moving.right
endif

if moving.vel.y < 0 then
    distY = static.bottom - moving.top
else
    distY = static.top - moving.bottom
endif

timeX = distX / moving.vel.x
timeY = distY / moving.vel.y

collisionTime = min(timeX, timeY)

moving.move(collisionTime * moving.vel.x, collisionTime * moving.vel.y)

For the dynamic-dynamic case you can use the same thing. You need to realize, that if we were to look at the collision from one of the moving rectangles' local coordinates, then we see that rectangle as a static one (it always stays in (0,0)), and the other is moving a lot faster. So replace the velocity in the pseudo code above with moving1.vel - moving2.vel where moving1 will act as the dynamic rectangle and moving2 is the static one

\$\endgroup\$
  • \$\begingroup\$ I ran into a problem: I move diagonally up-left and hit a the middle of a wall. The algorithm will do static.right - moving.left because I'm moving left, and static.bottom - moving.top because I'm moving up. The player is hitting the wall from below so the collision is happening more on the bottom face of the wall than the right face. But the player is hitting the middle of the bottom face of the wall. So the algorithm thinks the collision on the x axis happened earlier, since static.right - moving.left will be a large number (since I'm hitting it from the middle)...opposed to the y-axis \$\endgroup\$ – errandel Mar 3 at 8:31

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.