Opposite Force to Apply to a Collided Rigid Body?

Posted by Milo on Game Development See other posts from Game Development or by Milo
Published on 2012-11-11T15:13:35Z Indexed on 2012/11/11 17:15 UTC
Read the original article Hit count: 311

I'm working on the physics for my GTA2-like game so I can learn more about game physics.

The collision detection and resolution are working great.

I'm now just unsure how to compute the force to apply to a body after it collides with a wall.

My rigid body looks like this:

/our simulation object
class RigidBody extends Entity
{
  //linear
  private Vector2D velocity = new Vector2D();
  private Vector2D forces = new Vector2D();
  private float mass;
  private Vector2D v = new Vector2D();

  //angular
  private float angularVelocity;
  private float torque;
  private float inertia;

  //graphical
  private Vector2D halfSize = new Vector2D();
  private Bitmap image;

  private Matrix mat = new Matrix();
  private float[] Vector2Ds = new float[2];
  private Vector2D tangent = new Vector2D();
  private static Vector2D worldRelVec = new Vector2D();
  private static Vector2D relWorldVec = new Vector2D();
  private static Vector2D pointVelVec = new Vector2D();
  private static Vector2D acceleration = new Vector2D();


  public RigidBody()
  {
      //set these defaults so we don't get divide by zeros
      mass = 1.0f;
      inertia = 1.0f;
      setLayer(LAYER_OBJECTS);
  }

    protected void rectChanged()
    {
        if(getWorld() != null)
        {
            getWorld().updateDynamic(this);
        }
    }

  //intialize out parameters
  public void initialize(Vector2D halfSize, float mass, Bitmap bitmap)
  {
      //store physical parameters
      this.halfSize = halfSize;
      this.mass = mass;
      image = bitmap;
      inertia = (1.0f / 20.0f) * (halfSize.x * halfSize.x) * (halfSize.y * halfSize.y) * mass;

      RectF rect = new RectF();
      float scalar = 10.0f;
      rect.left = (int)-halfSize.x * scalar;
      rect.top = (int)-halfSize.y * scalar;

      rect.right = rect.left + (int)(halfSize.x * 2.0f * scalar);
      rect.bottom = rect.top + (int)(halfSize.y * 2.0f * scalar);
      setRect(rect);


  }

  public void setLocation(Vector2D position, float angle)
  {
      getRect().set(position.x,position.y, getWidth(), getHeight(), angle);
      rectChanged();
  }

  public Vector2D getPosition()
  {
      return getRect().getCenter();
  }

  @Override
  public void update(float timeStep)
  {
      doUpdate(timeStep);
  }

  public void doUpdate(float timeStep)
  {
      //integrate physics
      //linear
      acceleration.x = forces.x / mass;
      acceleration.y = forces.y / mass;
      velocity.x += (acceleration.x * timeStep);
      velocity.y += (acceleration.y * timeStep);
    //velocity = Vector2D.add(velocity, Vector2D.scalarMultiply(acceleration, timeStep));
      Vector2D c = getRect().getCenter();
      v.x = getRect().getCenter().getX() + (velocity.x * timeStep);
      v.y = getRect().getCenter().getY() + (velocity.y * timeStep);
      setCenter(v.x, v.y);
      forces.x = 0; //clear forces
      forces.y = 0;



      //angular
      float angAcc = torque / inertia;

      angularVelocity += angAcc * timeStep;
      setAngle(getAngle() +  angularVelocity * timeStep);  
      torque = 0; //clear torque


  }


  //take a relative Vector2D and make it a world Vector2D
  public Vector2D relativeToWorld(Vector2D relative)
  {
      mat.reset();

      Vector2Ds[0] = relative.x;
      Vector2Ds[1] = relative.y;

      mat.postRotate(JMath.radToDeg(getAngle()));
      mat.mapVectors(Vector2Ds);

      relWorldVec.x = Vector2Ds[0];
      relWorldVec.y = Vector2Ds[1];
      return relWorldVec;
  }

  //take a world Vector2D and make it a relative Vector2D
  public Vector2D worldToRelative(Vector2D world)
  {
      mat.reset();

      Vector2Ds[0] = world.x;
      Vector2Ds[1] = world.y;

      mat.postRotate(JMath.radToDeg(-getAngle()));
      mat.mapVectors(Vector2Ds);

      worldRelVec.x = Vector2Ds[0];
      worldRelVec.y = Vector2Ds[1];
      return worldRelVec;
  }

  //velocity of a point on body
  public Vector2D pointVelocity(Vector2D worldOffset)
  {
      tangent.x = -worldOffset.y;
      tangent.y = worldOffset.x;

      pointVelVec.x = (tangent.x * angularVelocity) + velocity.x;
      pointVelVec.y = (tangent.y * angularVelocity) + velocity.y;
      return pointVelVec;
  }

  public void applyForce(Vector2D worldForce, Vector2D worldOffset)
  {
      //add linear force
      forces.x += worldForce.x;
      forces.y += worldForce.y;
      //add associated torque
      torque += Vector2D.cross(worldOffset, worldForce);
  }

  @Override
  public void draw( GraphicsContext c)
  {
      c.drawRotatedScaledBitmap(image, getPosition().x, getPosition().y,
              getWidth(), getHeight(), getAngle());
  }

    public Vector2D getVelocity()
    {
        return velocity;
    }

    public void setVelocity(Vector2D velocity)
    {
        this.velocity = velocity;
    }

}

The way it is given force is by the applyForce method, this method considers angular torque.

I'm just not sure how to come up with the vectors in the case where: RigidBody hits static entity RigidBody hits other RigidBody that may or may not be in motion.

Would anyone know a way (without too complex math) that I could figure out the opposite force I need to apply to the car?

I know the normal it is colliding with and how deep it collided.

My main goal is so that say I hit a building from the side, well the car should not just stay there, it should slowly rotate out of it if I'm more than 45 degrees. Right now when I hit a wall I only change the velocity directly which does not consider angular force.

Thanks!

© Game Development or respective owner

Related posts about java

Related posts about physics