2D OBB collision detection, resolving collisions?

Posted by Milo on Game Development See other posts from Game Development or by Milo
Published on 2012-11-04T04:17:30Z Indexed on 2012/11/04 5:24 UTC
Read the original article Hit count: 429

I currently use OBBs and I have a vehicle that is a rigid body and some buildings.

Here is my update()

private void update()
{

    camera.setPosition((vehicle.getPosition().x * camera.getScale()) - ((getWidth() ) / 2.0f),
            (vehicle.getPosition().y * camera.getScale()) - ((getHeight() ) / 2.0f));



    //camera.move(input.getAnalogStick().getStickValueX() * 15.0f, input.getAnalogStick().getStickValueY() * 15.0f);
    if(input.isPressed(ControlButton.BUTTON_GAS))
    {
        vehicle.setThrottle(1.0f, false);
    }

    if(input.isPressed(ControlButton.BUTTON_BRAKE))
    {
        vehicle.setBrakes(1.0f);
    }

    vehicle.setSteering(input.getAnalogStick().getStickValueX());


    vehicle.update(16.6666f / 1000.0f);

    ArrayList<Building> buildings = city.getBuildings();
    for(Building b : buildings)
    {
        if(vehicle.getRect().overlaps(b.getRect()))
        {
            vehicle.update(-17.0f / 1000.0f);
            break;
        }
    }
}

The collision detection works well. What doesn't is how they are dealt with.

My goal is simple. If the vehicle hits a building, it should stop, and never go into the building. When I apply negative torque to reverse the car should not feel buggy and move away from the building. I don't want this to look buggy.

This is my rigid body class:

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

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

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

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

  //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, getWidth(), getHeight(), angle);
  }

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

  @Override
  public void update(float timeStep)
  {
      //integrate physics
      //linear
      Vector2D acceleration = Vector2D.scalarDivide(forces, mass);
      velocity = Vector2D.add(velocity, Vector2D.scalarMultiply(acceleration, timeStep));
      Vector2D c = getRect().getCenter();
      c = Vector2D.add(getRect().getCenter(), Vector2D.scalarMultiply(velocity , timeStep));
      setCenter(c.x, c.y);
      forces = new Vector2D(0,0); //clear forces

      //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)
  {
      Matrix mat = new Matrix();
      float[] Vector2Ds = new float[2];

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

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

      return new Vector2D(Vector2Ds[0], Vector2Ds[1]);
  }

  //take a world Vector2D and make it a relative Vector2D
  public Vector2D worldToRelative(Vector2D world)
  {
      Matrix mat = new Matrix();
      float[] Vectors = new float[2];

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

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

      return new Vector2D(Vectors[0], Vectors[1]);
  }

  //velocity of a point on body
  public Vector2D pointVelocity(Vector2D worldOffset)
  {
      Vector2D tangent = new Vector2D(-worldOffset.y, worldOffset.x);
      return Vector2D.add( Vector2D.scalarMultiply(tangent, angularVelocity) , velocity);
  }

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

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

}

Essentially, when any rigid body hits a building it should exhibit the same behavior.

How is collision solving usually done?

Thanks

© Game Development or respective owner

Related posts about collision-detection

Related posts about physics