28. June 2015

 

In this chapter we are going to explore handling input from the keyboard, mouse and gamepad in your MonoGame game.  XNA/MonoGame also have support for mobile specific input such as motion and touch screens, we will cover theses topics in a later topic.

 

There is an HD video of this chapter available here: [coming soon]

 

XNA input capabilities were at once powerful, straightforward and a bit lacking.  If you come from another game engine or library you may be shocked to discovered there is no event driven interface out of the box for example.  All input in XNA is done via polling, if you want an event layer, you build it yourself or use one of the existing 3rd party implementations.  On the other hand, as you are about to see, the provided interfaces are incredibly consistent and easy to learn.

 

Handling Keyboard Input

 

Let’s start straight away with a code sample:

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System.Text;

namespace Example1
{
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Vector2 position;
        Texture2D texture;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            base.Initialize();
            position = new Vector2(graphics.GraphicsDevice.Viewport.
                       Width / 2 -64, 
                                    graphics.GraphicsDevice.Viewport.
                                    Height / 2 -64);
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            texture = this.Content.Load<Texture2D>("logo128");
        }

        protected override void UnloadContent()
        {
        }

        protected override void Update(GameTime gameTime)
        {
            // Poll for current keyboard state
            KeyboardState state = Keyboard.GetState();
            
            // If they hit esc, exit
            if (state.IsKeyDown(Keys.Escape))
                Exit();

            // Print to debug console currently pressed keys
            System.Text.StringBuilder sb = new StringBuilder();
            foreach (var key in state.GetPressedKeys())
                sb.Append("Key: ").Append(key).Append(" pressed ");

            if (sb.Length > 0)
                System.Diagnostics.Debug.WriteLine(sb.ToString());
            else
                System.Diagnostics.Debug.WriteLine("No Keys pressed");
            
            // Move our sprite based on arrow keys being pressed:
            if (state.IsKeyDown(Keys.Right))
                position.X += 10;
            if (state.IsKeyDown(Keys.Left))
                position.X -= 10;
            if (state.IsKeyDown(Keys.Up))
                position.Y -= 10;
            if (state.IsKeyDown(Keys.Down))
                position.Y += 10;

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin();
            spriteBatch.Draw(texture, position);
            spriteBatch.End();
            base.Draw(gameTime);
        }
    }
}

 

We are going to re-use the same basic example for all the examples in this chapter.  It simply draws a sprite centered to the screen, then we manipulate the position in Update()

image

 

In this particular example, when the user hits keys, they are logged to the debug console:

image

 

Now let’s take a look at the keyboard specific code.  It all starts with a call to Keyboard.GetState(), this returns a struct containing the current state of the keyboard, including modifier keys like Control or Shift.  It also contains a method named GetPressedKeys() which returns an array of all the keys that are currently pressed.  In this example we simply loop through the pressed keys, writing them out to debug.  Finally we poll the pressed state of the arrow keys and move our position accordingly.

 

Handling Key State Changes

One thing you might notice with XNA is you are simply checking the current state of a key.  So if a key is pressed or not.  What if you only want to respond when the key is first pressed?  This requires a bit of work on your behalf.

    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Vector2 position;
        Texture2D texture;
        KeyboardState previousState;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            base.Initialize();
            position = new Vector2(graphics.GraphicsDevice.Viewport.
                       Width / 2 -64, 
                                    graphics.GraphicsDevice.Viewport.
                                    Height / 2 -64);

            previousState = Keyboard.GetState();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            texture = this.Content.Load<Texture2D>("logo128");
        }

        protected override void Update(GameTime gameTime)
        {
            KeyboardState state = Keyboard.GetState();
            
            // If they hit esc, exit
            if (state.IsKeyDown(Keys.Escape))
                Exit();

            // Move our sprite based on arrow keys being pressed:
            if (state.IsKeyDown(Keys.Right) & !previousState.IsKeyDown(
                Keys.Right))
                position.X += 10;
            if (state.IsKeyDown(Keys.Left) & !previousState.IsKeyDown(
                Keys.Left))
                position.X -= 10;
            if (state.IsKeyDown(Keys.Up))
                position.Y -= 10;
            if (state.IsKeyDown(Keys.Down))
                position.Y += 10;

            base.Update(gameTime);

            previousState = state;
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin();
            spriteBatch.Draw(texture, position);
            spriteBatch.End();
            base.Draw(gameTime);
        }
    }

 

The changes to our code are highlighted.  Essentially if you want to check for changes in input state ( this applies to gamepad and mouse events too ), you need to track them yourself.  This is a matter of keeping a copy of the previous state, then in your input check you check not only if a key is pressed, but also if it was pressed in the previous state.  If it isn’t this is a new key press and we respond accordingly.  In the above example on Left or Right arrow presses, we only respond to new key presses, so moving left or right requires repeatedly hitting and releasing the arrow key.

 

Handling Mouse Input

Next we explore the process of handling Mouse input.  You will notice the process is almost identical to keyboard handling.  Once again, let’s jump right in with a code example.

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System.Text;

namespace Example2
{
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Vector2 position;
        Texture2D texture;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            base.Initialize();
            position = new Vector2(graphics.GraphicsDevice.Viewport.
                       Width / 2 ,
                                    graphics.GraphicsDevice.Viewport.
                                    Height / 2 );

            
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            texture = this.Content.Load<Texture2D>("logo128");
        }

        protected override void Update(GameTime gameTime)
        {
            MouseState state = Mouse.GetState();

            // Update our sprites position to the current cursor 
            location
            position.X = state.X;
            position.Y = state.Y;

            // Check if Right Mouse Button pressed, if so, exit
            if (state.RightButton == ButtonState.Pressed)
                Exit();

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin();
            spriteBatch.Draw(texture, position, origin:new Vector2(64,
                             64));
            spriteBatch.End();
            base.Draw(gameTime);
        }
    }
}

 

When you run this example, the texture will move around relative to the location of the mouse.  When the user clicks right, the application exits.  The logic works almost identically to handling Keyboard input.  Each frame you check the MouseState by calling Mouse.GetState().  This MouseState struct contains the current mouse X and Y as well as the status of the left, right and middle mouse buttons and the scroll wheel position.  You may notice there are also values for XButton1 and XButton2, these buttons can change from device to device, but generally represent a forward and back navigation button.  On devices with no mouse support, X and Y will always be 0 while each button state will always be set to ButtonState.Released. If you are dealing with a multi touch device this code will continue to work, although the values will only reflect the primary (first) touch point.  We will discuss mobile input in more detail in a later chapter.  As with handling Keyboard events, if you want to track changes in event state, you will have to track them yourself.

 

If you add the following code to your update, you will notice some interesting things about the X,Y position of the mouse:

        protected override void Update(GameTime gameTime)
        {
            MouseState state = Mouse.GetState();

            // Update our sprites position to the current cursor 
            location
            position.X = state.X;
            position.Y = state.Y;

            System.Diagnostics.Debug.WriteLine(position.X.ToString() + 
                                   "," + position.Y.ToString());
            // Check if Right Mouse Button pressed, if so, exit
            if (state.RightButton == ButtonState.Pressed)
                Exit();

            base.Update(gameTime);
        }

The X and Y values are relative to the Window’s origin.  That is (0,0) is the top left corner of the drawable portion of the window, while (width,height) is the bottom right corner.  However, if you are in a Windowed app, the mouse pointer location continues to be updated, still relative to the top left corner of the application window.

image

 

You can also set the position of the cursor in code using the following line:

            if(state.MiddleButton == ButtonState.Pressed)
                Mouse.SetPosition(graphics.GraphicsDevice.Viewport.
                                  Width / 2,
                    graphics.GraphicsDevice.Viewport.Height / 2);

 

This code will center the mouse position to the middle of the screen when the user presses the middle button.

 

Finally its common to want to display the mouse cursor, this is easily accomplished using:

            IsMouseVisible = true;

This member of the Game class toggles the visibility of the system mouse cursor.

image

 

 

Handling Gamepad Input

 

Now we will look at handling input from a gamepad or joystick controller.  You probably wont be surprised to discover the process is remarkably consistent.

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System.Text;

namespace Example3
{
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Vector2 position;
        Texture2D texture;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            base.Initialize();
            position = new Vector2(graphics.GraphicsDevice.Viewport.
                       Width / 2,
                                    graphics.GraphicsDevice.Viewport.
                                    Height / 2);
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            texture = this.Content.Load<Texture2D>("logo128");
        }

        protected override void Update(GameTime gameTime)
        {
            if (Keyboard.GetState().IsKeyDown(Keys.Escape)) Exit();

            // Check the device for Player One
            GamePadCapabilities capabilities = GamePad.GetCapabilities(
                                               PlayerIndex.One);
            
            // If there a controller attached, handle it
            if (capabilities.IsConnected)
            {
                // Get the current state of Controller1
                GamePadState state = GamePad.GetState(PlayerIndex.One);

                // You can check explicitly if a gamepad has support 
                for a certain feature
                if (capabilities.HasLeftXThumbStick)
                {
                    // Check teh direction in X axis of left analog 
                    stick
                    if (state.ThumbSticks.Left.X < -0.5f) 
                        position.X -= 10.0f;
                    if (state.ThumbSticks.Left.X > 0.5f) 
                        position.X += 10.0f;
                }

                // You can also check the controllers "type"
                if (capabilities.GamePadType == GamePadType.GamePad)
                {
                    if (state.IsButtonDown(Buttons.A))
                        Exit();
                }
            }
            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin();
            spriteBatch.Draw(texture, position, origin: new Vector2(64,
                             64));
            spriteBatch.End();
            base.Draw(gameTime);
        }
    }
}

 

When you run this example, if there is a controller attached, pressing left or right on the analog stick with move the sprite accordingly.  Hitting the A button (or pressing Escape for those without a controller) will cause the game to exit.

 

The logic here is remarkably consistent with Mouse and Keyboard event handling.  The primary difference is the number of controllers attached and the capabilities of each controller can vary massively, so the code needs to responding appropriately.  In the above example, we check only for the first controller attached, by passing PlayerIndex to our GetEvents call.  You can have up to 4 controllers attached, and each needs to be polled separately. 

 

Supported Gamepads


On the PC there are a plethora of devices available with a wide range of capabilities. You can have up to 4 different controllers attached, each accesible by passing the appropriate PlayerIndex to GetEvents(). The following device types can be returned:

  • AlternateGuitar
  • ArcadeStick
  • BigButtonPad
  • DancePad
  • DrumKit
  • FlightStick
  • GamePad
  • Guitar
  • Unknown
  • Wheel


Obviously each devices supports a different set of features, which can be polled invdividually using the GamePadCapabilities struct returned by Gamepad.GetCapabilities().


Buttons on a GamePad controller are treated just like Keys and MouseButtons, with a value of Pressed or Released.  Once again, if you want to track changes in state you need to code this functionality yourself.  When dealing with Analog sticks, the value returned is a Vector2 representing the current position of the stick.  A value of 1.0 represents a stick that is fully up or right, while a value of –1.0f represents a stick that is full left or down.  A stick at 0,0 is un-pressed.

 

There is a small challenge with dealing with analog controls however that you should be aware of.  Even when a stick is not pressed, it is almost never at the position (0.0f,0.0f), the sensors often return very small fluctuations from complete zero.  This means if you respond directly to input without taking into account these small variations, your sprites will “twitch” while they are supposed to be stationary.  This is worked around using something called a dead zone.  This is a range of motions, or motion values, that are considered too small to be registered.  You can think of a deadzone as a value that is “close enough to zero to be considered zero”.

 

You have a couple options with XNA/MonoGame for dealing with deadzones.  The default is IndependentAxis, which compares each axis against the deadzone separately, Circular which combines the X and Y values together before comparison to the dead zone (recommended for controls the use both axis together, such as a thumbstick controlling 3D view), and finally None, which ignores the deadzone completely.  You would generally choose None if you don’t care about a dead zone, or wish to implement it yourself.

           GamePadState state = GamePad.GetState(PlayerIndex.One, 
                                GamePadDeadZone.Circular);

 

As you can see, XNA's Input handling is somewhat sparse compared to other game engines, but does provide the building blocks to make more complex systems if required. The approach to handling input across devices is remarkably consistent, making it easier to use and hopefully resulting in less unexpected behavior and bugs.

 

 

The Video

[Coming Soon]

Programming , , ,

15. June 2015

 

In this chapter we are going to look closely at the structure of a typical XNA game.  By the end you should have a better idea of the life cycle of a typical MonoGame application, from program creation, loading content, the game loop, unloading content and exiting.

 

If you prefer videos to text, you can watch this content in HD video right here.

 

Let’s start by looking at the code for an automatically generated application, stripped of comments.  There are two code files in the generated project, Program.cs and [YourProjectName].cs.  Let’s start with Program.cs

using System;

namespace Example1
{
#if WINDOWS || LINUX
    public static class Program
    {
        [STAThread]
        static void Main()
        {
            using (var game = new Game1())
                game.Run();
        }
    }
#endif
}

The heart of this code is the creation of our Game object, then calling it’s Run() method, which starts our game executing, kicking off the game loop until the Game execution finishes.  We will talk about the game loop in a bit more detail later on.  Otherwise this is a standard C# style application, with Main() being the applications entry point.  This is true for  Windows and Linux applications at least, which is the reason for the #if  preprocessor directive.  We will discuss the entry point of various other platforms later on, so don’t worry about this too much.  Also note, if you didn’t select Windows as your platform when creating this project, your own Program.cs file contents may look slightly different.  Again, don’t worry about this right now, the most important thing is to realize that Program creates and runs your Game derived class.

Predefined Platform Values

One of the major features of MonoGame over XNA is the addition of several other supported platforms. In addition to WINDOWS and LINUX symbols, the following platforms have been defined:

  • ANDROID
  • IOS
  • LINUX
  • MONOMAC
  • OUYA
  • PSM
  • WINDOWS
  • WINDOWS_PHONE
  • WINDOWS_PHONE81
  • WINDOWSRT
  • WEB

Of course, new platforms are being added all of the time, so this list may not still be current. You can look up the definitions in the MonoGame sources in the file /Build/Projects/MonoGame.Framework.definition in the MonoGame GitHub repository.

Please note, there are plenty of other defines per platform, for example iOS, Android, MacOS, Ouya and WindowsGL all also define OPENGL. You can use these predefined symbols for implementing platform or library specific code.

Now let's move on to our Game class

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace Example1
{
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
        }

        protected override void UnloadContent()
        {
        }

        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == 
                ButtonState.Pressed || Keyboard.GetState().IsKeyDown(
                Keys.Escape))
                Exit();
            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            base.Draw(gameTime);
        }
    }
}

Our game is derived from the class Microsoft.Xna.Framework.Game and is the heart of our application. The Game class is responsible for initializing the graphics device, loading content and most importantly, running the application game loop. The majority of our code is implemented by overriding several of Game’s protected methods.

 

Let’s take a look at the code, starting from the top.  We create two member variables, graphics and spriteBatch.  GraphicsDeviceManager requires a reference to a Game instanceWe will cover the GraphicsDeviceManager and SpriteBatch classes shortly in the graphics chapter, so please ignore them for now.

 

Next we override the Initialize(), LoadContent and UnLoadContent methods.  The most immediate question you’ve probably got is, why have an Initialize() method at all, why not just do initialization in the constructor.  First, behavior of calling a virtual function from a constructor can lead to all kinds of hard to find bugs in a C# application.  Second, you don’t generally want to do any heavy lifting in a constructor.  The existence of LoadContent() however, will often leave you will an empty Initialize() method.  As a general rule, perform inititalizations that are required ( like GraphicsDeviceManager’s allocation ) for the object to be valid in the constructor, perform long running initializations ( such as procedural generation of terrain ) in Initialize() and load all game content in LoadContent().

 

Next we override Update() and Draw(), which is essentially the heart of your application’s game loop.  Update() is responsible for updating the state of your game world, things like polling input or moving entities, while Draw is responsible for drawing your game world.  In our default Update() call, we check for the player hitting the back button or escape key and exit if they do.  Don’t worry about the details, we will cover Input shortly.  In Draw() we simply clear the screen to CornFlower Blue ( an XNA tradition ).  You will notice in both examples we call the base class as well.

 

What's a game loop?


A game loop is essentially the heart of a game, what causes the game to actually run. The following is a fairly typical game loop:

void gameLoop(){
   while (game != DONE){
      getInput();
      physicsEngine.stepForward();
      updateWorld();
      render();
   }
   cleanup();
}

 

As you can see, it's quite literally a loop that calls the various functions that make your game a game.  This is obviously a rather primitive example but really 90% of game loops end up looking very similar to this.

 

However, once you are using a game engine or framework, things behave slightly different.  All this stuff still happens, it’s just no longer your code’s responsibility to create the loop.  Instead the game engine performs the loop and each iteration it then calls back to your game code. This is where the various overridden function such as update() and draw() are called.  Looking at our sample loop above though, you might notice a physics engine call.  XNA doesn’t have a built in physics engine, so instead of the game loop updating the physics, you will have to do it yourself in your games update() call.

 

When you run this code you should see:

image

 

Please note, depending on what platform you are running on, this window may or may not be created full screen.  On Windows it defaults to windowed, while on MacOS it defaults to full screen.  Hit the Escape key, or Back button if you have a controller installed, to exit the application.

 

Let’s take a quick look at a program’s lifecycle with this handy graphic.

programFlow

In a nutshell the game is created, initialized, content is loaded, the game loop runs until Exit() is called, then the game cleans up and exits.  There are actually a few more methods behind the scenes, such as BeginDraw() and EndDraw(), but for most games, this is sufficient detail.

 

Our current example isn’t exactly exciting because absolutely nothing happens.  Let’s create a slightly more interesting example, one that draws a rectangle on screen and rolls it across the screen.  Don’t worry about the specifics, we will cover graphics in more detail shortly.

 

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

// This example simply adds a red rectangle to the screen
// then updates it's position along the X axis each frame.
namespace Example2
{
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Texture2D texture;
        Vector2 position;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            position = new Vector2(0, 0);
        }

        protected override void Initialize()
        {
            texture = new Texture2D(this.GraphicsDevice, 100, 100);
            Color[] colorData = new Color[100 * 100];
            for (int i = 0; i < 10000; i++)
                colorData[i] = Color.Red;

            texture.SetData<Color>(colorData);
            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
        }

        protected override void UnloadContent()
        {
        }

        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == 
                ButtonState.Pressed || Keyboard.GetState().IsKeyDown(
                Keys.Escape))
                Exit();

            position.X += 1;
            if (position.X > this.GraphicsDevice.Viewport.Width)
                position.X = 0;
            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin();
            spriteBatch.Draw(texture,position);
            spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}

 

When we run this we will see:

gif1

 

Nothing exciting, but at least our game does something now.  Again, don’t worry overly about the details of how, we will cover this all later.  What we want to do is look at a few key topics when dealing about dealing with the game loop. 

 

Pausing Your Game

 

Pausing your game is a pretty common task, especially when an application loses focus.  If you take the above example, minimize the application, then restore it and you will notice the animation continued to occur, even when the game didn’t have focus.  Implementing pause functionality is pretty simple though, let’s take a look at how:

        protected override void Update(GameTime gameTime)
        {
            if (IsActive)
            {
                if (GamePad.GetState(PlayerIndex.One).Buttons.Back == 
                    ButtonState.Pressed || Keyboard.GetState().
                    IsKeyDown(Keys.Escape))
                    Exit();
                position.X += 1;
                if (position.X > this.GraphicsDevice.Viewport.Width)
                    position.X = 0;
                base.Update(gameTime);
            }
        }

Well that was simple enough.  There is a flag set, IsActive, when your game is active or not.  The definition of IsActive depends on the platform it’s running. On a desktop platform, an app is active if its not minimized AND has input focus.  On console it’s active if an overlay like the XBox guide is not being shown, while on phones it’s active if it’s the running foreground application and not showing a system dialog of some kind.  As you can see, the can pause the game by simply not performing Game::Update() calls.

 

There may be times when you wish to perform some activity when you gain/lose active status.  This can be done with a pair of event handlers:

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            position = new Vector2(0, 0);

            this.Activated += (sender, args) => {  this.Window.Title = 
                              "Active Application"; };
            this.Deactivated += (sender, args) => { this.Window.Title 
                                = "InActive Application"; };
        }

Or by overriding the functions OnActivated and OnDeactivated, which is the recommended approach:

        protected override void OnActivated(object sender, System.
                                            EventArgs args)
        {
            this.Window.Title = "Active Application";
            base.OnActivated(sender, args);
        }

        protected override void OnDeactivated(object sender, System.
                                              EventArgs args)
        {
            this.Window.Title = "InActive Application";
            base.OnActivated(sender, args);
        }
 

Controlling the Game Loop

Another challenge games face is controlling the speed games run at across a variety of different devices.  In our relatively simple example there is no problem for two reasons.  First, it’s a very simple application and not particularly taxing, meaning any machine should be able to run it extremely quickly.  Second, the speed is actually being capped by two factors, we are running at a fixed time step ( more on that later ) and we have vsync enabled, which on many modern monitors, refresh at a 59 or 60hz rate.  If we turn both of these features off and let our game run at maximum speed, then suddenly the speed of the computer it’s running on becomes incredibly important:

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            position = new Vector2(0, 0);
            this.IsFixedTimeStep = false;
            this.graphics.SynchronizeWithVerticalRetrace = false;
        }

 

By setting IsFixedTimeStep to false and Graphics.SyncronizeWithVerticalRetrace to false, our application will now run as fast as the game is capable.  The problem is, this will result in our rectangle being drawn extremely fast and at different speeds on different machines.  We obviously don’t want this, but fortunately there is an easy fix.  Take a look at Update() and you will notice it is being passed in a GameTime parameter.   This value contains the amount of time that occurred since the last time Update() was called.  You may also notice Draw() also has this parameter.  This value can be used to smooth out motion so it runs at a consistent speed across machines.  Let’s change our update call so position instead of being ++’ed each frame, we now move at a fixed rate, say 200 pixels per second.  That can be accomplished with this change to your Update() position code:

position.X += 200.0f * (float)gameTime.ElapsedGameTime.TotalSeconds;

TotalSeconds will contain the fraction of a second that have elapsed since Update() was last called, assuming of course your game is running at at least 1 frame a second!  For example, if your game is updating a 60hz ( second times per second ), then TotalSeconds will have a value of 0.016666 ( 1/60 ).  Assuming your stays pretty steady at 60fps, this results in your Update code updating the position by 3.2 pixels per frame ( 200 * 0.016 ).  However, on a computer running at 30fps, this same logic would then update position by 6.4 pixels per frame ( 2000 * (1/30) ).  The end result is the behavior of the game on both machines is identical even though one draws twice as fast as the other.

The GameTime class contains a couple useful pieces of information:

image

ElapsedGameTime holds information on how much time has happened since the last call to Update (or Draw,  completely separate values by the way ).  As you just saw, this value can be used to normalize behavior regardless to how fast the underlying machine actually performs.  The value TotalGameTime on the other hand is the amount of time that elapsed since game started, including time spend paused.  Finally there is the IsRunningSlowly flag, which is set if the game isn’t hitting it’s target elapsed time, something we will discuss momentarily.  Game also has a property called InactiveSleepTime, which along with TotalGameTime can be used to calculate the amount of time a game spent running.

 

Fixed Vs. Variable TimeStep

 

Finally let’s discuss using a FixedStep game loop instead.  Instead of messing with all of this frame normalization stuff you can instead say “Hey, Monogame, I want you to run my game at this speed” and it will do it’s best.  Lets look at this process:

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            position = new Vector2(0, 0);
            this.IsFixedTimeStep = true;
            this.graphics.SynchronizeWithVerticalRetrace = true;
            this.TargetElapsedTime = new System.TimeSpan(0, 0, 0, 0, 33); // 33ms = 30fps
        }

This will then try to call the Update() exactly 30 times per second.  If it can’t maintain this speed, it will set the IsRunningSlowly flag to true.  At the same time, the engine will try to call Draw() as much as possible, but if the machine isn’t fast enough to hit the TargetElapsedTime it will start skipping Draw() frames, calling only Update() until it’s “caught up”.  If your  You can control the maximum amount of draw calls that will be skipped per Update() by setting MaxElapsedTime.  This value is a MonoGame specific extension and is not in the original XNA.  If you don’t specify a TargetElapsedTime, the default is 60fps (1/60).

 

Ultimately the decision between using a Fixed Step game loop or not is ultimately up to you.  A fixed step game loop has the advantage of being easier to implement and provides a more consistent experience.  A variable step loop is a bit more complicated, but can result in smoother graphics on higher end machines.  The result is more pronounced on a 3D game than a 2D one, resulting in smoother controls and slightly cleaner visuals.  In a 2D game the difference is much less pronounced.

 

In the next chapter we will move on to the much more exciting topic of 2D graphics.

 

The Video

Programming , , ,

14. June 2015

 

Welcome to a brand new series on GameFromScratch.com covering the MonoGame open source game framework.  Over the next several chapters we will cover almost every factor of using MonoGame for game development.  First we are going to start with a bit of a history lesson and introduction to MonoGame; we’ll talk about where it came from and why you should care.  Don’t worry, we will get to the code and the technical bits very soon!

 

For the more visually inclined there is also an HD video version covering mostly the same material we will discuss here.

 

So what exactly is MonoGame?  The simple answer is, it’s a cross platform, open source implementation of the XNA game libraries.   XNA in turn was Microsoft’s indie focused 2D/3D game library.  A more complex answer than that requires a bit of a history lesson.

 

A Brief History of XNA

 

XNA stands for XNA’s Not Acronymed, a recursive algorithm and very much on vogue at the time (think GNU or WINE).  Although the more likely reason for the name is X’s were really just quite cool at the time, XBox, X Games, XXX the Movie…  XNA was announced at the Game Developer Conference (GDC) in 2004 as a great and accessible way to bring game development to the masses.  At the time however, we instead got (what eventually became) MS Build and they open sourced the source code and all assets for the game MechCommander 2.  However two years later XNA Game Studio was finally released.

 

So what exactly was XNA Game Studio?  First off, it was a special version of Visual Studio for C# with an integrated pipeline for importing game assets.  On top of that, it was a collection of .NET libraries aimed at making games, covering facets like input handling, graphics, audio and networking.  Finally it was a special .NET runtime capable of running on PC, (eventually) Windows Phone and perhaps most importantly, XBox 360.  That was the big selling point…  XNA enabled basically anybody to make games for a game console.  Outside of the very limited edition ( and much more expensive ) Net Yaroze ( a special version of the PlayStation 1), nobody had ever done this.  You could argue that XNA more than any other single release, gave rise to the burgeoning indie development scene we have today.

 

What makes XNA even more impressive is realizing the world it was released in.  Game engines certainly existed, Unreal was AAA only and several million dollars per title, Unity was I believe still a Mac only product and several hundred dollars per seat.  Several of the prominent open source libraries of today simply didn’t exist back then.  Plus the IDE XNA itself was based on, Visual Studio,  cost a few thousand dollars.  XNA really did bring console game development to the masses and many of the “big” indie games, titles like Fez, Braid and Terraria were create using XNA.

 

It wasn’t all roses though, and even though Microsoft basically invented the indie developer market, it quickly pissed it away too.  XNA titles, without a publisher agreement, were confined to Xbox Indie Games channel as well as Windows Phone stores.  The Xbox IG channel quickly became a dumping ground, discovery became a huge factor and very few developers made money.  With the release of XBox One, it seems Sony stole Microsoft’s crown as the place for indie developers to shine.

 

Worse, and this is a story that could fill a book on it’s own, there was a shake up at Microsoft and several technologies ended up having their plug pulled.  XNA was one of them.  Sadly, in Oct 2011, with XNA Game Studio 4.0 refresh, XNA saw it’s final release. 

 

So then, a dead and unsupported technology… why the heck should we care?  Simple… XNA was… is good.  Very good.  Plus “unsupported” isn’t exactly the right word to used.  Enter…

 

A Brief History of MonoGame

 

So XNA became very popular very quickly.  There was a large and growing community, several books available on the subject and new versions being released.  Hands down the biggest limitation were the supported platforms, XNA was very much tied to Microsoft platforms and a limited subset at that.  This lead to twoimage different projects, SilverSprite and XNA Touch.  The first was an attempt to make a code compatible version of XNA (at least, the 2D bits) that could be run in the browser using Silverlight.  The other was a port of XNA to run on an OpenGL back end on mobile devices.  XNA Touch ended up using the 2D code from Silver Sprite and the two eventually emerged as MonoGame.

 

This was several years ago and since then MonoGame has grown into a nearly 100% complete implementation of XNA 4 that can be run on several platforms ( Windows DirectX, Windows OpenGL, Mac, Linux, Android, iOS, PlayStation Vita, PlayStation 4, OUYA and more ).  The biggest hanging point has always been the content pipeline.  Until recently you’ve needed to keep an old version ( and a PC ) Game Studio around to convert your assets into the binary XNB format.  However, near the end of 2014 the MonoGame team provided that final missing piece with the release of their own cross platform content pipeline tool.    It will be interesting to see what the future holds now that the MonoGame team have basically implemented 100% of XNA.  The future of XNA is now theirs to determine.

 

 

Why should I use MonoGame?

 

So, that was a bit of XNA history for you.  The biggest question you may have now is… “So what?  Why should I use XNA/MonoGame today?”

 

Sometimes it is often easier to start with why you shouldn’t use something.  The following are the biggest reasons I can think of not to use MonoGame.

  • You want a WYSIWYG environment or integrated game editor
  • You don’t like C#
  • You want a higher level programming experience
  • There is a price tag attached to support iOS and Android

 

Those are probably the biggest drawbacks of using XNA.  There is no world editor.  In fact, there are very few tools at all, except content importers.   Even the libraries themselves are fairly low level, leaving you to roll your own sprite and animation classes for example.  XNA is also not the easiest library to learn, especially compared to many scripting languages or all in one solutions like GameMaker or Construct.  That coding is done in C# ( or other Mono supported languages like F#, but 99% of examples are in C# ), so if you aren’t a fan of that language, you wont like MonoGame.  Finally, and perhaps worst, targeting iOS or Android requires a Xamarin license, and that costs money.

 

So that’s why you shouldn’t use MonoGame, now why you should.

 

First off, because XNA was and is just a great library!  It was well designed, very clean and works well.  Simply put, if you like working in C# ( and I do, very much ), working in XNA is just a very pleasant coding experience.  You work at a lower level of abstraction than many of todays game engines, but after being around for about a decade, there are a huge amount of code samples and libraries to fill those pieces.  The core though, those pieces every game needs, they are all provided.  If you are the type of person that likes to have maximum control, to dig in deep and get your finger nails dirty, you’ll feel right at home!

 

Also, MonoGame provides access to pretty much every single platform you’d want to target today.  One of the scary things about working with some open source game project is, you never know how well they will work in the real world.  Fortunately, MonoGame has an pretty impressive resume of shipped titles, such as:

  • Bastion
  • Fez
  • Infinite Flight
  • Skulls of the Shogun
  • Transistor

Some of the biggest selling indie game, from both the past and the present, prove that MonoGame is capable. 

 

So basically MonoGame is a battle proven cross platform indie friendly code focused C# based game engine built on the bones of Microsoft’s XNA.  Now, let’s jump into the technical aspects and you can see why I am such a big fan of the XNA libraries in the first place.  Along the way we will cover the way MonoGame does things differently, and look at some of the unique concerns that cross platform development bring.  Next however, let’s look at getting MonoGame up and running on your platform of choice.

 

The Book

 

While I am compiling this tutorial series on GameFromScratch.com, I am also compiling the entire series for an e-book release.   In the end the tutorial series and the book will contain virtually identical content.  I will be compiling new WIP releases of the book as I go and those will be made available to Patreon backers as a thank you reward.  So if you enjoy this series but would prefer it offline or printed in a PDF or Kindle/Kobo friendly format, or if you simply wish to help support GameFromScratch (or both!), your support is certainly appreciated.  Once the series is “complete”, I will do a formal compilation with proper forward, index and table of contents and make this book available on popular book stores for purchase.  Basically I am publishing a book in the open, while I develop it.  Just instead of the traditional model, this one is available completely free and has a video tutorial series to go along with it!

 

As always, your feedback is appreciated.  If you have any requests, comments or suggestions, please let me know and I will see what I can do!

 

The Video

Programming , , ,

10. June 2015

 

This tutorial is a quick guide on getting MonoGame up and running on Windows OS.  The process is incredibly straight forward, with two options on how to proceed.

 

First you are going to need a development environment, of which two options are available.  Xamarin’s Xamarin Studio or Microsoft’s Visual Studio.  If you wish to go the Xamarin Studio route, be sure to check the MacOS guide, as the process will be virtually identical.  The rest of this tutorial assumes that you chose to install Visual Studio, the industry standard IDE for Windows development which is now thankfully available for free.

 

So first things first, download and install Visual Studio 2013 Community.  Be sure that you select Community and not one of the 90 trial editions.  The community install is a complete and full functioning version of Visual Studio, but with some limitations on the size of your company.

 

As of time of writing, this is the version you want.

image

 

If you want to talk a walk on the wild side, the release candidate of Visual Studio 2015 will also work.  Of course, it’s a release candidate… so buyer beware. 

Installing either with the minimal recommendations or better will get you all that you need installed.

 

Install using the Installer

 

By far the easiest option, simply download and run the installer available here.  Be sure to shut down Visual Studio before installing.

Click Next, then agree to the EULA… after you read it and submit it to your lawyer for approval of course…

Next you will be prompted for the features you want installed.  The defaults are pretty solid, click Install:

image

 

 

Install using NuGet

Visual Studio integrates a package manager called NuGet.  This offers a few (potential) benefits over using the library’s standalone installer.

  • dependency resolution.  If it depends on other libraries, NuGet can handle those dependencies
  • package updating abilities.  Keep yourself up to date easier

Actually, that’s about it.  Basically if you want to be kept up to date on updates, this is the route to go.  The install process is certainly more complicated though, at least initially.

First of course you need the NuGet package manager installed.  It’s getting more and more common in use, so you will probably have it installed or need it installed shortly.   It is available as a Visual Studio extension or command line utility.

To install with NuGet, Launch Visual Studio, on first run you may have to make some configuration choices, don’t worry, most of these can be revisited later on.  Once configured, select the menu Tools->NuGet Package Manager->Package Manager Console:

image

Now you simply install the packages you want.  Unlike the installer you download the various packages independently.   The list of packages are available here.  Assuming you are going to develop initially on Windows, you probably want to start with the DirectX Windows version.  To install that in the Package Manager Console type:

Install-Package MonoGame.Framework.WindowsDX

This will download and install all the required files and dependencies.  For more details on the MonoGame NuGet packages please read this post on StackOverflow by the maintainer.

 

Your First Project

Now that you’ve got MonoGame installed let’s create our first project.  If not already done, load up Visual Studio.

 

Select File->New Project

image

 

In the resulting dialog, on the left hand side under installed templates, select Visual C#->MonoGame, then on the right hand side select MonoGame Windows Project, pick a location, a project name, if you want source control, then click OK.

image

 

As you can see, MonoGame ships out of the box with templates for a number of different targets and a few above may require a bit of an explanation.  The MonoGame Windows Project targets Windows desktop using Direct X for the backend.  The OpenGL project is another Windows target, but instead using OpenGL as the backend.  As DirectX is Windows, XBox and WinPhone only, you may find using the GL backend the most consistent if targeting Mac, Linux, Android and/or iOS, as those all use OpenGL on the back end.  A Windows 8.1 Universal project is an application that supports both Win 8 desktop and mobile targets with one code base, and if I am honest, with the announcement of Windows 10, is probably a complete dead end.

 

Ideally you will write most of your code as libraries, with only the platform specific portions in their own corresponding project file.  We will look at this process closer down the road.  For now we will KISS (Keep It Simple Stupid) and just target the platform we are developing on.

 

Once you click OK, the following simple project will be created:

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace Game1
{
    /// <summary>
    /// This is the main type for your game.
    /// </summary>
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to 
        before starting to run.
        /// This is where it can query for any required services and 
        load any non-graphic
        /// related content.  Calling base.Initialize will enumerate 
        through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place 
        to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw 
            textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the 
        place to unload
        /// game-specific content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing 
        audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing 
                        values.</param>
        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == 
                ButtonState.Pressed || Keyboard.GetState().IsKeyDown(
                Keys.Escape))
                Exit();

            // TODO: Add your update logic here

            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing 
                        values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            // TODO: Add your drawing code here

            base.Draw(gameTime);
        }
    }
}

 

Don’t concern yourself overly with the code, we will explain it all shortly.  We just want to make sure that your MonoGame install is up and running.  To run your game hit F5 or press:

image

Assuming all went well, you should see a window drawn in CornFlower blue:

image

Congratulations, you’ve just created your first ever MonoGame application!

 

Let’s talk briefly about the Content Pipeline.  This is the way you get content into your MonoGame application.  If you look in the Solution Explorer, you will see a file named Content.mgcb.

image

 

Double click it, and the MonoGame Content Pipeline tool will open:

image

 

Let’s quickly add a texture to our project.  Select Edit->Add->Existing Item, navigate to an existing image file somewhere on your computer.

image

 

Next you will be prompted for how you want the file to be added, copied or linked, I chose copy to break the connection with the source image.  This means updates to the original image will not be propagated, nor will deleting it have any effect.

image

 

The image will be added to your content bundle, as as you can see with it selected, there are a number of properties exposed for how the image should be processed when building content:

image

There are several Import processors available for various different file types:

image

 

Each one exposes different parameters you can modify.  For images some of the key properties exposed are the option to automatically resize the image to a power of 2 dimension, to change the texture compression settings (TextureFormat) or setting the color key value used for transparencies.

Now select the Content root node and you will see the property details have changed:

image

The key setting here is Platform.  Each different platform can have slightly different requirements and the Content Pipeline takes care of that for you.  In this case we already have Windows set for the pipeline, so there is nothing that needs to be changed.

 

Now Build your content using the Buld->Build menu option, or by hitting F6.

image

 

Now back in Visual Studio, confirm that the build action on your Content.mgcb file is set correctly.  Right click the file and select Properties:

image

 

Make sure that Build Action is set to MonoGameContentReference.

image

 

This will enable you to use the content as if it was installed locally, making switching between platform versions trivial.

 

Now actually using content in code is as simple as:

 protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            var myImage = this.Content.Load<Texture2D>("SBO6h0Gk");
        }

Don't worry, we will cover this process in more detail later. Just note that the file extension is not used.

Behind the scenes, you may notice that the Content Pipeline tool created the following xnb file in the /bin/Windows subdirectory of Content:

image

Programming , ,

9. June 2015

 

In this tutorial we are going to look at getting a MonoGame development environment up and running on MacOS, create and run our first MonoGame application and finally take a quick look at the Content Pipeline tool.

 

For those that prefer video, there is a video version of this tutorial available here or embedded below.

 

The Installation Process

In order to get up and running there are a couple things you need to install, Mono itself then MonoGame.  We will also be installing Xamarin Platform, which includes Xamarin’s cross platform Mono based IDE Xamarin Studio.  It is not strictly required, but will make your life a great deal simpler.

 

The process is as straight forward as installs can get, simple download an run each installer.  There is not ambiguity to the install, however the install order is extremely important.  Download the following in this order.  In each case be sure to install the most recent version if given an option.

 
As I said earlier, there should be nothing complicated about any of those installs, except the order.  If you install out of order the proper templates for MonoGame won’t get added to Xamarin Studio.
 
 

Our First Project

Now let’s fire up Xamarin Studio and create our first application.  Once Xamarin loads, select New Solution...
 
Ss1
 
 
In the resulting dialog, next select the project template to get started.  Along the left hand side scroll down and locate Other->Miscellaneous. On the right hand side you should see a number of preconfigured MonoGame templates.  For this example we are going to target only Mac OS using Xamarin’s Mac libraries, so select MonoGame Mac Application (Xamarin.Mac), then click Next.
 
Ss2
 
 
All that remains is to pick a location and name for your application as well as if you want Git control or not.  When ready click Create.
Ss3
 
 
This should create a simple application for us with the following code:
#region Using Statements
using System;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.Input;

#endregion

namespace HelloMonoGame
{
  /// <summary>
  /// This is the main type for your game.
  /// </summary>
  public class Game1 : Game
  {
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;

    public Game1 ()
    {
      graphics = new GraphicsDeviceManager (this);
      Content.RootDirectory = "Content";
      graphics.IsFullScreen = true;
    }

    /// <summary>
    /// Allows the game to perform any initialization it needs to 
    before starting to run.
    /// This is where it can query for any required services and load 
    any non-graphic
    /// related content. Calling base.Initialize will enumerate 
    through any components
    /// and initialize them as well.
    /// </summary>
    protected override void Initialize ()
    {
      // TODO: Add your initialization logic here
      base.Initialize ();
        
    }

    /// <summary>
    /// LoadContent will be called once per game and is the place to 
    load
    /// all of your content.
    /// </summary>
    protected override void LoadContent ()
    {
      // Create a new SpriteBatch, which can be used to draw textures.
      spriteBatch = new SpriteBatch (GraphicsDevice);

      //TODO: use this.Content to load your game content here 
    }

    /// <summary>
    /// Allows the game to run logic such as updating the world,
    /// checking for collisions, gathering input, and playing audio.
    /// </summary>
    /// <param name="gameTime">Provides a snapshot of timing values.<
                    /param>
    protected override void Update (GameTime gameTime)
    {
      // For Mobile devices, this logic will close the Game when the 
      Back button is pressed
      // Exit() is obsolete on iOS
      #if !__IOS__
      if (GamePad.GetState (PlayerIndex.One).Buttons.Back == 
          ButtonState.Pressed ||
          Keyboard.GetState ().IsKeyDown (Keys.Escape)) {
        Exit ();
      }
      #endif
      // TODO: Add your update logic here 
      base.Update (gameTime);
    }

    /// <summary>
    /// This is called when the game should draw itself.
    /// </summary>
    /// <param name="gameTime">Provides a snapshot of timing values.<
                    /param>
    protected override void Draw (GameTime gameTime)
    {
      graphics.GraphicsDevice.Clear (Color.CornflowerBlue);
    
      //TODO: Add your drawing code here
            
      base.Draw (gameTime);
    }
  }
}

 
We aren’t going to go into any specifics of what this code does, not yet anyways, but we will make sure that it runs.  Hit the Play icon in the top control bar:
 
Ss4 
 
You should now see a full screen cornflower blue window.  If so, congratulations, you just successfully made your first Monogame application!
 

The Content Pipeline

 

The content pipeline was a major component missing from MonoGame, but they have recently implemented one.  The Content Pipeline takes external assets for your game, be them videos, textures, sounds, fonts, etc…  converts them for your platform of choice, generating a XNB file, a binary format that XNA used internally.  Let’s take a look at the process in MonoGame.

 

If you look under the Content folder of your Solution, you will see a file called Content.mgcb. 

Ss5

 

Double click this and the Content Pipeline tool will load:

Ss6

 

This is the tool you use to assemble the assets your game is going to use.  Let’s take a quick example of importing a texture.

 

First select Edit->Add->Existing Item...

Ss7

 

Browse to the image you wish to import as a texture then select OK.

Screen Shot 2015 06 09 at 12 35 35 PM

 

Now you will be asked how you wish to import the file.  I want a copy to be made so the original is unaffected.

Screen Shot 2015 06 09 at 12 36 41 PM

 

Your texture should now be added:

Screen Shot 2015 06 09 at 12 37 09 PM

 

You now have a few options about how the content will be processed on import.  With the image selected, notice the options available below it:

Screen Shot 2015 06 09 at 12 38 17 PM

 

Each different importer has a different set of parameters you can modify.  Here you can set the automatic generation of mip maps, resize to power of 2 dimensions, change the compression settings, etc.

 

By selecting the Importer drop down you can get an idea of the various type of assets supported by the Content Pipeline:

Screen Shot 2015 06 09 at 12 40 04 PM

 

Now select the Content node and the properties available will change again.  This time we simply want to change the target platform to MacOS:

Screen Shot 2015 06 09 at 12 41 11 PM

 

You can have the Content Pipeline automatically process content for a variety of different platforms.  Now that this task is done let’s actually build our content.  Simply select Build->Build or hit F6:

Screen Shot 2015 06 09 at 12 42 08 PM

 

In the directory [Content]/bin/MacOSX there will now be an XNB file available for use.  Let’s add it to our project.

 

In Xamarin Studio, right click the Content folder and select Add->Add Files...

Screen Shot 2015 06 09 at 12 44 15 PM

 

Navigate to the XNB file in Content/bin/MacOSX that you just created and select it.  Then select Override Build action and choose ‘Content'

Screen Shot 2015 06 09 at 12 46 11 PM

 

This time when prompted how to add the file, choose the Link option:

Screen Shot 2015 06 09 at 12 47 57 PM

 

Congratulations, you have now added an asset to your game.  In future tutorials we will look at using them in more detail.

The Video Version

, , ,

Month List

DisqusCommentsSummary