docflabby's picture

Simple Physics and AABB Collisions

Please note its come to my attention the collision response doesnt work properly (everything else is good though)

This is a repost from my forums, that I thought you guys here might be interested in as it covers basic physics and uses OpenTK for the graphics!

Having tried out a number of physics engines for Subspace2 none of them quite meet the performance demands I require. The biggest issue is that many of the engines support alot of features that I'm not interested in at the moment such as collisions with rotating objects. I want a much more simpler system (arcade style). Unfortunately this whole area I'm woefully lacking knowledge in in.

Fortunately after ALOT of research I found a tutorial http://gafferongames.com/game-physics/ that started to make some sence to me. and from the knowledge i've learnt in the tutorial i have begun to build my own engine based on the work of many others. I still have plans to use other physics engines for other game modes.

The subspace world only contains AABB (squares or rectangles) collision objects.

Collision handling and physics are usually done separately. In my engine I move all the objects first using numerical integration and process the collisions afterwards by looking for intersecting objects (this is a pretty standard way of doing things). So there are 2 district phases. That are repeated around 60times/second

while (GameLoop)
   Integrate
   CollisionCheckResponse
end

1. Physics

As objects in subspace have no mass there are only 2 equations governing the movement of objects.
position = velocity * time
velocity = acceleration * time

A simple Eular Integrator can be used to calculate your new position for a change in time.

public void EularIntergrate(float deltaTime)
  {
    position += velocity * deltaTime;
    velocity += acceleration * deltaTime;
  }

the problem with Eular Integration is its horrible inaccurate which can lead to nasty quirks appearing in the game. Therefore after reading this article http://gafferongames.com/game-physics/integration-basics/ I managed to implement a RK4 (Runge-Kutta Integration) integrator.

Thus the Physics part of the engine is now complete, we have a decent integrator which is producing the accurate simulation we require.

2. Collisions

The First step in a collision detection is to detect if an object has collided with another (wow big surpise)
In the example i'm using I test every object against each other, which is very inefficient, though the use of spacial partitioning and/or broad phase the number of tests can be minimised. ( http://stackoverflow.com/questions/414553/broad-phase-collision-detectio...)

The test if two AABB bodies intersect is pretty simple: Min refers to the top left corner, Max refers to the bottom right corner.

 
public bool Intersects(aabb other)
        {
            if (this.Max.X < other.Min.X || 
                this.Max.Y < other.Min.Y || 
                this.Min.X > other.Max.X || 
                this.Min.Y > other.Max.Y) 
            {
                return false;
            }
    return true;
}

Following testing for intersections we will have a list of objects that are colliding, we are now ready to create responses to the collisions.
In order to create accurate responses we need to find the collision vector, which can be obtained from the Minimum Translation Distance or MTD Vector.

This is more complex to calculate:

public Vector2 minimumTranslation(aabb other)
        {
            Vector2 amin = this.Min;
            Vector2 amax = this.Max;
            Vector2 bmin = other.Min;
            Vector2 bmax = other.Max;
 
            Vector2 mtd = new Vector2();
 
            float left = (bmin.X - amax.X);
            float right = (bmax.X - amin.X);
            float top = (bmin.Y - amax.Y);
            float bottom = (bmax.Y - amin.Y);
 
            // box dont intersect   
            if (left > 0 || right < 0) throw new Exception("no intersection");
            if (top > 0 || bottom < 0) throw new Exception("no intersection");
 
            // box intersect. work out the mtd on both x and y axes.
            if (Math.Abs(left) < right)
                mtd.X = left;
            else
                mtd.X = right;
 
            if (Math.Abs(top) < bottom)
                mtd.Y = top;
            else
                mtd.Y = bottom;
 
            // 0 the axis with the largest mtd value.
            if (Math.Abs(mtd.X) < Math.Abs(mtd.Y))
                mtd.Y = 0;
            else
                mtd.X = 0; 
            return mtd;
        }

Now we have the MTD we can use it to move our objects out of collision, and correct there velocities to ensure they should not collide next time

mtd = this.minimumTranslation(ab);
this.position += mtd ;
if (interv.X != 0)
{
this.velocity.X = -this.velocity.X ; //* bounce factor\
}
else if (interv.Y != 0)
{
this.velocity.Y = -this.velocity.Y;//* bounce factor
}

This is a repost of http://www.ssforum.net/index.php?showtopic=23091
I'm not sure how useful anyone will find it but maybe it will help someone somewhere :p

References
http://gafferongames.com/game-physics/
http://www.gamedev.net/community/forums/topic.asp?topic_id=531478
http://www.gamedev.net/community/forums/topic.asp?topic_id=520224
http://www.deannolan.co.uk/pt/blog/default.aspx?id=23&t=2D-Collision-Det...

Any quite a few other random pages, that I can't remember

Build with OpenTK 0.97
Download Link (was bigger than 512k so i couldn't attach):
http://www.ssforum.net/index.php?app=core&module=attach&section=attach&a...

Keys AWSD
Mouse clicks create another object.

Its quick and messy but gives you enough to play with :)

Inline Images