November 25, 2008

Going on Vacation

I’ll be in Vegas for the next few days, so don’t expect a tutorial until after I get back. Enjoy your Thanksgiving!

  • DotNetKicks
  • Digg
  • StumbleUpon
  • del.icio.us
  • Google
  • Reddit
  • Facebook
November 23, 2008

Updated Input Tutorial

The Input Tutorial has been updated to make it compatible with Xbox and Zune, where Enum.GetValues() is not supported. Scroll down to the point in the post where you see the [EDIT] tag. Once finished with the part between the [EDIT] tags, you will need to update the three input devices (Mouse, Keyboard, GamePad) to use the new method in their update functions. If you are having trouble, the MouseDevice in the post has been updated, and the other two in the links have been updated, and all the changes are in the project for the tutorial.

  • DotNetKicks
  • Digg
  • StumbleUpon
  • del.icio.us
  • Google
  • Reddit
  • Facebook
November 16, 2008

XNA Game Engine Tutorial Series #6 - Input

In this tutorial we are going to be building an input system for our engine. This system will support the Xbox 360 game pad, keyboard, and mouse, but could be extended to support most if not all other types of devices (assuming you know how to interface with the device, as XNA doesn’t provide support for any other devices directly).

The structure will be as follows:

InputDevice: The InputDevice class is the base class for input devices. An input device is the interface between the engine/game and the device itself. It keeps track of a state object and provides functions for getting data from the device.

The input devices we will be building are MouseDevice, KeyboardDevice, and GamePadDevice.

First, however, I want to discuss what are called “Generics”. A generic is a way for us to tell C# that our class or function can handle multiple types. A Type is a class that contains info about a class. You can get an object’s Type using MyObject.GetType(). You can get the Type of a class using typeof(ClassName). An example of a function that uses generics is XNA’s “Content.Load()” function. Since it can load multiple data types, it uses a generic to tell what kind of Type it returns. This is why we load textures using , models using , etc. (ie: “Texture2D texture = Content.Load(”Content/TextureName”) ). We tell C# what kind of generics definition we expect using in the class name line. Of course, you could use any or multiple types here, ie: . The generic can then be used like a regular type in the class. Here is an example of doing this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class ExampleClass <T, R>
{
	public T ReturnVariableT()
	{
		T object = new T();
 
		return T;
	}
 
	public R ReturnVariableR()
	{
		R object = new R();
 
		return T;
	}
}

Here is the code for the InputDevice class. It’s not very complex, since all the base class does is maintain a state object.

1
2
3
4
5
6
7
8
// The base input device class. Other input device types will
// inherit from it. The <T> generic allows us to specify what
// type of input device state it manages. (MouseState, etc.)
public abstract class InputDevice <T> : Component
{
    // The State object of type T specified above
    public abstract T State { get; }
}

We will also need to create two classes: an event argument class and event handler class, which will be used for events relating to input (like button pressed, button up, etc).

Before we get to that, however, I want to quicly discuss events. An event is exactly what it sounds like, we can define events that other classes can “hook”, by specifying a method for C# to call when the event is triggered by the owner of the event.

We create an event like this:

1
public event EventHandler ExampleEvent;

The “EventHandler” part of the declaration tells C# what kind of method is allowed to hook an event. EventHandler is just a delegate that accepts a few specific arguments. A delegate, in this case, is just a way of defining the type of method we want. For example, an event that specifies the EventHandler event handler will only be hooked by methods of the following format:

1
2
3
void FunctionToCallWhenEventIsFired(object sender, EventArgs e)
{
}

We would then hook it like this:

1
EventOwner.ExampleEvent += new EventHandler(FunctionToCallWhenEventIsFired);

Now, if EventOwner fires ExampleEvent, FunctionToCallWhenEventIsFired would be called and passed the object that called it as “object sender” and the data about the event in “EventArgs e”.

We can create our own class that inherits from “EventArgs” to pass our own data to the event handler. We would then need to create our own EventHandler delegate that accepts the custom event arguments class. For example, our event arguments class and event handler class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// An input device event argument class that can handle events
// for several types of input device. "O" specified what type
// of object the event was triggered by (Key, Button,
// MouseButton, etc). "S" specifies the type of state the
// event provides (MouseState, KeyboardState, etc.)
public class InputDeviceEventArgs<O, S> : EventArgs
{
    // The object of type O that triggered the event
    public O Object;
 
    // The input device that manages the state of type S that
    // owns the triggered object
    public InputDevice<S> Device;
 
    // The state of the input device of type S that was triggered
    public S State;
 
    // Constructor takes the triggered object and input device
    public InputDeviceEventArgs(O Object, InputDevice<S> Device)
    {
        this.Object = Object;
        this.Device = Device;
        this.State = ((InputDevice<S>)Device).State;
    }
}
 
// An input device event handler delegate. This defines what type
// of method may handle an event. In this case, it is a void that
// accepts the specified input device arguments
public delegate void InputEventHandler<O, S>(object sender, 
    InputDeviceEventArgs<O, S> e);

So, lets start with KeyboardDevice. Here’s the class definition, as you can see we specify that KeyboardDevice keeps track of a KeyboardState object.

1
2
3
4
5
6
7
8
using Microsoft.Xna.Framework.Input;
using System;
 
namespace Innovation
{
    // An input device that manages the Keyboard and KeyboardState
    public class KeyboardDevice : InputDevice<KeyboardState>
    {

Now we are going to add several members, properties, and events. They should be self explanatory:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// The last and current KeyboardStates
KeyboardState last;
KeyboardState current;
 
// The keys that were pressed in the current state
Keys[] currentKeys;
 
// Public properties for the above members
public override KeyboardState State { get { return current; } }
public Keys[] PressedKeys { get { return currentKeys; } }
 
// Events for when a key is pressed, released, and held. This
// event can be handled by our InputEventHandler class.
public event InputEventHandler<Keys, KeyboardState> KeyPressed;
public event InputEventHandler<Keys, KeyboardState> KeyReleased;
public event InputEventHandler<Keys, KeyboardState> KeyHeld;

Now the constructor:

1
2
3
4
5
6
7
// Constructor sets up the current state and updates for the
// first time
public KeyboardDevice()
{
    current = Keyboard.GetState();
    Update();
}

Now the Update() method. We start by updating the keyboard states:

1
2
3
4
5
6
7
8
9
10
public override void Update()
{
    // Set the last state to the current one and update the
    // current state
    last = current;
    current = Keyboard.GetState();
 
    // Set the currently pressed keys to the keys defined in
    // the current state
    currentKeys = current.GetPressedKeys();

Now we will check if our events need to be fired, then fire them if neccessary. We will write the functions that check for the various cases (button up, down, etc.).

[EDIT: Added on 11/23/2008, read the Update Notes]

First we need to create a class that will allow us to enumerate over the values of an enum, in a foreach loop. We can do this on Windows using Enum.GetValues(), but this isn’t provided in the .Net Compact Framework on Xbox and Zune, so we need to create our own. Add a new static class called Util, and add the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
using System;
using System.Collections.Generic;
using System.Reflection;
 
namespace Innovation
{
    public static class Util
    {
        public static List<T> GetEnumValues<T>()
        {
            Type currentEnum = typeof(T);
            List<T> resultSet = new List<T>();
 
            if (currentEnum.IsEnum)
            {
                FieldInfo[] fields = currentEnum.GetFields(BindingFlags.Static | BindingFlags.Public);
                foreach (FieldInfo field in fields)
                    resultSet.Add((T)field.GetValue(null));
            }
            else
                throw new ArgumentException("The argument must of type Enum or of a type derived from Enum", "T");
 
            return resultSet;
        }
    }
}

Now we can go through the values of an enum like this:

1
2
3
4
5
Enum ExampleEnum { One, Two, Three };
 
foreach(ExampleEnum value in Util.GetEnumValues<ExampleEnum>()
{
}

[END EDIT]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    // For every key on the keyboard...
    foreach (MouseButtons button in Util.GetEnumValues<MouseButtons>())
    {
        // If it is a new key press (this is the first frame
        // it is down), trigger the corresponding event
        if (WasKeyPressed(key))
            if (KeyPressed != null)
                KeyPressed(this, new InputDeviceEventArgs
                    <Keys, KeyboardState>(key, this));
 
        // If it was just released (this is the first frame
        // it is up), trigger the corresponding event
        if (WasKeyReleased(key))
            if (KeyReleased != null)
                KeyReleased(this, new InputDeviceEventArgs
                    <Keys, KeyboardState>(key, this));
 
        // If it has been held (it has been down for more
        // than one frame), trigger the corresponding event
        if (WasKeyHeld(key))
            if (KeyHeld != null)
                KeyHeld(this, new InputDeviceEventArgs
                    <Keys, KeyboardState>(key, this));
    }
}

Now we will write the functions that check for various states (button up, down, held, released, and pressed):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// Whether the specified key is currently down
public bool IsKeyDown(Keys Key)
{
    return current.IsKeyDown(Key);
}
 
// Whether the specified key is currently up
public bool IsKeyUp(Keys Key)
{
    return current.IsKeyUp(Key);
}
 
// Whether the specified key is down for the first time
// this frame
public bool WasKeyPressed(Keys Key)
{
    if (last.IsKeyUp(Key) && current.IsKeyDown(Key))
        return true;
 
    return false;
}
 
// Whether the specified key is up for the first time
// this frame
public bool WasKeyReleased(Keys Key)
{
    if (last.IsKeyDown(Key) && current.IsKeyUp(Key))
        return true;
 
    return false;
}
 
// Whether the specified key has been down for more than
// one frame
public bool WasKeyHeld(Keys Key)
{
    if (last.IsKeyDown(Key) && current.IsKeyDown(Key))
        return true;
 
    return false;
}

The MouseDevice and GamepadDevice classes work similarly, so I will link to the files instead of posting the whole thing:

MouseDevice.cs
GamepadDevice.cs

And thats all there is to it! So, for example, if you wanted to monitor the keyboard and mouse, you would create instances of KeyboardDevice and MouseDevice in your game:

1
2
MouseDevice mouse = new MouseDevice();
KeyboardDevice keyboard = new KeyboardDevice();

Then to monitor them, add them add services so you can access them elsewhere:

1
2
Engine.Services.AddService(typeof(MouseDevice), mouse);
Engine.Services.AddService(typeof(KeyboardDevice), keyboard);

For example, to spawn the box to tip the others over when the mouse button is pressed, change the box spawn code in the update method to the following:

1
2
3
4
5
6
7
8
9
10
if (Engine.Services.GetService<MouseDevice>().WasButtonPressed(MouseButtons.Left))
{
    PhysicsActor act = new PhysicsActor(
        Engine.Content.Load<Model>("Content/ig_box"), 
        new BoxObject(new Vector3(1), new Vector3(0, .5f, 1), Vector3.Zero));
 
    act.Scale = new Vector3(1);
    act.PhysicsObject.Mass = 1000;
    act.PhysicsObject.Velocity = new Vector3(0, 2, -6);
}

We now have a full input system. Other devices could be built to monitor other device types, such as the guitar, or zune input panel, or an input type that XNA doesn’t support at all.

Download the Code for this Chapter

Back to Game Engine Tutorial Series

  • DotNetKicks
  • Digg
  • StumbleUpon
  • del.icio.us
  • Google
  • Reddit
  • Facebook
November 9, 2008

What’s Next

I just wanted to post a list of things we will be covering in the near future in the tutorial series:

  • Input: Gamepad, Keyboard, and Mouse
  • Cameras: Arc-Ball, Position-Target (Look-At), and Free-Look (FPS)
  • Custom shaders on models
  • Terrain: Loading from heightmap texture + Physics for terrain
  • Water: Reflective/refractive water, with normal mapped waves
  • Sky: Atmospheric scattering/cloud generation with perlin noise
  • Player physics (controlling character with input while still reacting to collisions)
  • 2D/3D Audio using XAct and XNA’s audio api
  • Xbox Live and Games For Windows Live Integration (Demo Mode, Gamer Profiles, Voice Chat, etc)
  • Editor
  • Networking
  • Lighting/Shadows
  • Advanced Shaders

There will likely be more tutorials after that, I just haven’t thought that far ahead. Also we won’t neccessarily be covering these topics in this order.

  • DotNetKicks
  • Digg
  • StumbleUpon
  • del.icio.us
  • Google
  • Reddit
  • Facebook
November 8, 2008

New Forums Up

Hi everyone, I’ve set up some forums for discussion on the engine, questions with tutorials, or whatever else you may want to discuss! You’ll need to register, and then you will be able to post on the forums. Enjoy!

http://www.innovativegames.net/forum

  • DotNetKicks
  • Digg
  • StumbleUpon
  • del.icio.us
  • Google
  • Reddit
  • Facebook
November 5, 2008

XNA Game Engine Tutorial Series #5.5 - Component Update

I want to post a little update I’ve made to the engine that doesn’t really need to be a tutorial itself. You don’t need to do this, but I’ve found that it can help with debugging later on. The problem I ran into several times is that I forgot that the engine had to be initialized before we could make components. This means that doing something like

1
2
3
4
5
6
7
public class Game1 : Game
{
	Actor actor = new Actor(...);
 
	public Game1()
	{
		.... and so on

would crash, because the engine had not set up its list of components in LoadContent() yet, and so was not ready to take new components. So, to remind myself not to do this, I added an exception that would be thrown if a component tried to set itself up before the engine was ready.

So, first we add a boolean to the Engine class called “Initialized”:

1
2
// Whether the engine has been initialized with SetupEngine()
public static bool IsInitialized = false;

Then set it to true at the end of the SetupEngine() method:

1
2
// Let components know the engine is ready to accept them
IsInitialized = true;

Now in the InitializeComponent() method of the Component class, we will first check if the engine has been intitialized, and if not we throw an exception to remind ourselves of this. Add this to the beginning of that method:

1
2
3
4
5
6
// Check if the engine has been initialized before setting
// up the component, or the Engine will crash when the
// component tries to add itself to the list.
if (!Engine.IsInitialized)
    throw new Exception("Engine must be initialized with \"SetupEngine()\"" 
        + "before components can be initialized");

Now, if we try to setup a component before the engine is ready, we will get a message telling us about it instead of a random crash. Note that something like this would still be fine:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Game1 : Game
{
	Actor actor;
	GraphicsDeviceManager graphics;
 
	public Game1()
	{
		graphics = new GraphicsDeviceManager(this);
	}
 
	protected override void LoadContent()
	{
		Engine.SetupEngine(graphics);
 
		actor = new Actor(...);
	}
 
	... and so on
  • DotNetKicks
  • Digg
  • StumbleUpon
  • del.icio.us
  • Google
  • Reddit
  • Facebook
November 2, 2008

XNA Game Engine Tutorial Series #5 - Physics

In this chapter of the tutorial, we will be implementing a physics simulation into our engine! We will not be writing the physics engine ourserlves, however, as that is far too complicated for this series. Instead, we will be writing some classes that are designed to interface with the open source JigLibX physics engine, which is built on XNA. This is great, by the way, because it means that we will be able to maintain compatibility with Xbox.

I have modified the original JigLibX project slightly to make it work better with our engine, and to fix small bugs in the original here and there. We will need to reference this project in our engine project. Download the dll here. Now, open “References” from the project, right click and choose “Add Reference”. Naviagate to the downloaded dll, and choose OK. We now have JigLibX referenced.

Note: If you are interested, you can download the modified JigLibX project here.

Now we need to start integrating JigLibX with our engine. The way this will be setup is as follows:

“Physics” Component: This will be used to manage JigLibX’s “PhysicsSystem” class. It will update the physics simulation and hold the instance of the physics system. We will need to add an instance of “Physics” to the engine’s service container for this to work. However, the benefit here is that if we don’t want to do all the extra phsyics calculations if we aren’t simulating any physics object, then we can simply not add an instance of “Physics” to the engine services.

“PhysicsObject” Component: This is the base type of physics simulation object. It keeps track of the neccessary objects to properly simulate a physical object with JigLibX, and other object types will inherit from it. These types are “Box”, “Capsule”, “Sphere”, “Plane”, and “Triangle Mesh”. The last one simulates every triangle in a model. This is useful for things like levels, which can have a complex design that can’t be simulated with a few boxes and spheres. Another plus here is that we could create new types of physics objects very easily to simulate more complex models without doing work for every triangle.

“PhysicsActor” Component: This component inherits from “Actor”, the key difference being that it takes a PhysicsObject, which is uses for drawing instead of user defined values (like the normal “Actor” class does). It does this by overriding the I3DComponent properties with the position, rotation, scale, and BoundingBox of it’s PhysicsObject.

Lets begin! Add a new class called “Physics”. Set it up as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
using JigLibX.Collision;
using JigLibX.Physics;
 
namespace Innovation
{
    public class Physics : Component
    {
        // The physics simulation
        public PhysicsSystem PhysicsSystem = new PhysicsSystem();
 
        // Whether or not we should update
        public bool UpdatePhysics = true;
 
        public Physics()
        {
            // Set up physics system
            this.PhysicsSystem.EnableFreezing = true;
            this.PhysicsSystem.SolverType = PhysicsSystem.Solver.Normal;
            this.PhysicsSystem.CollisionSystem = new CollisionSystemSAP();
        }
 
        public override void Update()
        {
            // Update the physics system
            if (UpdatePhysics)
                PhysicsSystem.CurrentPhysicsSystem.Integrate(
                    (float)Engine.GameTime.ElapsedGameTime.TotalSeconds);
        }
    }
}

This class will be responsible for handling the JigLibX PhysicsSystem and updating it. If we don’t want to simulate physics in a simpler game, for example, we can not create this class and keep extra calculation to a minimum.

The next class we will build is called PhysicsObject. This is the base class that simulated objects will inherit from. These child classes simulate boxes, capsules (pills), planes, spheres, and triangle meshes (simulate every vertex in a model). Here is the code for this class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
using JigLibX.Collision;
using JigLibX.Geometry;
using JigLibX.Physics;
using Microsoft.Xna.Framework;
 
namespace Innovation
{
    // Provides a base object type for physics simulation
    public abstract class PhysicsObject : Component
    {
        // Local copy of the mass of the object
        float mass = 1;
 
        // The Body managed by the PhysicsObject
        public Body Body;
 
        // The CollisionSkin managed by the PhysicsObject
        public CollisionSkin CollisionSkin;
 
        // The mass of the PhysicsObject
        public float Mass
        {
            get { return mass; }
            set {
                // Set the new value
                mass = value;
 
                // Fix transforms
                Vector3 com = SetMass(value);
                if (CollisionSkin != null)
                    CollisionSkin.ApplyLocalTransform(
                        new JigLibX.Math.Transform(-com, Matrix.Identity));
            }
        }
 
        // The PhysicsObject's position
        public Vector3 Position
        {
            get { return Body.Position; }
            set { Body.MoveTo(value, Body.Orientation); }
        }
 
        // The PhysicsObject's orientation
        public Matrix Orientation
        {
            get { return Body.Orientation; }
            set { Body.MoveTo(Body.Position, value); }
        }
 
        // Whether or not the physics object is locked in place
        public bool Immovable
        {
            get { return Body.Immovable; }
            set { Body.Immovable = value; }
        }
 
        // The PhysicsObject's rotation
        public Vector3 Rotation
        {
            get {
                Quaternion q = Quaternion.CreateFromRotationMatrix(Orientation);
                return new Vector3(q.X, q.Y, q.Z);
            }
            set { Body.MoveTo(Body.Position, Matrix.CreateFromYawPitchRoll(
                MathHelper.ToRadians(value.Y),
                MathHelper.ToRadians(value.X),
                MathHelper.ToRadians(value.Z)));
            }
        }
 
        // Returns the PhysicsObject's BoundingBox
        public BoundingBox BoundingBox
        {
            get
            {
                if (Body.CollisionSkin != null)
                    return Body.CollisionSkin.WorldBoundingBox;
                else
                    return new BoundingBox(Position - Vector3.One,
                        Position + Vector3.One);
            }
        }
 
        // The body's velocity
        public Vector3 Velocity
        {
            get { return Body.Velocity; }
            set { Body.Velocity = value; }
        }
 
        // Constructors
        public PhysicsObject() : base(){ }
        public PhysicsObject(GameScreen Parent) : base(Parent) { }
 
        // Sets up the body and collision skin
        protected void InitializeBody()
        {
            Body = new Body();
            CollisionSkin = new CollisionSkin(Body);
            Body.CollisionSkin = this.CollisionSkin;
            Body.EnableBody();
        }
 
        // Sets the mass of the PhysicsObject
        public Vector3 SetMass(float mass)
        {
            PrimitiveProperties primitiveProperties =
                new PrimitiveProperties(
                    PrimitiveProperties.MassDistributionEnum.Solid,
                    PrimitiveProperties.MassTypeEnum.Density, mass);
 
            float junk; Vector3 com; Matrix it, itCoM;
 
            CollisionSkin.GetMassProperties(primitiveProperties,
                out junk, out com, out it, out itCoM);
            Body.BodyInertia = itCoM;
            Body.Mass = junk;
 
            return com;
        }
 
        // Rotates and moves the model relative to the physics object to
        // better align the model with the object
        public void OffsetModel(Vector3 PositionOffset,
            Matrix RotationOffset)
        {
            CollisionSkin.ApplyLocalTransform(
                new JigLibX.Math.Transform(PositionOffset, RotationOffset));
        }
 
        // Disables physics body and component
        public override void DisableComponent()
        {
            Body.DisableBody();
            base.DisableComponent();
        }
    }
}

The first type of object we are going to make is a box. We accept the lengths of the sides of the box, and set up the body. As you can see, most of the work is done by PhysicsObject, and most of the code we write here is just various constructor overloads to allow greater flexibility.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
using JigLibX.Collision;
using JigLibX.Geometry;
using JigLibX.Physics;
using Microsoft.Xna.Framework;
 
namespace Innovation
{
    // A box shaped physics object
    public class BoxObject : PhysicsObject
    {
        Vector3 sideLengths;
 
        // The length of the sides of the box
        public Vector3 SideLengths
        {
            get { return sideLengths; }
            set
            {
                // Set the new value
                sideLengths = value;
 
                // Update the collision skin
                CollisionSkin.RemoveAllPrimitives();
                CollisionSkin.AddPrimitive(
                    new Box(-0.5f * value, Body.Orientation, value),
                    (int)MaterialTable.MaterialID.UserDefined,
                    new MaterialProperties(0.8f, 0.8f, 0.7f));
 
                // Set the mass to itself to fix the local transform
                // on the CollisionSkin in the set accessor
                this.Mass = this.Mass;
            }
        }
 
        // Constructors
 
        public BoxObject() : base()
        {
            InitializeBody();
            SideLengths = Vector3.One;
        }
 
        public BoxObject(Vector3 SideLengths) : base()
        {
            SetupSkin(SideLengths, Vector3.Zero, Vector3.Zero);
        }
 
        public BoxObject(Vector3 SideLengths, Vector3 Position,
            Vector3 Rotation) : base()
        {
            SetupSkin(SideLengths, Position, Rotation);
        }
 
        public BoxObject(Vector3 SideLengths, Vector3 Position,
            Vector3 Rotation, GameScreen Parent) : base(Parent)
        {
            SetupSkin(SideLengths, Position, Rotation);
        }
 
        // Sets up the object with the specified parameters
        void SetupSkin(Vector3 SideLengths, Vector3 Position,
            Vector3 Rotation)
        {
            // Setup the body
            InitializeBody();
 
            // Set properties
            this.SideLengths = SideLengths;
            this.Position = Position;
            this.Rotation = Rotation;
        }
    }
}

For the sake of brevity, I am not going to post the other physics objects in the post, instead, you can download the code files here:

CapsuleObject.cs
PlaneObject.cs
TriangleMeshObject.cs
SphereObject.cs

Now that we have all these object types, we are going to make a new Actor that knows how to deal with them. We will call this “PhysicsActor”. The difference here is that this class will accept a model and physics object, instead of a position. Most of the work will still be done by the base actor class, but we will be overriding the position, rotation, bounding box, and scale properties to take the physics object’s matching properties. In order to do so, we need to change these properties in the base “Actor” class to “virtual”, which simply means that classes that inherit from “Actor” will be able to override them, or replace their functionality. Change the position, rotation, etc. in the “Actor” class to this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// I3DComponent values
public virtual Vector3 Position { get; set; }
public virtual Vector3 Rotation { get; set; }
public virtual Vector3 Scale { get; set; }
public virtual BoundingBox BoundingBox
{
    get
    {
        return new BoundingBox(
            Position - (Scale / 2),
            Position + (Scale / 2)
        );
    }
}

Now add the “PhysicsActor” class. As you can see, all it does is replace the values of position, rotation, etc. to those of the physics object, and does some management of the object.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
 
namespace Innovation
{
    // Manages a PhysicsObject and allows the engine to work
    // with it
    public class PhysicsActor : Actor
    {
        // The object we are managing
        public PhysicsObject PhysicsObject;
 
        // Override the position of the base class to that
        // of the physics object
        public override Vector3 Position
        {
            get { return PhysicsObject.Position; }
            set
            {
                if (PhysicsObject != null)
                    PhysicsObject.Position = value;
            }
        }
 
        // Override the rotation of the base class to that
        // of the physics object
        public override Vector3 Rotation
        {
            get { return PhysicsObject.Rotation; }
            set
            {
                if (PhysicsObject != null)
                    PhysicsObject.Rotation = value;
            }
        }
 
        // Override the BoundingBox of the base class to that
        // of the physics object
        public override BoundingBox BoundingBox
        {
            get { return PhysicsObject.BoundingBox; }
        }
 
        // Constructors
 
        public PhysicsActor(Model Model, PhysicsObject PhysicsObject)
            : base(Model, PhysicsObject.Position)
        {
            this.PhysicsObject = PhysicsObject;
        }
 
        public PhysicsActor(Model Model, PhysicsObject PhysicsObject,
            GameScreen Parent)
            : base(Model, PhysicsObject.Position, Parent)
        {
            this.PhysicsObject = PhysicsObject;
        }
 
        // Override DisableComponent so we can remove the physics
        // object as well
        public override void DisableComponent()
        {
            this.PhysicsObject.DisableComponent();
            base.DisableComponent();
        }
    }
}

We are now done with our basic physics implementation! Now let’s change our demo game so we can test it out! Here is the updated content for this tutorial: Content.zip.

To demo our physics, we are going to create a stack of boxes, then knock it down with another box after a few seconds. Change the load method to look like the following code. Here we are doing all the regular set up stuff, but we are also adding a Physics component, and creating a plane for the ground, and creating the pile of boxes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
protected override void LoadContent()
{
    // Setup engine. We do this in the load method
    // so that we know graphics will be ready for use
    Engine.SetupEngine(graphics);
 
    // Create a new Camera
    Camera camera = new Camera();
 
    // Setup its position and target
    camera.Position = new Vector3(3, 3, 5);
    camera.Target = new Vector3(0, 0, 0);
 
    // Add it to the service container
    Engine.Services.AddService(typeof(Camera), camera);
 
    // Setup physics
    Engine.Services.AddService(typeof(Physics), new Physics());
 
    // Create the plane and make it immovable
    PhysicsActor plane = new PhysicsActor(
        Engine.Content.Load<Model>("Content/ig_plane"),
        new BoxObject(new Vector3(4, .01f, 4)));
    plane.PhysicsObject.Immovable = true;
 
    // Load the model we will use for our boxes
    Model model = Engine.Content.Load("Content/ig_box");
 
    // Create the stack of boxes
    for (int y = 0; y < 3; y++)
        for (int x = 0; x < 3; x++)
        {
            PhysicsActor act = new PhysicsActor(model, new BoxObject(
                new Vector3(.5f),
                new Vector3