Bill Reiss is a Windows Platform Development MVP and a Senior Consultant for AgileThought

MonoGame For Windows 8 Step 2 – Content

In the first post in this series we looked at getting the environment set up, and created a game based on the MonoGame (XAML) project template. Of course this game didn’t do anything except show a blank game surface but sometimes the first step is the hardest one to take. Over the past few years I’ve tried to think of ways to demystify game development since I frequently hear very experienced developers say that they don’t think they could actually write a game. Game development has a bit of a different way of thinking about it, especially compared to what .NET developers typically do on a daily basis.

Let’s think a bit about creating a “Hello World” in WPF. Typically what you would do is drop a button on the window, handle a click event,  and pop up a message box or change some text. This is event-based programming, you wait for something to happen and then act upon it.

In game programming, you often have things going on while you’re waiting for input. This could involve animations, processing the current position of objects based on physics, checking the network for the other player’s actions, and a myriad of other things. The most common model for game development is to do loop-based programming, specifically a game loop. A game loop is something that executes repeatedly on a timer for the life of the game. In XNA and MonoGame, there are actually what can be considered two game loops, the Update loop and the Draw loop. The Update loop calls the Update method repeatedly, and is where you would do things like check for input, kick off sound effects, call into the physics engine, etc. The Draw loop calls the Draw method once per frame for when the screen needs to be updated, and you need to draw everything every frame. If you don’t draw something when the Draw method is called, even if you drew it last time, it won’t show up. This may seem wasteful, but when there is a lot going on, let’s say a bunch of particle effects and a lot of things moving around, it would take more processing effort to try to keep track of where all of the elements are in a “visual tree” like WPF, Silverlight, WinForms or other similar technology uses.

I like to simplify game development in MonoGame or XNA into the following tasks:

  • Draw Stuff
  • Handle Input
  • Play Sounds

When you think of it this way, none of those tasks seems too daunting does it? I’d actually argue that getting familiar with event based programming is a lot more complicated and harder to grasp. If you took a complete novice to programming and tried to explain both types of programming I’d argue that game programming would have a shorter ramp-up time.

So let’s get start by drawing stuff.

Content in XNA and MonoGame

Since MonoGame is modeled after XNA and they want to make the bar as low as possible to port an XNA game to MonoGame, they have made a huge effort to be compatible with the content format that XNA uses. Content items in XNA are called “assets” and are packaged with the game as files with an XNB file extension. There is a special project type in XNA called a Content Project, and at compile time any assets in the content project are compiled into this standard XNB format that the XNA runtime understands. This simplifies the runtime significantly since it doesn’t need to know about all of the various content formats that XNA can accept. Take for example image formats. XNA content projects can accept BMP, JPG, TGA ,PNG and DDS out of the box, and you could even write your own custom content importer to support other formats. At run time, XNA only has to deal with the image format that all of these others are converted to at compile time.

Now even though the MonoGame runtime knows how to handle XNB files, there is nothing built into MonoGame currently to generate these files, although I think they plan on supporting this in the future. This means that you need to generate these XNB files using an XNA Content Project, and then add these XNB files to your MonoGame project.

This is where things get a little tricky for MonoGame on Windows 8. Since Windows 8 Store development doesn’t support XNA, Visual Studio 2012 doesn’t ship with the XNA project templates. In general it looks like Microsoft is moving away from XNA on all of its platforms. But all is not lost. One option is to install Visual Studio 2010 (or Express) side by side with Visual Studio 2012 and install XNA Game Studio 4.0 and build your content there, and then add it to your Visual Studio 2012 based MonoGame project. This isn’t ideal since you have to switch back and forth and have two solution files.

I’ve come up with a better idea. Since Windows Phone 8 can run Windows Phone 7.1 apps and games, and since Microsoft is still supporting developing XNA games for Windows Phone 7.1 in their Windows Phone 8 SDK, and since the Windows Phone 8 SDK runs on Visual Studio 2012, you can install the Windows Phone 8 SDK and then use the XNA Content Project support that ships with it to build your XNB files! This is a little tricky to set up but once it’s set up it’s pretty sweet so stick with me through this.

Download and install the free Windows Phone 8 SDK

Now, open up the solution we started in the last post. If you skipped it, you can get it here.

Add a new project to the solution of type Empty Content Project. You can find this under C#->XNA Game Studio 4.0. We’ll take the default name of “Content1”

image

Add a new project of type Windows Phone Game Library (4.0). We’ll call this “DummyLibrary” since its only use is so that we can harvest the XNB files.

  image

Delete the Class1.cs file from the DummyLibrary project, we don’t need it.

Right click on the DummyLibrary project node in the Solution Explorer. Select Add Content Reference…

image

Choose Content1.

image

Now go to Solution Properties and Project Dependencies. For MyFirstGame, select that it depends on DummyLibrary. This will ensure that the DummyLibrary project (and therefore the XNB files) will be compiled before the game project.

image

Now to actually add the content. We want an image we can draw. Let’s borrow one from the XNA Platformer Starter kit.

Run

Click on this image which will open it up in a new window and then save it as Run.png.

Now in the Content1 project, Select Add Existing Item and select Run.png.

Build the solution. This will generate the XNB file we need.

Add a new folder named Content to the MyFirstGame project.

On the Content folder, select Add Existing Item. Navigate to the DummyLibrarybinWindows PhoneDebugContent1 folder and make sure the filter is set to All Items. Select the Run.xnb file, and then Add As Link.

image

By using Add As Link instead of Add, when this file changes the MyFirstGame project will automatically pick up these changes.

Now one last thing. Since Visual Studio doesn’t know what to do with an XNB file added to a project, it sets its Build Action to None, so you need to manually set the Build Action of Run.xnb to Content instead.

image

Ok so now we’re finally able to use this content. In the future to add more content, which we’ll see in a later post, all you’ll need to do is add it to the content project, do a build, and then go to the Content folder of your game, and add the XNB file “As Link”, and set the Build Action to Content.

SpriteBatch

This series of posts will focus strictly on 2D games in MonoGame. The main reason for this is that the level of complexity for game development goes up exponentially once you get into 3D. Also some of the most popular games ever are 2D games, so your best best is probably to build one of these first before moving on to 3D. That being said, MonoGame has good support for most of XNA’s 3D APIs, and if you run into anything it doesn’t support you can put in a request for them to add it.

When writing 2D games in XNA or MonoGame, you are actually still using 3D, but there is an abstraction layer put on top of this that makes it feel like a 2D surface. This means if you wanted to, you could mix 2D and 3D graphics and this is commonly done for things like a heads up display (score, health, etc).

To make writing 2D games easier, XNA (and consequently MonoGame) provides a SpriteBatch class. The SpriteBatch class provides APIs for drawing images and text, so you will be using it extensively in your 2D games.

If you look in the Game1.cs file, you’ll see that the default template declares a SpriteBatch object for you.

        SpriteBatch _spriteBatch;

And in the LoadContent method, it is instantiated:

        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
        }

Notice the comment says “draw textures”. Bitmaps or images in XNA are referred to as Textures, and for the textures that we’re going to draw with the SpriteBatch we need to load them into Texture2D objects. So let’s declare a Texture2D as a field in the Game1 class:

        Texture2D player;

and then in the LoadContent method, we’ll instantiate it by telling the content manager to load it.

 

            player = Content.Load<Texture2D>("Run");

By default, the content manager looks in the Content folder, and the asset name is the file name without the extension by default. If you wanted a different asset name (which would also change the file name of the XNB file) you can change this in the content project in the item’s property pane.

image

Note that in XNA and in MonoGame for Windows 8, asset names are not case sensitive, so “run”, and “Run” point to the same file. On MonoGame for Android, this is not the case so be careful.

Now to draw this texture. As the “batch” in the name SpriteBatch implies, drawing is done as a batch. This means you draw one or many things, and then tell it you’re done, and then at that point it actually goes off and does the drawing. So before you begin drawing, you need to tell SpriteBatch to Begin the batch, and then once done, call End. If you don’t do this nothing will draw and you’ll likely get runtime errors.

In the Draw method, add the following:

            _spriteBatch.Begin();
            _spriteBatch.Draw(player, Vector2.Zero, Color.White);
            _spriteBatch.End();

This draws the texture object we called “player” at position 0,0 on the screen (top left corner) with a color of white. In the next post we’ll get more into vectors and colors along with other fun things SpriteBatch can do, but for now let’s just run this and you should see the following:

image

Click here for the solution as of this point.

That’s it for now, tune in next time for more fun with SpriteBatch.

  • http://www.facebook.com/CromWhoCaresForNothing David Cole

    So the other day after reading your first blog posts in this series, I got started moving one of my XNA projects to Mono Game and was perplexed by the lack of a Content project.  It turns out that MonoGame is perfectly capable of loading content without the need for an XNB file.  I’m not sure if there’s any drawback to this approach, but I simply dropped my images in the assets folder and loaded them from there.

    • http://billreiss.com/ Bill Reiss

      Interesting, thanks for pointing that out. It looks like you can do this for images but it doesn’t work for sound effects, fonts, and I would guess some of the other asset types. It can however be useful for images since many times the XNB file is larger in size than the corresponding image file, and so you may want to mix and match the two. 

    • http://twitter.com/GnomicStudios Gnomic Studios

      Loading of raw assets such as this is not strictly speaking “supported” by MonoGame. Although it works, the MonoGame team plan to remove this feature once the full content pipeline build system is supported. If this happens, you can still support it by creating a custom ContentManger which calls Texture2D.FromStream() when it fails to find a Xnb texture file.

      Bill: Thanks for this post. I’m moving to Win8 shortly so this information will be most useful.

      • http://www.facebook.com/CromWhoCaresForNothing David Cole

         Thanks for clarifying, that’s good to know.

      • http://billreiss.com/ Bill Reiss

        Thank you very much for clarifying and I’m kind of glad it didn’t completely invalidate what I did here :)

  • Martin

    So, are you guys all using VS Pro or above? Using the above method of adding an XNA Studio project to the solution doesn’t work for me using the express editions since XNA Project is VS Express for Windows Phone and MonoGame is VS Express For Windows 8, and you can’t mix and match them. VS Express point blank refuses…

    • http://billreiss.com/ Bill Reiss

      Apologies, I guess if you’re using Express you’ll have to have 2 separate solutions. Since adding content is a fairly uncommon occurrence, it’s more of an annoyance than anything. There are many ways to get VS2012 for free if you’re in the US, such as BizSpark, DreamSpark, and I think WebsiteSpark. I’m unsure what kinds of offers like this exist in other countries.

      • Martin.

        Thanks Bill – I knew of DreamSpark but don’t qualify, but didn’t know of the others. I’m a Software Architect for a big multi-national (that is still VS2010 based – and that’s not likely to change any time soon), so also don’t qualify for the BizSpark, but I do look after a club website for a local organisation that I wrote in ASP.NET so I’ll investigate and see if the WebsiteSpark may cover me.

        If not, I guess separate solutions isn’t too big of a deal. It would be pretty straightforward too if I could add a post build step on the content project (to copy the resources) but actually, I’ve a feeling that’s not available in the Express versions either.

        Just very interested to follow along and have a tinker since I’ve done a lot with old arcade games in the past :)

        • http://www.facebook.com/CromWhoCaresForNothing David Cole

           Does the multi-national that you work for supply you with an MSDN license?  Often times large companies do provide their Software Engineers and the like with these.  If so, you could get it from there.

          • http://www.facebook.com/sychris.lee Chris Lee

            Yeah, that’s how I’ve got my VS2012 installation going

          • http://www.guddler.co.uk/ Martin White

            Sorry, missed this as wasn’t subscribed. No, currently just VS2010 Pro, no MSDN. MSDN was mentioned at one point but the cogs move slowly sometimes :) Plus I couldn’t just install it on my home machine anyway, and I can’t venture into Windows 8 / gaming code etc. on the work machine.

  • http://www.facebook.com/sychris.lee Chris Lee

    One question Bill, and maybe I’m preempting the next article a little bit, but I am guessing you’re going to animate the player by splicing (or is cropping the correct term?) the one big image? I am guessing because from another XNA tutorial ( http://xbox.create.msdn.com/en-US/education/tutorial/2dgame/getting_started ) this is exactly what they did. 

    My question is, is there a reason why one big image is used like that? Isn’t it better to hold an array of Texture2D’s, hold those in memory and just loop the array? Wouldn’t splicing the one image use up unnecessary CPU cycles to work out which frame to show?

    • http://billreiss.com/ Bill Reiss

      Haha yes you’re jumping ahead. I have already written the first part of the next post where I discuss that very subject. To sum it up, there is significant overhead when copying a texture from the CPU accessible memory to the GPU memory, and this far outweighs the very small amount of CPU cycles required to calculate which frame to show.

      • http://www.facebook.com/sychris.lee Chris Lee

        One more question if you can indulge me.

        The one big png file with all the frames, how would you go about creating an image like that? I successfully animated something, but I used the Texture2D array method, but since you say it’s terribly inefficient, I’ve been trying to convert the images into one. 

        Just want to know is there some go-to tool that you use for this, as I imagine it’s a fairly common scenario? Or do you just use Photoshop, increasing canvas@twitter-106071270:disqus
        size and pasting the pictures in one by one (which is what I am doing)?

  • scoy6

    Hi Bill, I love the idea of using the phone contents project to get around MonoGame not having content projects yet but do you have any way around the fact that the phone content projects don’t support custom shaders?
    Also, is there any way to have a library project work with MonoGame?

    Thanks!

  • Yuki

    ah, this indeed is a great tutorial :O
    i hope some day i can be as talented as you Bill
    Avatar Games</a