Kategorien
Game developement

XNA 4 tutorial: Simple game engine

The first XNA 4 tutorial is about creating a game engine structure and how to draw a simple scene on the screen.

Game engine structure

A default XNA project already comes with a small structure, a game loop which is split into an Update and a Draw method:

  • The Update method contains the game logic, moves game objects and handles user input.
  • The Draw method draws all game objects on the screen.

Moreover there are two methods which are called once when the game is started:

  • The Initialize method which setups the game objects.
  • The LoadContent method which loads external data from files like models, shaders, textures or sounds.

For this tutorial the default XNA project will be extended by three additionally components:

[singlepic id=2127 float=none]

Input

An input component handles any hardware input source like keyboard, mouse or gamepad. There may be more than one input component, in order to implement different input behaviour. Each input component is derived from GameComponent, so its Update method is automatically called from the XNA framework. In order to make the user input independent from the framerate, it should always be scaled with the elapsed game time. An input component can control any entity object(s) provided. Entity object? See next.

class EntityInputComponent : GameComponent
{
    public IMoveableEntity Entity { get; set; }

    private KeyboardState currentKeyboardState;

    public override void Update(GameTime gameTime)
    {
        currentKeyboardState = Keyboard.GetState();

        // Decouple input from framerate
        var translationStep = 0.01f * gameTime.ElapsedGameTime.Milliseconds; 

        if (currentKeyboardState.IsKeyDown(Keys.Up))
        {
            Entity.Translate(Vector3.Up, translationStep);
        }

        if (currentKeyboardState.IsKeyDown(Keys.Down))
        {
            Entity.Translate(Vector3.Down, translationStep);
        }

        if (currentKeyboardState.IsKeyDown(Keys.Left))
        {
            Entity.Translate(Vector3.Left, translationStep);
        }

        if (currentKeyboardState.IsKeyDown(Keys.Right))
        {
            Entity.Translate(Vector3.Right, translationStep);
        }

        if (currentKeyboardState.IsKeyDown(Keys.PageUp))
        {
            Entity.Translate(Vector3.Forward, translationStep);
        }

        if (currentKeyboardState.IsKeyDown(Keys.PageDown))
        {
            Entity.Translate(Vector3.Backward, translationStep);
        }

        base.Update(gameTime);
    }
}

Entity

An entity represents a physical object within the simulated world like walls, trees, cars, avatars and so on. It contains its own visual representation, its world location and moving behaviour (velocity, acceleration, collision). In a future tutorial the entity object will be extended with a physics engine.

Camera

A camera represents the eye of the user. Everything in front of the camera will be projected on the screen (more exactly: everything within the view frustrum). A camera is usually not visible but behaves like other entity objects, so it implements the same entity object interfaces. Since every camera has its own location, view and projection matrix, the game engine can be easily extented with a camera manager enabling the user to switch between several cameras or having a picture in picture feature.

Depending on the game, there are different types of cameras:

  • First person (ego perspective)
  • Third person (fixed behind an entity object)
  • Spectator (free fly)
  • Overhead (top down)

This tutorial uses a free flying spectator camera, this behaviour can be changed by replacing the input component and maybe a derived camera class with restricted movement constraints.
Please see following camera related web resources for further implementation details:

Setting up a scene

This simple game engine just puts all described game components together in order to draw an Entity object on the screen. The Entity object can be controlled by an Entity input component. The visual part of the Entity is loaded into the game by using the XNA content pipeline: the mesh is loaded from a .fbx file and is saved in a XNA Model class. In order to make things visible lighting is added by a BasicEffect. The BasicEffect will be replaced with a custom shader effect in the upcoming tutorial lesson.

Finally here is an outline of the game engine. For further details please download the source code which can be found at the bottom of this article.

protected override void Initialize()
{
    // Initialize camera
    Camera = new QuaternionCamera(MathHelper.ToRadians(45.0f), GraphicsDevice.Viewport.AspectRatio, 1.0f, 1000.0f);

    // Initialize input components
    CameraInputComponent = new CameraInputComponent(this);
    CameraInputComponent.Entity = Camera;
    Components.Add(CameraInputComponent);

    EntityInputComponent = new EntityInputComponent(this);
    Components.Add(EntityInputComponent);

    base.Initialize();
}

protected override void LoadContent()
{
    var effect = new BasicEffect(GraphicsDevice);
    effect.EnableDefaultLighting();
    effect.AmbientLightColor = Color.Blue.ToVector3();
    var sphereModel = Content.Load("models/sphere");
    SphereEntity = new ModelEntity(effect, sphereModel);

    EntityInputComponent.Entity = SphereEntity; // Enables user to move the sphere
}

protected override void Update(GameTime gameTime)
{
    // Rotates the entity around itself continuously
    SphereEntity.Rotate(Vector3.UnitY, gameTime.ElapsedGameTime.Milliseconds * 0.01f); 
    base.Update(gameTime);
}

protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.Black);
    SphereEntity.Draw(gameTime, Camera.View, Camera.Projection);
    base.Draw(gameTime);
}

Resources


Download solution files