Search code examples
physicstrigonometrycollision

Calculating 2D resultant forces for vehicles in games


I am trying to calculate the forces that will act on circular objects in the event of a collision. Unfortunately, my mechanics is slightly rusty so i'm having a bit of trouble.

I have an agent class with members

vector position // (x,y)
vector velocity // (x,y)
vector forward // (x,y)  
float radius   // radius of the agent (all circles)
float mass     

So if we have A,B:Agent, and in the next time step the velocity is going to change the position. If a collision is going to occur I want to work out the force that will act on the objects.

I know Line1 = (B.position-A.position) is needed to work out the angle of the resultant force but how to calculate it is baffling me when I have to take into account current velocity of the vehicle along with the angle of collision.

arctan(L1.y,L1.x) is am angle for the force (direction can be determined) sin/cos are height/width of the components

Also I know to calculate the rotated axis I need to use x = cos(T)*vel.x + sin(T)*vel.y y = cos(T)*vel.y + sin(T)*vel.x

This is where my brain can't cope anymore.. Any help would be appreciated.

As I say, the aim is to work out the vector force applied to the objects as I have already taken into account basic physics.

Added a little psudocode to show where I was starting to go with it..

A,B:Agent 

Agent {
    vector position, velocity, front;
    float radius,mass;
}

vector dist = B.position - A.position;
float distMag = dist.magnitude();

if (distMag < A.radius + B.radius) { // collision 
    float theta = arctan(dist.y,dist.x);
    flost sine = sin(theta);
    float cosine = cos(theta);

    vector newAxis = new vector; 
      newAxis.x  = cosine * dist .x + sine * dist .y;
      newAxis.y  = cosine * dist .y - sine * dist .x;

    // Converted velocities
    vector[] vTemp = { 
         new vector(), new vector()         };
    vTemp[0].x  = cosine * agent.velocity.x + sine * agent.velocity.y;
    vTemp[0].y  = cosine * agent.velocity.y - sine * agent.velocity.x;
    vTemp[1].x  = cosine * current.velocity.x + sine * current.velocity.y;
    vTemp[1].y  = cosine * current.velocity.y - sine * current.velocity.x;        

Here's to hoping there's a curious maths geek on stack..


Solution

  • Let us assume, without loss of generality, that we are in the second object's reference frame before the collision.

    Conservation of momentum:

    m1*vx1 = m1*vx1' + m2*vx2'
    m1*vy1 = m1*vy1' + m2*vy2'
    

    Solving for vx1', vy1':

    vx1' = vx1 - (m2/m1)*vx2'
    vy1' = vy1 - (m2/m1)*vy2'
    

    Secretly, I will remember the fact that vx1'*vx1' + vy1'*vy1' = v1'*v1'.

    Conservation of energy (one of the things elastic collisions give us is that angle of incidence is angle of reflection):

    m1*v1*v1 = m1*v1'*v1' + m2*v2'+v2'
    

    Solving for v1' squared:

    v1'*v1' = v1*v1 - (m2/m1)v2'*v2'
    

    Combine to eliminate v1':

    (1-m2/m1)*v2'*v2' = 2*(vx2'*vx1+vy2'*vy1)
    

    Now, if you've ever seen a stationary poolball hit, you know that it flies off in the direction of the contact normal (this is the same as your theta).

    v2x' = v2'cos(theta)
    v2y' = v2'sin(theta)
    

    Therefore:

    v2' = 2/(1-m2/m1)*(vx1*sin(theta)+vy1*cos(theta))
    

    Now you can solve for v1' (either use v1'=sqrt(v1*v1-(m2/m1)*v2'*v2') or solve the whole thing in terms of the input variables).

    Let's call phi = arctan(vy1/vx1). The angle of incidence relative to the tangent line to the circle at the point of intersection is 90-phi-theta (pi/2-phi-theta if you prefer). Add that again for the reflection, then convert back to an angle relative to the horizontal. Let's call the angle of incidence psi = 180-phi-2*theta (pi-phi-2*theta). Or,

    psi = (180 or pi) - (arctan(vy1/vx1))-2*(arctan(dy/dx))
    

    So:

    vx1' = v1'sin(psi)
    vy1' = v1'cos(psi)
    

    Consider: if these circles are supposed to be solid 3D spheres, then use a mass proportional to radius-cubed for each one (note that the proportionality constant cancels out). If they are supposed to be disklike, use mass proportional to radius-squared. If they are rings, just use radius.

    Next point to consider: Since the computer updates at discrete time events, you actually have overlapping objects. You should back out the objects so that they don't overlap before computing the new location of each object. For extra credit, figure out the time that they should have intersected, then move them in the new direction for that amount of time. Note that this time is just the overlap / old velocity. The reason that this is important is that you might imagine a collision that is computed that causes the objects to still overlap (causing them to collide again).

    Next point to consider: to translate the original problem into this problem, just subtract object 2's velocity from object 1 (component-wise). After the computation, remember to add it back.

    Final point to consider: I probably made an algebra error somewhere along the line. You should seriously consider checking my work.