This tutorial is going to cover the addition of some utilities to Engine and demonstrate the creation of a basic component. Then we are going to cover the creation of a camera and actor.
We are going to add two utilities to the Engine class. The first is a math helper that mainly generates matrices for drawing, cameras, model rendering, etc. The second is a graphics utility that helps with the creation of render targets and resolve textures. It’s OK if you don’t know that that means, we won’t be using them for a while.
First, here is the code for the MathUtil class:
using Microsoft.Xna.Framework;
namespace Innovation
{
public static class MathUtil
{
// Generates a projection matrix for a draw call
public static Matrix CreateProjectionMatrix()
{
return Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4,
(float)Engine.GraphicsDevice.Viewport.Width
/ (float)Engine.GraphicsDevice.Viewport.Height,
.01f, 1000000);
}
// Creates a world matrix
public static Matrix CreateWorldMatrix(Vector3 Translation)
{
return CreateWorldMatrix(Translation, Matrix.Identity);
}
// Creates a world matrix
public static Matrix CreateWorldMatrix(Vector3 Translation,
Matrix Rotation)
{
return CreateWorldMatrix(Translation, Rotation, Vector3.One);
}
// Creates a world matrix
public static Matrix CreateWorldMatrix(Vector3 Translation,
Matrix Rotation, Vector3 Scale)
{
return Matrix.CreateScale(Scale) *
Rotation *
Matrix.CreateTranslation(Translation);
}
// Converts a rotation vector into a rotation matrix
public static Matrix Vector3ToMatrix(Vector3 Rotation)
{
return Matrix.CreateFromYawPitchRoll(Rotation.Y, Rotation.X, Rotation.Z);
}
// Converts a rotation matrix into a rotation vector
public static Vector3 MatrixToVector3(Matrix Rotation)
{
Quaternion q = Quaternion.CreateFromRotationMatrix(Rotation);
return new Vector3(q.X, q.Y, q.Z);
}
}
}
Second, here is the code for the GraphicsUtil class:
using Microsoft.Xna.Framework.Graphics;
namespace Innovation
{
public static class GraphicsUtil
{
// Creates a RenderTarget2D with the specified parameters
public static RenderTarget2D CreateRenderTarget()
{
return CreateRenderTarget(Engine.GraphicsDevice.Viewport.Width,
Engine.GraphicsDevice.Viewport.Height);
}
// Creates a RenderTarget2D with the specified parameters
public static RenderTarget2D CreateRenderTarget(int Width, int Height)
{
return CreateRenderTarget(Width, Height,
Engine.GraphicsDevice.DisplayMode.Format);
}
// Creates a RenderTarget2D with the specified parameters
public static RenderTarget2D CreateRenderTarget(int Width, int Height,
SurfaceFormat Format)
{
return CreateRenderTarget(Width, Height, Format,
Engine.GraphicsDevice.PresentationParameters.MultiSampleQuality,
Engine.GraphicsDevice.PresentationParameters.MultiSampleType);
}
// Creates a RenderTarget2D with the specified parameters
public static RenderTarget2D CreateRenderTarget(int Width, int Height,
SurfaceFormat Format, int MultiSampleQuality,
MultiSampleType SampleType)
{
return new RenderTarget2D(Engine.GraphicsDevice, Width,
Height, 1, Format, SampleType, MultiSampleQuality,
RenderTargetUsage.DiscardContents);
}
// Creates a ResolveTexture2D
public static ResolveTexture2D CreateResolveTexture()
{
return new ResolveTexture2D(Engine.GraphicsDevice,
Engine.GraphicsDevice.Viewport.Width,
Engine.GraphicsDevice.Viewport.Height, 1,
Engine.GraphicsDevice.DisplayMode.Format);
}
}
}
Now we can get started with some basic components. Our demo component will do nothing more than clear the backbuffer. Before we get started on this component, we need to clean up the Game class in the demo project (in our example, “TestEnvironment”). We are going to remove the large amounts of comments and some of the methods and objects we won’t be using (in Game1.cs):
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Innovation;
namespace TestEnvironment
{
public class Game1 : Game
{
// The IGraphicsDeviceService the engine will use
GraphicsDeviceManager graphics;
public Game1()
{
// Setup graphics
graphics = new GraphicsDeviceManager(this);
}
protected override void LoadContent()
{
}
protected override void Update(GameTime gameTime)
{
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
base.Draw(gameTime);
}
}
}
Now we are going to add the code to initialize the engine. Add the followig to LoadContent(), Update(), and Draw(), respectively. Add the code before the base.Whatever() calls.
// Setup engine. We do this in the load method // so that we know graphics will be ready for use Engine.SetupEngine(graphics);
// Update the engine and game Engine.Update(gameTime);
// Draw the engine and game Engine.Draw(gameTime, ComponentType.All);
Now when you hit F5, you should see the following:
Now we can create our component. Create this one in the game project. Add a new class and add the following code:
using Innovation;
using Microsoft.Xna.Framework.Graphics;
namespace TestEnvironment
{
class ClearScreen : Component
{
// Override the component's draw method
public override void Draw()
{
// Simply clear the backbuffer to red
Engine.GraphicsDevice.Clear(Color.Red);
}
}
}
Now, go back to the Game1 class and add the following at the end of the LoadContent() method to add an instance of it to the game:
// Create a new ClearScreen. It will automatically // be set the engine's DefaultScreen, currently // Engine.BackGroundScreen ClearScreen clear = new ClearScreen();
You should now see the following:
Now we are going to start on some more complicated components. The first is our Camera class. This is just a base class, other cameras later on will inherit from it. This camera doesn’t have any fancy movement functions, but it does what we need it to, which, for now is just point at a target location and generate the matrices we need to draw. Here is the code, add this class to the engine’s project:
using Microsoft.Xna.Framework;
using System;
namespace Innovation
{
// Basic Camera class
public class Camera : Component, I3DComponent
{
// Internal values
Vector3 position = Vector3.Zero;
Matrix rotationMatrix = Matrix.Identity;
Vector3 target = new Vector3(0, 0, -1);
Vector3 up = Vector3.Up;
Matrix view;
Matrix projection;
// The point the camera is looking at
public virtual Vector3 Target
{ get { return target; } set { target = value; } }
// The View and Projection matrices commonly used for rendering
public virtual Matrix View
{ get { return view; } set { view = value; } }
public virtual Matrix Projection
{ get { return projection; } set { projection = value; } }
public virtual Vector3 Up
{ get { return up; } set { up = value; } }
// Public I3DComponent values
public virtual Vector3 Position { get { return position; } set { position = value; } }
public virtual Vector3 Scale { get { return Vector3.One; } set { } }
public Vector3 EulerRotation
{
get { return MathUtil.MatrixToVector3(Rotation); }
set { Rotation = MathUtil.Vector3ToMatrix(value); }
}
// The rotation matrix used by the camera and the current up vector
public virtual Matrix Rotation
{ get { return rotationMatrix; } set { rotationMatrix = value; } }
public virtual BoundingBox BoundingBox
{ get { return new BoundingBox(Position - Vector3.One, Position + Vector3.One); } }
// Constructors
public Camera(GameScreen Parent) : base(Parent) { }
public Camera() : base() { }
// Update the camera
public override void Update()
{
// Calculate the direction from the position to the target, and normalize
Vector3 newForward = Target - Position;
newForward.Normalize();
// Set the rotation matrix's forward to this vector
Matrix rotationMatrixCopy = this.Rotation;
rotationMatrixCopy.Forward = newForward;
// Save a copy of "Up" (0, 1, 0)
Vector3 referenceVector = Vector3.Up;
// On the slim chance that the camera is pointed perfectly parallel with
// the Y Axis, we cannot use cross product with a parallel axis, so we
// change the reference vector to the forward axis (Z).
if (rotationMatrixCopy.Forward.Y == referenceVector.Y
|| rotationMatrixCopy.Forward.Y == -referenceVector.Y)
referenceVector = Vector3.Backward;
// Calculate the other parts of the rotation matrix
rotationMatrixCopy.Right = Vector3.Cross(this.Rotation.Forward,
referenceVector);
rotationMatrixCopy.Up = Vector3.Cross(this.Rotation.Right,
this.Rotation.Forward);
this.Rotation = rotationMatrixCopy;
// Use the rotation matrix to find the new up
Up = Rotation.Up;
// Recalculate View and Projection using the new Position, Target, and Up
View = Matrix.CreateLookAt(Position, Target, Up);
Projection = MathUtil.CreateProjectionMatrix();
}
}
}
The next component we need to make is called ‘Actor’. This class simply keeps track of a model, keeps track of Position, Rotation, Scale, etc, and draws the model with those properties. You will see that it looks for a Camera in the Engine’s service container to draw with. If it doesn’t find one, it will stop excecution and throw an exception. Here is the code:
using System;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
namespace Innovation
{
public class Actor : Component, I3DComponent
{
// The model to draw
Model model;
// I3DComponent values
public virtual Vector3 Position { get; set; }
public Vector3 EulerRotation
{
get { return MathUtil.MatrixToVector3(Rotation); }
set { Rotation = MathUtil.Vector3ToMatrix(value); }
}
public virtual Matrix Rotation { get; set; }
public virtual Vector3 Scale { get; set; }
public virtual BoundingBox BoundingBox
{
get
{
return new BoundingBox(
Position - (Scale / 2),
Position + (Scale / 2)
);
}
}
// Constructors take a model to draw and a position
public Actor(Model Model, Vector3 Position)
: base()
{
Setup(Model, Position);
}
public Actor(Model Model, Vector3 Position, GameScreen Parent)
: base(Parent)
{
Setup(Model, Position);
}
// Provide a method to setup the actor so we don't need to
// write it in each constructor
void Setup(Model Model, Vector3 Position)
{
this.model = Model;
this.Position = Position;
Scale = Vector3.One;
EulerRotation = Vector3.Zero;
}
public override void Draw()
{
// Look for a camera in the service container
Camera camera = Engine.Services.GetService();
// Throw an exception if one isn't present
if (camera == null)
{
throw new Exception("Camera not found in engine's"
+ "service container, cannot draw");
}
// Generate the world matrix (describes the objects movement in 3D)
Matrix world = MathUtil.CreateWorldMatrix(Position, Rotation, Scale);
Matrix[] transforms = new Matrix[model.Bones.Count];
model.CopyAbsoluteBoneTransformsTo(transforms);
// Set some renderstates so the model will draw properly
Engine.GraphicsDevice.RenderState.AlphaBlendEnable = true;
Engine.GraphicsDevice.RenderState.SourceBlend = Blend.SourceAlpha;
Engine.GraphicsDevice.RenderState.DestinationBlend = Blend.InverseSourceAlpha;
Engine.GraphicsDevice.RenderState.DepthBufferEnable = true;
// Loop through meshes and effects and set them up to draw
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
// Set effect parameters
effect.Parameters["World"].SetValue(transforms[mesh.ParentBone.Index] * world);
effect.Parameters["View"].SetValue(camera.View);
effect.Parameters["Projection"].SetValue(camera.Projection);
// Enable lighting
effect.EnableDefaultLighting();
}
// Draw the mesh
mesh.Draw();
}
}
}
}
Finally, we are going to add a camera and actor to our game. You will need to add the content files found here to the content project for the following code to work. Add this code at the end of the LoadContent() method in the Game1 class in the game project:
// Create a new Camera
Camera camera = new Camera();
// Setup its position and target
camera.Position = new Vector3(1, 1, 2);
camera.Target = new Vector3(0, 0, 0);
// Add it to the service container
Engine.Services.AddService(typeof(Camera), camera);
// Create a new actor
Actor actor = new Actor(Engine.Content.Load("Content/ig_box"), new Vector3(0, 0, 0));
Now, when you run the game, you should see the model being draw at the coordinates specified with a camera positioned at the specified coordinates.
That’s all for this tutorial, we’ll be making some more components next time!
Download the Code for this Chapter
Back to Game Engine Tutorial Series
« XNA 3.0 Release Date Announced! XNA Game Engine Tutorial Series #4 – DrawOrder »




Can I just say that you are an amazing individual for taking the time to do this for all of us who are working so hard to learn how to make games! I am a programming major at a local college, and they have not prepared me whatsoever for the world of programming and its intricacies. They leave those of us who have a desire to learn on our own, and people like you make it that much easier. I have been scraping through tutorials for the past six months, and this has to be the most informative one I have found, so THANK YOU!
Looks great. I love how simple it is to implement additional components. Great concept.
Issues (in text only)
In the text above you have the GraphicsUtil class as just Graphics
public class Graphics
should be
public class GraphicsUtil
Thank you to both of you, for your complements and for pointing out the error!
By far the best XNA tutorials I have seen so far – easy to understand, heavily commented and above all extremely useful!
Hopefully you will continue to add more tutorials in the same style which explain more advanced concepts.
Keep up the good work.
I obtain this error at Actor class.
public Vector3 Position { get; set; }
Error 1 ‘XNAMotor.Actor.Position.get’ you should declare a body because it not is abstract or extern: Actor.cs
FIXED.
I am using Net Framework 2.0, and it don’t support auto properties.
The final code was:
Vector3 position;
public Vector3 Position { get { return position; } set { position = value; } }
Thanks for the tutorial.
Hey,
I really like your tutorials, greatly commented and good ideas – thanks!
I do have a problem though: (my fault since your code works fine but I wanna work of my own you know?)
Prob: When my screen is supposed to turn red after added the clearScreen it doesnt… How come? I tried to just keep working on and got to the end. Compiles no problem but it still only shows the blue background and no
Can you help me?
Ah nevermind it! Got a hold of a comparison program and found the error. I had forgot to set
Visible = true
under the Component.cs… doh! hehe Ah well all solved now. Cant wait to move onto 4 and 5.
Hope you are gonna cover some groundwork of an editor before long as I think thats gotta be a corner stone of any game being able to change your levels around quickly to accomodate change.
Brilliant articles – keep up the good work!
Would like to add to the praise mentioned here so far – just downloaded XNA 2 days ago and am finding your tutorial absolutely eye-opening. I’ve never done any 3D before but by working through your clear steps and code I actually understand what’s going on (I think!)
A hearty thank you and I’ll keep on going with number 4.
Wow – this is an amazing series of articles. Working through these has really cleared up a lot of the other stuff I was poking around with before this – your engine layout really helps me understand how XNA works!
Working through is like getting power-leveled — sooo grateful!
Alex
This is a brilliant tutorial. Most of the rest are advanced where I couldn’t understand a thing (such as one on how to create fur etc.) and this has helped me understand how programming really is. I used to just go through the steps not knowing what in the world I was doing, but I actually understand this now! I have a question now.
I have added a reference to the base game to my engine, and in the Game1 class added a using statement for it. Unfortunately, it comes up with several warnings such as that Engine doesn’t exist in the current context, and that the Component in the Components class has no return type. I’m by no means an experienced programmer, so I was hoping someone could help me out with this.
Scratch the Component problem, but I’m still getting the error that the Engine doesn’t exist in the current context.
Sounds to me like you have your references backwards. You need to reference the engine project from the game project. Not the other way around. If you are able to reference the game from the engine then that means you aren’t referencing the engine from the game, because you’d get errors if you tried. Make sure that you are referencing the engine from the game. if you are, then make sure you are doing “using Innovation;”
I fixed it some time last night, I don’t remember how though haha. I promptly went to bed soon after.
I finally finished your tutorial. I have rechecked my code.
It worked absolutely perfectly up until the Input tutorial, and then it started giving me the error that in InitializeComponent inside the Component class that my Parent.Components.Add(this); is not set to a reference of an object. Any ideas on this?
One small discrepancy above in the MathUtil code:
public static Matrix CreateWorldMatrix(Vector3 Translation,
Vector3 Rotation, Vector3 Scale)
The Rotation parameter should be a Matrix:
public static Matrix CreateWorldMatrix(Vector3 Translation,
Matrix Rotation, Vector3 Scale)
@pdub
I think the error is different. The MathUtil code is correct, just replace the given rotation matrix param with EulerRotation and everything should work fine.
Hi there!
Love the tutorials!!! learning allot.
I have one question tho.
if i load a model i get a invalidCastException…
Unable to cast object of type ‘Microsoft.Xna.Framework.Graphics.GraphicsDevice’ to type ‘Microsoft.Xna.Framework.Graphics.IGraphicsDeviceService’.
Perhaps you have an idea what i causing this ?
Oww sorry just a type. you can delete my question
Sean I’d just like to say a big Thank You. I’m 5 months from my Bachelor’s in Game Development in a program that is very C++ heavy. I’ve only ever made tools in C# and this past week is my first foray into XNA. Your tutorials have made learning the API and brushing up on C# so much easier. I’m impressed by some of your ideas concerning structure and state flow and have plans to carry some of them over into a C++ mini wrapper for a state machine and input handler.
You’ve just made my side projects easier to implement and more fun for me. All I have to worry about is the game itself from now on.
Good on you Sir! and Thanks!
@Julian and Sean
What I’m saying is: The code shown in the tutorials for MathUtil.cs is different than the source code provided in the project.zip file. It does not compile if you type it in as it’s shown on the tutorial.
In the tutorial, the Rotation params are of type Vector3. In the source code, they are of the (correct) type Matrix.
Additionally, some of the other MathUtil.cs code in the tutorial (namely the CreateWorldMatrix overloads) is completely different from the MathUtil.cs code provided in the Project.zip file. It appears as if the code was changed and the tutorial was not updated to reflect the change.
I’m no expert at any of this stuff, all I’m saying is if you are following along manually typing the code from the tutorials MathUtil won’t compile.
I’m stuck with a cornflowerblue screen. I have deleted the clear line from Game1.draw and commented out the clear from the Engine.draw. I tried putting in different colors at the Engine.draw clear statement. Anyone got an idea for figuring out what I’ve left out or should I just start over?
@pdub
I can confirm this. I just changed “Rotation” in
// Generate the world matrix (describes the objects movement in 3D)
Matrix world = MathUtil.CreateWorldMatrix(Position, Rotation, Scale);
to EulerRotation and it worked fine.
My bad. I am still new to 3D and I didn’t understand what an Euler rotation even was. I’ve got it now tho.
No, you were right the first time. I updated the post with the corrected MathUtil.
I had to change the last line of code to
Actor actor = new Actor(Engine.Content.Load(“Content/images/ig_box”), new Vector3(0, 0, 0));
Engine.Content.Load if I didn’t have I got three compiler errors.
OH, what was inside of “” got erased
so the last line should have
Engine.Content.Load”"
I give up trying to type it,
it should be Engine.Content.Load(lessthansymbol)Model(greaterthansymbol)
WordPress doesn’t like the < and > symbols, it thinks you are trying to insert HTML into the commnet. I’ve fixed this a number of times in the post but every once in a while it will block it out again. I would type & l t ; and & g t ; (without the spaces) to insert those symbols.
I have a few problems which I’m having trouble figuring out.
In Actor.cs (Engine), this line produces an error:
Camera camera = Engine.Services.GetService();
Should this be Camera camera = Engine.Services.GetServices<Camera>(); ?
Apart from that, I’m getting a few errors which tell me:
“The type or namespace name ‘Camera’ could not be found”, in Game1.cs.
The same goes for ‘Actor’.
And finally, in Camera.cs
public Camera(GameScreen Parent) : base(Parent) { }
produces:
“‘object’ does not contain a constructor that takes ’1′ arguments”.
I’m very confused. Thanks in advance for your help.
Hah, do I feel silly.
I downloaded the source and turns out I missed some key lines.
Keep up the awesome work =D
Hey, i really like the tutorials theyve been helping a lot.
How would i go about moving around an actor object, such as the one that was rendered in this tutorial?
Thank you!
There are a few differences between the source code .zip files and the code on the page. When I tried using the source code on the page I got two errors in the final build.
First was this one in actor.cs
Camera camera = Engine.Services.GetService();
Second was the drawing of the object in game1.cs:
Actor actor = new Actor(Engine.Content.Load(“Content/ig_box”), new Vector3(0, 0, 0));
Should we be using the source files instead of the web site?
Oh, I see, the web site is removing anything inside the greaterthanlessthan brackets which explains it.
I get a ContentLoadException when it tries to load the model. After looking at some of the debug information, I found out that it appends “.xnb” to the end of the filename. So, instead of looking for “Content/ig_box”, it looks for “Content/ig_box.xnb”. any suggestions?
I am at the end of this tutorial and I keep getting this exception(look below). Not sure what is causing it. It looks like it has something to do with this line in the Game1 class:
// Create a new actor
Actor actor = new Actor(Engine.Content.Load(“Content/ig_box”), new Vector3(0, 0, 0));
————————————————————————–
System.NotImplementedException was unhandled
Message=”The method or operation is not implemented.”
Source=”VenomEngine2″
StackTrace:
at VenomEngine2.Components.IEContentManager.Load(String p) in G:\Documents\Visual Studio 2008\Projects\VenomEngine2\VenomEngine2\IEContentManager.cs:line 85
at TestGame1.Game1.LoadContent() in G:\Documents\Visual Studio 2008\Projects\VenomEngine2\TestGame1\Game1.cs:line 35
at Microsoft.Xna.Framework.Game.Initialize()
at Microsoft.Xna.Framework.Game.Run()
at TestGame1.Program.Main(String[] args) in G:\Documents\Visual Studio 2008\Projects\VenomEngine2\TestGame1\Program.cs:line 14
InnerException:
————————————————————————-
The exception is from the IEContentManager class file:
public Microsoft.Xna.Framework.Graphics.Model Load(string p)
{
throw new NotImplementedException();
}
Getting a lot of these in Engine.cs and ComponentCollection.cs
Inconsistent accessibility: base class ‘System.Collections.ObjectModel.Collection’ is less accessible than class ‘Innovation.ComponentCollection’
I downloaded your code to double check what I typed.. not sure why I get these errors and you don’t. Can somebody explain?
here is the example of the above error
public class ComponentCollection : Collection
SOLVED!!! I forgot to make sure my classes were public! Thanks for the great tutorials!!
I’ve been following your tutorials, thanks for taking the time to help us newer folks out.
Based on your tutorials i’ve been trying to make a test game using JigLibX and cannot seem to pick out collisions. I have 3 objects and in the update method of PhyicsActor check if skin1 and skin0 are not equal then have a bell sound. My problem is, the bell sounds no matter which of the other two objects I hit. Do you think you could expand on this tutorial and demonstrate how to make a bell sound when 1 object hits a specific target (or collisionskin) and not the other? I’ve read all the JigLibX help online and their docs are just lacking severly.
Thanks!
When I use Viewport.width / Viewport.height in the AspectRatio argument of the CreateProjectionMatrix class I get a slightly stretched box on the screen, I changed it to Viewport.AspectRatio and now the box looks fine, anyone else also had this?
I mean the CreateProjectionMatrix class inside the MathUtil class :p