Write a post
Published Jan 12, 2017Last updated Jan 16, 2017

Simple Physics for Game Programming: Circular Collisions & Movement (Part 1 of 2)

Simple Physics for Game Programming: Circular Collisions & Movement (Part 1 of 2)

Let's Do Physics!

How can I program Mario to jump on an enemy or a car to bounce off of another car? This tutorial will show you how, using the simple physics simulations to handle collision detection (if an object has collided with another) and the response (how it should bounce).

Prerequisites

This tutorial assumes you have at least a basic level of programming knowledge and focuses on the concepts behind simulating physical movement.

While this tutorial is in C#, the concepts can be applied in any language.

First things first

Before we can have movement, we need objects that can move (typically called an "entity"). These entities have to know a few things:

  1. Where they are now (Position)
  2. Where they are going (Velocity)
  3. How big they are (Size/Radius)
  4. How heavy they are (Mass).

In order to do this easily, we can create two classes to help us:

public class Vector2D
{
    public float X;
    public float Y;
    
    public Vector2D( float x, float y )
    {
        this.X = x;
        this.Y = y;
    }
}

public class Entity
{
    public Vector2D Position;
    public Vector2D Velocity;
    public float Radius;
    public float Mass;

    public Entity( Vector2D pos, Vector2D vel, float radius, float mass )
    {
        this.Position = pos;
        this.Velocity = vel;
        this.Radius = radius;
        this.Mass = mass;
    }
}

Making The Math Easier

When working with this 2D Vector class, instead of adding, subtracting, multiplying, or dividing each x-y component every time, it will be nice to work with them as a unit. So let's add some nice code to help us by overloading the arithmetic operators and adding some extra methods as well. This way, we can do things like Vector2D result = vecA - vecB;

public class Vector2D
{
    // ...
    
    public static Vector2D operator +( Vector2D value1, Vector2D value2 )
    {
        value1.X += value2.X;
        value1.Y += value2.Y;
        return value1;
    }

    public static Vector2D operator -( Vector2D value1, Vector2D value2 )
    {
        value1.X -= value2.X;
        value1.Y -= value2.Y;
        return value1;
    }

    public static Vector2D operator *( Vector2D value1, Vector2D value2 )
    {
        value1.X *= value2.X;
        value1.Y *= value2.Y;
        return value1;
    }

    public static Vector2D operator *( Vector2D value, float scaleFactor )
    {
        value.X *= scaleFactor;
        value.Y *= scaleFactor;
        return value;
    }

    public static Vector2D operator *( float scaleFactor, Vector2D value )
    {
        value.X *= scaleFactor;
        value.Y *= scaleFactor;
        return value;
    }

    public static Vector2D operator /( Vector2D value1, Vector2D value2 )
    {
        value1.X /= value2.X;
        value1.Y /= value2.Y;
        return value1;
    }

    public static Vector2D operator /( Vector2D value1, float divider )
    {
        float factor = 1 / divider;
        value1.X *= factor;
        value1.Y *= factor;
        return value1;
    }
    
    // Get the length of the vector
    public float Length()
    {
        return (float)Math.Sqrt( ( X * X ) + ( Y * Y ) );
    }
    
    // Make the vector a length of 1
    public void Normalize()
    {
        float val = 1.0f / Length();
        X *= val;
        Y *= val;
    }
}

Physical Movement

For any movement to occur in the physical world, e.g. a falling apple, time has to pass. To simulate this movement based on time, we can do the same in code by adding a new method called Step() to the Entity class that takes a certain amount of time as its parameter.

Knowing the formula for an object's movement: p' = p + v*t

And using our handy Vector2D class, we can move an entity's Position by its Velocity * Time.

public class Entity
{
    // ...
    
    public void Step( float time )
    {
        this.Position = this.Velocity * time;
    }
}

So far, so good? Okay.

Now, we don't have collisions yet, but let's try putting this together into a two-dimensional world full of bubbles.

public class World
{
    public List<Entity> Bubbles;
    
    public World()
    {
        Bubbles = new List<Entity>();
    }
    
    public void Step( float time )
    {
        foreach( var bubble in Bubbles )
        {
            bubble.Step( time );
        }
    }
    
    public static World GiveMeRandomBubbles( int numBubbles = 10, int maxX = 1000, int maxY = 1000 )
    {
        var world = new World();
        var random = new Random();
        for( int i = 0; i < numBubbles; i++ )
        {
            Vector2D pos = new Vector2D( (float)random.Next( maxX ), (float)random.Next( maxY ) );
            Vector2D vel = new Vector2D( (float)( random.Next( maxX ) - maxX / 2 ), (float)( random.Next( maxY ) - maxY / 2 ) );
            float radius = 50;
            float mass = 1.0f;
            world.Bubbles.Add( new Entity( pos, vel, radius, mass ) );
        }
        return world;
    }
}

And now we can call GiveMeRandomBubbles() to get a world full of bubbles moving in random directions! Not only that, we can use that world to call its Step() method and move the bubbles in their virtual world.

Wrapping up

That's it for this part. To view the sample code, click here.

Next, we will dive into simulating collisions and updating entities' velocities based those collisions so stay tuned!

Discover and read more posts from Raphael Mun
get started
Enjoy this post?

Leave a like and comment for Raphael