Simple 3D Physics with XNA

XNA Lesson 3 -- Difficulty: Easy - Moderate

June 28th, 2007 -- Simple 3D Physics with XNA

Update (08-31-07): There is a 3D Physics sample now available for download. It has improved physics over what is taught in this lesson. The physics in this lesson are less accurate than newtonian based physics and this sample has difficulty dealing with combining multiple vectors or having gravity in different directions. This sample is however very easy to understand for beginners, and is still a good start. On with the lesson....

Because XNA has no built in physics, some of it can get pretty difficult. Fortunately for some things it is a breeze. Here are some simple, quick physics snippets for you beginners that should let you give gravity and basic movement to your objects.

Just one simple function should suffice for a small example. For this example we'll assume that the object we're updating movement for is of a simple class called Entity, which has a position, rotation, and linear velocity.

public class Entity
{
    Vector3 position = Vector3.Zero;
    Matrix rotation = Matrix.Identity;
    Vector3 velocity = Vector3.Zero;
    
   
public Entity()
    {
    }

    public Update( GameTime gameTime )
    {
        // The Vector3 in the 3rd parameter is our gravity vector, standard 9.8m/s/s.
        ApplyGravity( gameTime, new Vector3(0.0f, -9.8f, 0.0f) );

        ApplyMovement( gameTime );

        ApplyRotations( gameTime );
    }

    public void ApplyGravity( GameTime gameTime, Vector3 position, Vector3 gravity )
    {
        // Move position, based on gravity over time
        this.velocity += gravity * gameTime.ElapsedGameTime.Milliseconds;

        // Apply some resistance here, to give the entity a terminal velocity, and slow them down over
        // time. 0.1f is the key number here. It signifies 10%, which means that this objects velocity
        // will decrease by 10% per second.

        this.velocity *= (1 - ( 0.1f * gameTime.ElapsedGameTime.Milliseconds ));

        // Now that the object's velocity has been updated, update its position accordingly
        this.Position += this.velocity;
    }

    public void ApplyMovement( GameTime gameTime )
    {
        // Strafe, 'amount' would simply be a float value from the gamepad or mouse,
        // and if you wanted to use keyboard, then amount would be a speed modifier and you would
        // also want to multiply by milliseconds as keyboards are digital inputs, not analog.
        this
.position += this.rotation.Right * amount;

        // Jump
        this
.position += this.rotation.Up * amount;

        // Walk
        this
.position += this.rotation.Forward * amount;
    }


    public void ApplyRotations( GameTime gameTime )
    {
        // Pitch
        this
.rotation *= Matrix.CreateFromAxisAngle(this.rotation.Right * radians);

        // Yaw
        this
.rotation *= Matrix.CreateFromAxisAngle(this.rotation.Up * radians);

        // Yaw around world UP axis, this is usually preferred in any game that has gravity
        // Space simulators would use the above YAW method, most standard 3D games will use something
        // like this for Yaw.
        this
.rotation *= Matrix.CreateRotationY(radians);

        // Roll
        this
.rotation *= Matrix.CreateFromAxisAngle(this.rotation.Forward * radians);
    }

}

So now you have an entity that is affected by gravity, has a simulated wind resistance, and velocity. To get your player moving around the game you'd simply need to use input from the mouse/keyboard/gamepad to increase speed and rotate the player. These aren't exact newtonian physics, however they'll suffice for most simple 3d games.

Next