1
\$\begingroup\$

I've already implemented collision detection in my game loosely following this tutorial, which works great, but I realized there's one major flaw.
The player and the enemies are circles, while the obstacles can be either segments or polygons or circles.
Now, let's say I have segment A from point (100, 100) to point (300, 100) and segment B from point (100, 200) to point (300, 100), which means they form an acute angle, and player has it center in point (100, 125), with a radius of 25.
If player starts moving right, it will eventually collide against segment B. My method checkCollisions() will return a vector, but if I apply that vector on player, it will be moved up and left, and will overlap segment A.
If I call checkCollisions() a second time, player will be pushed down and collide again with segment B, so recursive invocations aren't a solution. Any ideas?

Here's a picture to explain: Here's a picture to explain The g->n vector direction is along the bisector of the two little vectors, but how do I find the length?

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

I think iterative solving may help.

The concept here is that you will solve several times each frame, but apply only part of the vector returned by checkCollisions() in each frame. The first solve attempt might start by applying the full collision response vector, because that will work fine in simple cases. If there are still intersections after that, you don't want to just bounce back to the original position. To avoid that, later iterations apply only a fraction of the response vector returned by checkCollisions(). To help the solution converge, the fraction is reduced for each iteration.

I know nothing about ActionScript, but here's some really terrible pseudo-code:

collisionResponseFactor = 1

for (i = 0; i < 20; ++i)
    responseVector = checkCollisions (player)
    player.position = player.position + responseVector * collisionResponseFactor
    collisionResponseFactor *= 0.8
\$\endgroup\$
  • \$\begingroup\$ But the result will not be pixel-perfect, right? And it looks quite slow... \$\endgroup\$ – Riccardo Vailati Mar 18 '14 at 9:37
  • \$\begingroup\$ Well, it's not perfect but 10 iterations are enough to produce an accuracy of about 5px... I hope it won't affect speed. \$\endgroup\$ – Riccardo Vailati Mar 19 '14 at 9:53
0
\$\begingroup\$

You can just sum multiple collision response vectors. The contradictory elements will cancel each other out and the resulting vector will just be aimed out as expected. Remember to normalize and rescale by the correct magnitude after summing.

EDIT (After OP added image): To handle that particular problem, you have to find the unique position at which the circle is touching the line segment AB and CD.

You'll need to solve A + (B-A) * t1 + r * n1 = C + (D-C) * t2 + r * n2 where the capital letters are the points in your diagram, r is the radius of the circle, n1 is the unit length collision normal of the quadrilateral, n2 is the same for the triangle, t1 is a real value in [0,1] that represents "how far along" the vector AB the desired point of contact is and t2 is the same for the vector CD. Only t1 and t2 are unknown and since everything except the t's and r are vectors, we have 2 equations (one for x, one for y) in the unknowns. Once you solve for either t, you can plug in everything into the corresponding side of the equation above, which will give you the desired circle position.

\$\endgroup\$
  • \$\begingroup\$ What do you mean with "correct magnitude"? \$\endgroup\$ – Riccardo Vailati Mar 18 '14 at 9:34
  • \$\begingroup\$ I mean that after you sum, you'll have a vector whose magnitude doesn't make physical sense. So you need to scale it to be the correct length according to however you're solving for collision resolution. \$\endgroup\$ – Drew Cummins Mar 18 '14 at 16:55

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.