Instead of moving down once a collision is detected, it would be better to return in the direction you came from . Thus, you have a guarantee that in the end you should be in a state where there are no collisions, assuming that the initial state did not have collisions.
We need to figure out how much we need to reduce (scale) v
to place it at the intersection of objects. The abbreviation v
will have the correct magnitude, so if we move backward in the -v
direction by this magnitude, we will no longer intersect.
Suppose the intersection consists of the x_intersection
and a y_intersection
. To find out how much we need to move backwards so as not to intersect anymore, we need to scale the original vector v = (v_x, v_y)
. If x_intersection
is a smaller intersection, then we scale v
to x_intersection / v_x
and return our object back to -v * x_intersection / v_x
. This means that we are returning to -(x_intersection, x_intersection * v_y/v_x)
. If y_intersection
is a smaller intersection, then we scale v
to y_intersection / v_y
and move our object back to -v * y_intersection / v_y = -(y_intersection * v_x/v_y, y_intersection)
.
So, I would say that the steps in your algorithm could be:
- Move an object using some displacement vector
v
- Check all conflicts.
If a collision occurs
For all collision objects, find the minimum scaling v
, with which we will need to go back. This scaling can calculate at least two relationships
given v = (v_x, v_y) min_i = min(x_intersection / v_x, y_intersection / v_y)
Find the minimum scaling ratio for all objects.
min_o = min(min_i) for all i
Move the object back in the direction of the vector obtained by scaling the direction of negative movement with a minimum ratio. This is v2 = (min_o*-v)
, where v2
is the vector we use to move backward.
- Go back to step 2
For example: first select w
:

Then select u2
:

Done:

source share