Search code examples
delphimathangle

How to influence 2 angles from 2 animated object?


Hello and thanks in advance for your help

Here is what i have:

  • A 2D Plan where multiple objects are moving randomly.
  • Each object has a position(x,y), and an integer direction (0 to 360).

Here is what i want to achieve:

  1. When 2 objects become close (let say distance < 20 pixel ), i want to make their direction to change so they become more far.
  2. When they become little bit far ( distance 40 to 60 pixel ), i want to change their direction so they become more close.
  3. Between 20 and 40 they follow each other ( but this part i did it easily )
  4. if distance > 60 px they just ignore each other (this part is already ok as well )

I experience some difficulties for point 1 and 2:

  • To compare both angles ( it's ok in simple cases but if one object angle is 359 and the other is 2, i can't find a good way to calculate that their actual direction is close, althought 359 - 2 = 357.
  • To apply a small variation to both objects so they look to influencate each other. Just to notice: if both object's direction are extreamly different they can ignore each other.

for instance, currently i am doing that when objects are too close ( distance < 20 ): self is the current object and b is another object of same type.

self.SetDirection( self.direction - ( b.direction - self.direction ));

And when objects are between 20-60px

self.SetDirection( direction + ( b.direction - self.direction ));

the setdirection method (i know it's ugly, and probably wrong ):

function TBoid.toAngle360(angle: double): double;
begin
  if angle < 0
  then angle := 360 - ( abs(round(angle)) mod 360 )
  else if angle > 360
       then angle := round(angle) mod 360;

  result := angle;
end;   

I would be very thankfull if anyone could help me, give some any explanation or point at my mistakes. I could not find any suitable answer on this site or in google, and i'm weak with trigonometric calculations, angles, radians and all that...

Thanks


Solution

  • More reliable approach is to minimize using angles.

    Instead of angle use velocity components vx and vy (note that vx=v*cos(direction), similar for vy and sin).

    To compare direction similarity, calculate dot product of direction vectors (normalized by their lengths)

    dot = (vx1 * vx2 + vy1 * vy2) / (len1*len2)
    where 
    len1 = Hypot(vx1,vy1)
    

    Dot product has value 1 for collinear vectors, close to 1 for close directions, is 0 for perpendicular vectors, is 1 for anticollinear vectors (note this is equivalent of calculation of angle difference cosine).

    To make mutual influence, apply something like gravity or Coulomb force - object makes a force (hence acceleration) onto another object. So velocity components change.

    For example, you have almost collinear vectors with components vx, vy. Find normal vector N

    nx = -vy
    ny = vx
    

    and add N*coeff to one velocity and -N*coeff to another velocity to make them divergent or convergent (depends on the sign of coeff). Value of coeff calculate correspondingly to distance between objects.