October 9, 2008

XNA Game Engine Tutorial Series: #1 – Component and GameScreen

One of the problems I often see is that people who are learning tend to spend much of their time learning graphics, and not enough time learning how to structure their game or game engine. In this tutorial series I am going to share what I’ve learned on this topic. This is by no means the only or ‘right’ way to do it, but there certainly are wrong ways, and I hope to help you avoid many of them.

There is a sample on the XNA Creators Club website that is a great starting point for game structure research. The design of the engine we’ll be designing is based partly on this tutorial. (http://creators.xna.com/en-us/samples/gamestatemanagement). So, let’s get started! The basic structure of the engine is as follows:

Game Engine Structure

  • Component class: This class is the base that all objects that will be managed by the engine should inherit from. It contains “Update()” and “Draw()” methods to update and draw itself. It also contains a “Visible” property to set whether or not to draw the component.
  • GameScreen class: This class contains a group of Components and handles their updating and drawing. It contains “BlocksDraw”, “BlocksUpdate”, and “BlocksInput” properties to block the drawing, updating, and input processing of the screens below. This allows for screens to easily implement functionality like pausing the game. Of course, the screens can override this so that screens that must always draw or update or something similar can still do so.
  • Engine class: This is a static class that contains a list of GameScreens. It manages their update and draw, and also contains a number of useful properties, such as a service container, the GraphicsDevice and SpriteBatch, and more.
Engine Structure

Engine Structure

Setting Up Visual Studio

Solution Explorer - Solution Setup

Solution Explorer - Solution Setup

Before we can start on our code, we need to get Visual Studio set up. We will have two projects in our solution, one for the engine itself and another for the demo game that utilizes it. So, open up Visual Studio, and select File-New Project, and choose type XNA Windows Game Library, and choose a name. I used “InnovationEngine”, but any name will do. When the project is all set up, open up the Solution Explorer and right click your solution (The top node). Select Add-New Project, and choose Type XNA Windows Game. Pick a name (I used “TestEnvironment”), and press OK. Finally, we need to reference our engine project from the game project. Expand the game’s node (It is labelled “TestEnvironment” in the example above”), right click “References”, and choose “Add Reference”. Click on the “Projects” tab and choose the name of your engine project. (In this case, “InnovationEngine”). Add a new folder to your engine project and call it “Components”. We are now all setup. To run the game, right click on it’s project and click “Set as Startup Project”. Now, if you press F5 your game should start up, and present you with a blank blue screen.

This helps us avoid common mistake #1 – Not seperating engine code and game code. This is almost always a good idea, unless the game is very simple. Not only does it help keep things straight in your solution, but it can greatly ease in the creation of an editor later on, and it helps to keep the code in a format that can be reused later on in different games.

Component Class

The first class we need to write is the component class. This is the basis for all objects managed by the engine. Add a new file to the engine project by right clicking on it and selecting Add-New Item-Code File, and call it “Component.cs”. Add the following code to that follow. Note: Please do not just copy and paste the code, actually type it out so you can learn and understand what you’re doing.

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
using Microsoft.Xna.Framework;
 
namespace Innovation
{
    public class Component
    {
	    // The GameScreen object that owns this component
        public GameScreen Parent;
 
	    // Whether or not this component has been initialized
        public bool Initialized = false;
 
    	// Whether or not the GameScreen that owns the component
	    // should draw it
        public bool Visible = true;
 
	    // This overloaded constructor allows us to specify the parent
        public Component(GameScreen Parent)
        {
            InitializeComponent(Parent);
        }
 
	    // This overload allows will set the parent to the default
	    // GameScreen
        public Component()
        {
            InitializeComponent(Engine.DefaultScreen);
        }
 
        // This is called by the constructor to initialize the
        // component. This allows us to only have to override this
        // method instead of both constructors
        protected virtual void InitializeComponent(GameScreen Parent)
        {
            // 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");
 
            Parent.Components.Add(this);
            Initialized = true;
        }
 
	    // Updates the component - This is called by the owner
        public virtual void Update()
        {
        }
 
	    // Draws the component - This is called by the owner
        public virtual void Draw()
        {
        }
 
    	// Unregisters the component with its parent
        public virtual void DisableComponent()
        {
            Parent.Components.Remove(this);
        }
    }
}

This should be pretty self explantory, the important thing to know is that a component is owned by a GameScreen, who calls the component’s update and draw methods every frame.

Having a clearly defined base class helps us avoid common mistake #2 - Not having a class that the engine knows how to work with. If your engine is made up of a bunch of differently formatted classes, then you have to worry about how each component will be updated, drawn etc. Having a base class means that all we have to do is inherit from it, change the update and draw a little bit, and the engine will draw, update, and manage the component for us, without any extra code. This is also useful because every component in the game can be accessed using the type of the base class, even if it is actually a terrain, sky, or anything else. This greatly simplifies our update, render, and component management logic.

Component Interfaces

The next thing we are going to do is define some interfaces for our components. An interface is a way of defining how an object interacts with other objects. It also lets us distinguish between types of objects. The interfaces we will be defining here are I2DComponent and I3DComponent. This allows to tell the engine if our component uses 2D or 3D for drawing and updating. It also allows the engine to get some basic information about an object’s position, rotation, etc. This simplifies things like picking (detecting what a mouse clicked on or what is under a target reticle), and things like adding modifiers in an editor to control position, rotation, etc.

We will also be defining an enum that will list various types of object groups: 2D, 3D, Both, and All. We can use this enum later on for things like rendering water. When drawing the reflections for water, we don’t want to have the HUD elements drawn with it in the reflection, so we can use this enum like this: Engine.Draw(ComponentType.Component3D); This will draw only 3D objects, so the HUD will not be drawn in the reflection. This lets us avoid common misake #3 - Having a base class, but not providing a way to tell the engine anything useful about it. By providing these interfaces, we can modify an object’s position, rotation, scale, etc. regardless of what kind of component it is. The code for the interfaces and object type enum are below. Add these into a new file called ObjectType.cs

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
using Microsoft.Xna.Framework;
 
namespace Innovation
{
    // Represents a 3D object. These objects will be drawn before 
    // 2D objects, and will have modifiers automatically provided 
    // in the editor.
    public interface I3DComponent
    {
        // Position in the Cartesian system (X, Y, Z)
        Vector3 Position { get; set; }
 
        // Rotation represented as a Vector3. This shouldn't
        // be used for calculations, it is left in so that
        // the rotation can be more easily modified by hand
        Vector3 EulerRotation { get; set; }
        // Rotation as a Matrix. This will give much smoother
        // and cleaner calculations that a Vector3
        Matrix Rotation { get; set; }
 
        // Scale for each axis (X, Y, Z)
        Vector3 Scale { get; set; }
 
        // BoundingBox to use for picking and pre-collision
        BoundingBox BoundingBox { get; }
    }
 
    // Represents a 2D object. These objects will be drawn after
    // 3D objects, and will have modifiers automatically provided
    // in the editor.
    public interface I2DComponent
    {
        Rectangle Rectangle { get; set; }
    }
 
    public enum ComponentType
    {
        // Represents all 2D components (I2DComponent)
        Component2D,
        // Represents all 3D components (I3DComponent)
        Component3D,
        // Represents all components that are either 2D or 3D
        // components
        Both,
        // Represents all components regardless of type
        All
    }
}

GameScreen

A GameScreen is a class that contains a group of components, and handles their updating, drawing, and input. It contains the properties BlocksDraw, BlocksInput, and BlocksUpdate. These can be used to control the screens that are “under” then if they are imagined as a stack of GameScreens, with the newest on top.

For example, if you add a new GameScreen with BlocksUpdate, BlocksInput, and BlocksDraw set to true, then you have effectively just created a pause menu. This can save huge amount of time because it is very easy to create screens like this that control those under them. There is no need to create a complex state system to keep track of what the game is doing. We can just add new screens and change their properties to suit our needs.

This brings us to common mistake #4 - Not segregating code into clearly defined sections and creating an overly complex state management system. While this may seem like overkill, and for smaller games it certainly is, this system is extemely flexible and can be expanded with very little effort.

While this kind of state management could be built into the final game itself and not managed by the engine, by including it right into engine itself, we get a flexible design provided right inside the engine, and we have a framework to design our game around.

So, without further ado, here’s the code for the GameScreen. Add it to a new file called GameScreen.cs:

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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace Innovation
{
    public class GameScreen
    {
        // Keep track of all the components we need to manage
        public ComponentCollection Components;
 
        // Whether or not to draw
        public bool Visible = true;
 
        // Whether or not this screen should block the update of
        // screens below (for pause menus), etc.
        public bool BlocksUpdate = false;
 
        // Whether or not this screen can override a blocked update
        // from an above screen (for a background screen), etc.
        public bool OverrideUpdateBlocked = false;
 
        // Same for drawing
        public bool BlocksDraw = false;
 
        // Same for drawing
        public bool OverrideDrawBlocked = false;
 
        // Same for input
        public bool BlocksInput = false;
 
        // Same for input
        public bool OverrideInputBlocked = false;
 
        // Whether or not we want to block our own input so we can
        // do things like loading screens that will want to accept
        // input at some point, but not at startup
        public bool InputDisabled = false;
 
        // This is set by the engine to tell us whether or not input
        // is allowed. We can still get input, but we shouldn't. This
        // is useful because a ProcessInput() type of function would
        // make it hard to manage input (because we can't utilize
        // events, etc.)
        public bool IsInputAllowed = true;
 
        // The name of our component, set in the constructor. This
        // is used by the Engine, because a GameScreen can be accessed
        // by name from Engine.GameScreens[Name].
        public string Name;
 
        // Fired when the component's Initialize() is finished. This can
        // be hooked for things like asynchronous loading screens
        public event EventHandler OnInitialized;
 
        // Whether or not the component is initialized. Handles firing of
        // OnInitialized.
        bool inititalized = false;
        public bool Initialized
        {
            get { return inititalized; }
            set
            {
                inititalized = value;
                if (OnInitialized != null)
                {
                    // Fire the OnInitalized event to let other's know we
                    // are done initializing
                    OnInitialized(this, new EventArgs());
                }
            }
        }
 
        // Constructor takes the name of the component
        public GameScreen(string Name)
        {
            // Setup our component collection
            Components = new ComponentCollection(this);
 
            // Register with the engine and set our name
            this.Name = Name;
            Engine.GameScreens.Add(this);
 
            // Initialize the component
            if (!Initialized)
                Initialize();
        }
 
        // Overridable function to initialize the GameScreen
        public virtual void Initialize()
        {
            this.Initialized = true;
        }
 
        // Update the screen and child Components
        public virtual void Update()
        {
            // Create a temporary list so we don't crash if
            // a component is added to the collection while
            // updating
            List<Component> updating = new List<Component>();
 
            // Populate the temporary list
            foreach (Component c in Components)
                updating.Add(c);
 
            // Update all components that have been initialized
            foreach (Component Component in updating)
                if (Component.Initialized)
                    Component.Update();
        }
 
        // Draw the screen and its components. Accepts a ComponentType
        // to tell us what kind of components to draw. Either 2D, 3D, or
        // both. (Useful for drawing a reflection into a render target
        // without 2D components getting in the way)
        public virtual void Draw(ComponentType RenderType)
        {
            // Temporary list
            List<Component> drawing = new List<Component>();
 
            foreach (Component component in Components)
            {
                if (RenderType == ComponentType.Both)
                {
                    // If the render type is both, we will draw all 2D or
                    // 3D components
                    if (component is I2DComponent || component is I3DComponent)
                        drawing.Add(component);
                }
                else if (RenderType == ComponentType.Component2D)
                {
                    // If the render type is 2D, we will only draw 2D
                    // components
                    if (component is I2DComponent)
                        drawing.Add(component);
                }
                else if (RenderType == ComponentType.Component3D)
                {
                    // If the render type is 2D, we will only draw 3D
                    // components
                    if (component is I3DComponent)
                        drawing.Add(component);
                }
                else
                {
                    // Otherwise, we will draw every component regardless of type
                    drawing.Add(component);
                }
            }
 
            // Keep a list of components that are 2D so we can draw them on top
            // of the 3D components
            List<Component> defer2D = new List<Component>();
 
            foreach (Component component in drawing)
                if (component.Visible && component.Initialized)
                {
                    // If the component is visible and is not loading itself..
                    if (component is I2DComponent)
                    {
                        // If it is 2D, wait to draw
                        defer2D.Add(component);
                    }
                    else
                    {
                        // otherwise, draw immediately
                        component.Draw();
                    }
                }
 
            // Draw 2D components
            foreach (Component component in defer2D)
                component.Draw();
        }
 
        // Disables the GameScreen
        public virtual void Disable()
        {
            // Clear out our components
            Components.Clear();
 
            // Unregister from the Engine's list
            Engine.GameScreens.Remove(this);
 
            // If the engine happens to have this screen set as the default
            // screen, set it to the background screen in the Engine class
            if (Engine.DefaultScreen == this)
                Engine.DefaultScreen = Engine.BackgroundScreen;
        }
 
        // Override ToString() to return our name
        public override string ToString()
        {
            return Name;
        }
    }
}

One thing to note here is input. We don’t want to limit our input by forcing it all into one function on the GameScreen, because we want to be able to take advantage of things like key press events. So, we have a boolean called IsInputAllowed. This will be calculated by the engine each frame, so when checking input we should also check to see if IsInputAllowed equals true before doing anything. Unless, of course, we want to ignore this to move a camera around in the background of the pause screen or something similar.

The GameScreen class has a member called Components, which is a ComponentCollection. This is a custom collection that handles the management of the Parent value for components when it is moved around various screens. The code for this collection is below. Add it to a file called ComponentCollection.cs:

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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
 
namespace Innovation
{
    // A custom collection for managing components in a GameScreen
    public class ComponentCollection : Collection<Component>
    {
        // The GameScreen to manage components for
        GameScreen owner;
 
        public ComponentCollection(GameScreen Owner)
        {
            owner = Owner;
        }
 
        // Override InsertItem so we can set the parent of the
        // component to the owner
        protected override void InsertItem(int index, Component item)
        {
            if (item.Parent != null && item.Parent != owner)
                item.Parent.Components.Remove(item);
 
            item.Parent = owner;
 
            base.InsertItem(index, item);
        }
 
        // Override RemoveItem so we can set the paren of
        // the component to null (no parent)
        protected override void RemoveItem(int index)
        {
            Items[index].Parent = null;
 
            base.RemoveItem(index);
        }
    }
}

In the next article, we’ll tackle the engine class itself. For now, read through and make sure you understand everything we have so far.

Download the Code for this Chapter

Back to Game Engine Tutorial Series


kick it at GameDevKicks.com


30 Responses to “XNA Game Engine Tutorial Series: #1 – Component and GameScreen”

  1.   Juan Campa Says:
      October 10, 2008 at 7:34 am

    Hey Sean, nice post, I like the BlockInput, BlockUpdate, BlockDraw idea. I’m curious, why didn’t you derive your Component Class from XNA’s GameComponent and/or use XNA’s GameComponentCollection? These classes are very handy, and manage UpdateOrder and DrawOrder among other things that can be quite important. One more thing, how do you handle time based updates/draws? XNA’s GameComponent.Update method gets a GameTime parameter, will you be adding these features later?. C ya.

  2.   Sean James Says:
      October 10, 2008 at 12:09 pm

    I didn’t derive from GameComponent because I’d like to allow the engine to function outside the Game class, because it is hard to get it work properly in an editor environment.

    As for game time, the Engine class will have a public GameTime object that gets updated at each draw and update. This means we can get the time outside of a function that accepts a GameTime object.

    So, you would get the game time through Engine.GameTime

  3.   Doug Shannon Says:
      October 11, 2008 at 8:16 am

    Sean, I was wondering if you could explain ‘public virtual void’ to me, I’m new and wasnt able to find an answer by googling it (which is rare).

    BTW Great tutorial, and am looking forward to the next one!

  4.   Sean James Says:
      October 11, 2008 at 9:12 am

    I would explain it to you, but the Microsoft documentation does a much better job than I could in one comment. Check out these links:

    http://msdn.microsoft.com/en-us/library/ms173121.aspx
    http://msdn.microsoft.com/en-us/library/ms173152(VS.80).aspx
    http://msdn.microsoft.com/en-us/library/1h3swy84(VS.71).aspx

    Hope they help

  5.   Doug Shannon Says:
      October 11, 2008 at 12:15 pm

    Ok, so I think I get it after a couple of hours of tutoring from microsoft. Basically When you set a class as virtual void, you are allowing its derrived classes to invoke their own methods (as long as they use override). This would be useful in the case that a derrived class needs to use some different code from its base class. correct?

  6.   Sean James Says:
      October 11, 2008 at 1:53 pm

    Basically, yes. The ‘virtual’ and ‘void’ are not related except that they both describe the function. Because it is ‘virtual’, derived classes can override the function. For example, our components will override update and draw to implement their own functionality.

    ‘void’ means that the function doesn’t return anything. If we had, for example, ‘int’ instead, then the function would return a number (using ‘return 57;’ for example, to return 57).

    ‘public’ means that the function is available outside the class. If it was ‘private’ or didn’t have any modifiers at all, then it would only be available inside the class.

  7.   Clueless Says:
      October 15, 2008 at 11:52 am

    Hi Sean. Thaks for this great series :)
    Just one thig I was wondering about is ComponentType.Both…
    If you stay with this Types All will be the same like Both. If you add more Types to the Enum the name Both will be quite confusing, won’t it? I guess naming it something like “Drawable” would be the better choice.

  8.   Sean James Says:
      October 15, 2008 at 6:54 pm

    We probably aren’t going to be adding more types to this enum, so I don’t see it being a problem. The reason I do this is that ComponentType.Both will only draw components that are either I3DComponent or I2DComponent, and will not draw a component that doesn’t inherit from either of them. This way, we can do things like render into a render target (for example, if we wanted to do split screen, we would need to render everything twice and draw the renders on different parts of the screen), without messing up other components. For example, we will be adding a frame rate component, which does some of it’s logic in it’s draw function. If we called Draw() on it before we were actually done drawing scene, we would get innacurate data from it. Thus, we have ComponentType.Both to act like ComponentType.All, but not draw components that explicitly say they want to be drawn.

  9.   Jim Says:
      November 8, 2008 at 7:03 am

    Would I be right in saying that after adding all the above code this should not yet build?

  10.   Sean James Says:
      November 8, 2008 at 10:33 am

    Correct. We haven’t added the Engine class yet. At the end of chapter 2 you should be able to build. :)

  11.   Jim Says:
      November 8, 2008 at 11:21 am

    Thats what i thought but i was a bit paranoid that maybe i’d messed something up :)

    Thanks.

  12.   Alex Says:
      November 14, 2008 at 12:12 am

    Awesome tutorial Sean – I have a decent grasp of a lot of small bits, but tieing it all together in a reusable engine environment is something I have no experience with — this is a great help!

  13.   Eldon Says:
      November 27, 2008 at 4:44 pm

    Sean, Thanks for this great tutorial. I started programming about 22 years ago, smalls games and such. I have since moved on as a business apps. developer. I have wanted to get back into game design / development for awhile. This will be a great start.

    Thanks again for your time and exp.

  14.   steve Says:
      December 27, 2008 at 1:55 pm

    Have been doing c# for a couple of years (business apps) but discovered XNA just the other day – great tutorial – makes good sense…

  15.   Neven Says:
      January 5, 2009 at 3:31 pm

    Hey Sean. Thanks for great series. Please keep em comming :D
    I just wanted to add tiny detail. In Component.cs it is missing “using System”, so Exception can be reached.
    Or other way, changing Exception to System.Exception

  16.   Joe Says:
      February 21, 2009 at 2:08 am

    I’ve been looking through your XNA game engine tutorials and they seem great. I’ve been programming for a while but I just started with C#. I wanted to point out something that gave me trouble though. When you create your two projects (InnovativeEngine and TestGame) you show an image of your project tree. In this image the Program.cs and the Game1.cs classes have been removed from the InnovativeEngine project. If the user removes these the code will not compile. After some searching online I found out that I needed to set the Output type of the InnovativeEngine project to Class Library in the project properties. That’s all. Keep up the good work.

  17.   Joe Says:
      February 21, 2009 at 2:10 am

    Well I feel like a horses puhtoot.

    “So, open up Visual Studio, and select File-New Project, and choose type XNA Windows Game Library, and choose a name.”

    It’s 5am. I’m sorry :-P

  18.   Dave Says:
      February 21, 2009 at 8:10 am

    Great tutorial, it is nice to see one that has more substance than “how to draw a model to the screen”. It is tutorials like this that will help beginner indie developers get to we they need to be. Thanks for all the information.

  19.   Jason Wieczorek Says:
      March 3, 2009 at 12:40 pm

    I was wondering about this tutorial, Im typing it all out but in my project words like using microsoft and bools set to true ora different colors than yours. Is this simply beacause you set the text colors? Im making the classes with the code files, is this wrong?

  20.   Sean Says:
      March 3, 2009 at 12:43 pm

    It’s because the wordpress plugin I use to post code gets using statements wrong. “using” should be blue and the text should be black, but it makes the text green. It also doesn’t make “true” and “false” blue like it should.

    You’re fine.

  21.   Ryan Duclos Says:
      March 15, 2009 at 6:56 pm

    Hey Sean,

    :applauds: honestly, I couldn’t believe this tutorial was for free. I have free access to a lot of the XNA books that are 40-50$ and none of them come close to this.

    Components.cs is missing “using System;” namespace otherwise compiler will complain that the exception you are throwing isn’t being recognized.

    Off to Chapter 2!

  22.   Ivo Coumans Says:
      March 22, 2009 at 10:07 am

    While I’m very new to both XNA and C#, and understand very little of what you’ve written, it really is one awesome tutorial.
    After rereading, discussing with a more experienced friend and rereading again I really think I understand now!

    Thank you very much for this great tutorial!

  23.   Xeroz23 Says:
      March 25, 2009 at 1:36 pm

    Hi, at the Components class i get 6 errors.

    Error 1 Newline in constant
    Error 2 ) expected
    Error 3 The name ‘Engine’ does not exist in the current context
    Error 4 The name ‘Engine’ does not exist in the current context
    Error 5 The type or namespace name ‘Exception’ could not be found (are you missing a using directive or an assembly reference?)
    Error 6 Only assignment, call, increment, decrement, and new object expressions can be used as a statement

    please, mail me or MSN me, alt_msn_erik(at)hotmail.com

    (at) because of spam protection.

  24.   haxpor Says:
      March 26, 2009 at 3:08 am

    Is it right, that this line

    public event EventHandler OnInitialized;

    which that method OnInitialized will be set from outside?

  25.   Joey Says:
      April 7, 2009 at 2:54 pm

    Amazing Tutorial… I’ve been working with Xna for about 8 Months now and I have ran into many of these mistakes. It’s great the way that you explain them in a way that makes sense.

    This is really the definitive Xna tutorial, because too many other tutorials only show how to make a single linear game. This gives you the Framework to make anything.

  26.   Yanko Says:
      April 13, 2009 at 3:46 pm

    Hey just wondering is this gonna show us how to make a game engine and use it ???in a small 3D game project?

  27.   Lazlo Says:
      April 13, 2009 at 8:25 pm

    -Great- tutorial. I’m only halfway through it, and I can’t stop reading. The only thing I miss is the “discover by yourself” part. Oh well. I guess I’ll get it sooner or later.

  28.   Lazlo Says:
      April 14, 2009 at 8:28 am

    I don’t understand how this part is helpful:

    // Create a temporary list so the engine doesn’t
    // crash if a component is added to the collection
    // while updating.
    List updating = new List();

    Why create a temporary list? I mean, you use all the components from it in the same function anyway o.o Sorry if I missed something.

  29.   Yanko Says:
      April 23, 2009 at 4:25 am

    are we allowd to use this engine anyhow we want?

  30.   Nick Says:
      May 12, 2009 at 11:32 am

    There is a bool variable named ‘inititalized’ (your spelling not mine) in the GameScreen class code, and its data access isnt set to public, private, or protected. So what does it mean? Also, is it spelt that way as a typo, or is there a genuine reason for it?

    thanks in advance
    Nick

comment Leave a Reply