<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Sgt. Conker &#187; RPG</title>
	<atom:link href="http://www.sgtconker.com/tag/rpg/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.sgtconker.com</link>
	<description>We are &#34;absolutely fine&#34;</description>
	<lastBuildDate>Wed, 06 Jul 2011 13:29:44 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Article: Vacant Skies &#8211; Action RPG Tutorial Series</title>
		<link>http://www.sgtconker.com/2010/09/article-vacant-skies-action-rpg-tutorial-series/</link>
		<comments>http://www.sgtconker.com/2010/09/article-vacant-skies-action-rpg-tutorial-series/#comments</comments>
		<pubDate>Sat, 18 Sep 2010 20:51:57 +0000</pubDate>
		<dc:creator>Absolutely Fine Tutorial Contest</dc:creator>
				<category><![CDATA[2010 Contest Entries]]></category>
		<category><![CDATA[Articles]]></category>
		<category><![CDATA[Contest]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[XNA]]></category>
		<category><![CDATA[Aaron T Foley]]></category>
		<category><![CDATA[Absolutely Fine Tutorial Contest]]></category>
		<category><![CDATA[Action]]></category>
		<category><![CDATA[Article]]></category>
		<category><![CDATA[Day Night Cycle]]></category>
		<category><![CDATA[GameStateManagement]]></category>
		<category><![CDATA[RPG]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[Vacant Skies]]></category>

		<guid isPermaLink="false">http://www.sgtconker.com/?p=1764</guid>
		<description><![CDATA[by Aaron T Foley

Welcome to the Vacant Skies – Action RPG Tutorial Series.  My name is Aaron Foley and I’ll be your host throughout this series.  The primary purpose of the series is to document a route on how to make a complete action RPG using XNA and various resources throughout the internet. [...]]]></description>
			<content:encoded><![CDATA[<h4 style="text-align: center;">by <a href="mailto:slyprid@roadrunner.com">Aaron T Foley</a></h4>
<p style="text-align: center;"><img class="aligncenter" title="Day Night Cycle" src="http://www.sgtconker.com/wp-content/uploads/contest/2010/rpg/part4/4.png" alt="" width="768" height="432" /></p>
<p>Welcome to the Vacant Skies – Action RPG Tutorial Series.  My name is Aaron Foley and I’ll be your host throughout this series.  The primary purpose of the series is to document a route on how to make a complete action RPG using XNA and various resources throughout the internet.  There are so many amazing resources out there now for XNA that it is pointless to keep reinventing the wheel when writing a game.  So I’m going to collect various tutorials, code, and libraries and utilize them all to create a game.  So let’s get this show on the road.</p>
<p><span id="more-1764"></span></p>
<p>First off we need to determine some of our base resources we will be using.  Most will already have these, but if you don’t there are links that can direct you to where you can get them.  I’ll be linking to the Express editions of Visual C#, but will be using Visual Studio for the tutorials. I also will be using XNA Game Studio 3.1 for now until XNA Game Studio 4.0 comes out.  Once 4.0 comes out, these will be switched over to using XNA 4.0 and Visual Studio 2010.</p>
<h2>Resources</h2>
<ul>
<li><a href="http://www.microsoft.com/express/Downloads/#Visual_Studio_2008_Express_Downloads">Visual C# Express Edition</a></li>
<li> <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=80782277-d584-42d2-8024-893fcd9d3e82&amp;displaylang=en">XNA Game Studio 3.1</a></li>
<li><a href="http://www.getpaint.net/">Paint .NET</a></li>
</ul>
<p>Once we have all these installed, we can begin.</p>
<p><strong>Download: <a href="http://www.sgtconker.com/wp-content/uploads/contest/2010/rpg/part1/Part1_Resources.zip">Part1_Resources.zip</a></strong></p>
<p>To start we will need to create a new project using the Windows Game (3.1) template.<br />
<a href="http://www.sgtconker.com/wp-content/uploads/contest/2010/rpg/part1/1.png"><img class="alignnone" title="New Project" src="http://www.sgtconker.com/wp-content/uploads/contest/2010/rpg/part1/1.png" alt="" width="100%" /></a></p>
<p>I like to use my <a href="http://dropbox.com">Dropbox </a>for storing my projects, but you can store them where ever you feel like.  So once that is created we will have our base application.</p>
<p>Next we will need to add another project to our solution.  This will be our helper library and will store code and classes we will use throughout our game. So add a new project to our solution and select Windows Game Library (3.1) from our Templates and name it.</p>
<p><a href="http://www.sgtconker.com/wp-content/uploads/contest/2010/rpg/part1/2.png"><img class="alignnone" title="New Game Library" src="http://www.sgtconker.com/wp-content/uploads/contest/2010/rpg/part1/2.png" alt="" width="100%" /></a></p>
<p>Now in our main application we need to add the library reference to references and in the content references.</p>
<p>So now we have our base project ready.  So let’s get our hands dirty.</p>
<p>For our first resource we need some way of managing what state our game is in.  There is a wonderful sample on the XNA Creators Club site that handles this great.  So let’s go get that and implement it into our game.</p>
<p><a href="http://creators.xna.com/en-us/samples/gamestatemanagement"><strong> </strong></a><strong><a>Game State Management Sample</a> </strong></p>
<p>To start we will be using the graphics and content from the sample as filler graphics until we get a chance to work on some more.  So copy the content from the sample over to our main application.  I broke them out into their own folders (i.e. Textures and Fonts) to start some basic organization of our content.</p>
<p>So our first task is to add the ScreenManager component to our library.  So create a folder in our library called Screens and add in the three class files GameScreen.cs, and ScreenManager.cs.  These will need some tweaking to work so let’s see what we have.</p>
<p>First go through and change the namespaces in each file to the corresponding namespaces of your library (i.e. VacantSkies.Lib.Screens).  I also created a new class file and moved the ScreenState enumeration over too it, but that’s more of a personal preference and is not necessary.</p>
<p>Next we will create another folder in our Library and name it Input.  Here we will copy over the InputState class file and change its namespace to what we need. (i.e. VacantSkies.Lib.Input)</p>
<p>So now if we try to compile we will probably get a couple errors stating that some namespaces couldn’t be found.  So you can either add those in by hand, or resolve them however you choose.  Once those are resolved they should compile.</p>
<p>Now let’s add in our title screen.  In our main application add a new folder called Screens. Next add in all the screens from the Game State Management sample.  Once again go through and change all our namespaces over and resolve any namespaces that are missing.</p>
<p>Next in our constructor for our game application add in the following lines of code.</p>
<pre class="brush: csharp; title: ;">
   	  public Game1()
        {
            graphics = new GraphicsDeviceManager(this)
            {
                PreferredBackBufferWidth = 1280,
                PreferredBackBufferHeight = 720
            };

            Content.RootDirectory = &quot;Content&quot;;

            screenManager = new ScreenManager(this);

            Components.Add(screenManager);

            screenManager.AddScreen(new BackgroundScreen(), null);
            screenManager.AddScreen(new MainMenuScreen(), null);
        }
</pre>
<p>Make sure you change the paths to our content also in ScreenManager, BackgroundScreen, GameplayScreen,  and MessageBoxScreen to reflect any folder changes in our Content folder.  Once that is complete you can run your application and should get a fully navigable menu system.</p>
<p><a href="http://www.sgtconker.com/wp-content/uploads/contest/2010/rpg/part1/3.png"><img class="alignnone" title="Menu" src="http://www.sgtconker.com/wp-content/uploads/contest/2010/rpg/part1/3.png" alt="" width="100%" /></a></p>
<p>It isn’t anything spectacular yet, but we can edit it to whatever we need now.</p>
<p>So let’s start doing some changes to our game screens now.  First let’s make the title screen really show our game instead of the filler graphics.  So add in the following to our textures content, VacantSkies-Title, and VacantSkies-TitleText.</p>
<p><a href="http://www.sgtconker.com/wp-content/uploads/contest/2010/rpg/part1/4.png"><img class="alignnone" title="VacantSkies-TitleText" src="http://www.sgtconker.com/wp-content/uploads/contest/2010/rpg/part1/4.png" alt="" /></a></p>
<p><a href="http://www.sgtconker.com/wp-content/uploads/contest/2010/rpg/part1/5.png"><img class="alignnone" title="VacantSkies-Title" src="http://www.sgtconker.com/wp-content/uploads/contest/2010/rpg/part1/5.png" alt="" width="100%" /></a></p>
<p>First lets open BackgroundScreen.  This screen will sit behind all of our other screens, so we want it to be something rather basic instead of the sample background. So in the LoadContent change the backgroundTexture to “Textures\\gradient”.</p>
<p>Next lets open up our MainMenuScreen.  There are going to be some significant changes need to be made here.  So before we dive into this lets determine what we want our main menu to actually reflect.</p>
<ul>
<li>Main Menu
<ul>
<li> New Story</li>
<li> Continue Story</li>
<li> Options</li>
<li> Credits</li>
<li> Exit</li>
</ul>
</li>
</ul>
<p>So you can see there is some changes we need to make to the menu.  So in the constructor of our MainMenuScreen add in some new menu entries and change other entries to reflect this menu structure.  So our constructor should look like this.</p>
<pre class="brush: csharp; title: ;">
   	public MainMenuScreen() : base(&quot;&quot;)
        {
            // Create our menu entries.
            MenuEntry playGameMenuEntry = new MenuEntry(&quot;New Game&quot;);
            MenuEntry continueGameMenuEntry = new MenuEntry(&quot;Continue Story&quot;);
            MenuEntry optionsMenuEntry = new MenuEntry(&quot;Options&quot;);
            MenuEntry creditsMenuEntry = new MenuEntry(&quot;Credits&quot;);
            MenuEntry exitMenuEntry = new MenuEntry(&quot;Exit&quot;);

            // Hook up menu event handlers.
            playGameMenuEntry.Selected += PlayGameMenuEntrySelected;
            continueGameMenuEntry.Selected += ContinueGameMenuEntrySelected;
            optionsMenuEntry.Selected += OptionsMenuEntrySelected;
            creditsMenuEntry.Selected += CreditsGameMenuEntrySelected;
            exitMenuEntry.Selected += OnCancel;

            // Add entries to the menu.
            MenuEntries.Add(playGameMenuEntry);
            MenuEntries.Add(continueGameMenuEntry);
            MenuEntries.Add(optionsMenuEntry);
            MenuEntries.Add(creditsMenuEntry);
            MenuEntries.Add(exitMenuEntry);

		MenuPosition = new Vector2(100, 300);
        }
</pre>
<p>And the two new event hooks should look like this for now.</p>
<pre class="brush: csharp; title: ;">
  /// &lt;summary&gt;
        /// Event handler for when the Continue Game menu entry is selected.
        /// &lt;/summary&gt;
        void ContinueGameMenuEntrySelected(object sender, PlayerIndexEventArgs e)
        {

        }
	  /// &lt;summary&gt;
        /// Event handler for when the Credits menu entry is selected.
        /// &lt;/summary&gt;
        void CreditsGameMenuEntrySelected(object sender, PlayerIndexEventArgs e)
        {

        }
</pre>
<p>Now in order to continue we need to change some things in MenuScreen.  First add in a property Vector2 MenuPosition {get; set;}  This will allow us to move our menu to wherever we choose on the screen.  Now in the constructor of MenuScreen set MenuPosition = new Vector2(100, 150) and then change our draw methods to use MenuPosition instead of position.<br />
Now jump back over to our MainMenuScreen and add in the following fields.</p>
<pre class="brush: csharp; title: ;">
        ContentManager content;
        Texture2D background;
        Texture2D title;
</pre>
<p>Then add in the LoadContent method.</p>
<pre class="brush: csharp; title: ;">
    public override void LoadContent()
        {
            if (content == null) content = new ContentManager(ScreenManager.Game.Services, &quot;Content&quot;);
            background = content.Load&lt;Texture2D&gt;(&quot;Textures\\VacantSkies-Title&quot;);
            title = content.Load&lt;Texture2D&gt;(&quot;Textures\\VacantSkies-TitleText&quot;);
        }
Then finally our Draw method.
    public override void Draw(GameTime gameTime)
        {
            SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
            Viewport viewport = ScreenManager.GraphicsDevice.Viewport;
            Rectangle fullscreen = new Rectangle(0, 0, viewport.Width, viewport.Height);
            byte fade = TransitionAlpha;

            Color transitionColor = new Color(fade, fade, fade);

            spriteBatch.Begin(SpriteBlendMode.AlphaBlend);

                spriteBatch.Draw(background, fullscreen, transitionColor);
                spriteBatch.Draw(title, new Vector2(100f, 50f), transitionColor);

            spriteBatch.End();

            base.Draw(gameTime);
        }
</pre>
<p>So now when we run it, our game is starting to take on shape.</p>
<p><a href="http://www.sgtconker.com/wp-content/uploads/contest/2010/rpg/part1/6.png"><img class="alignnone" title="Menu" src="http://www.sgtconker.com/wp-content/uploads/contest/2010/rpg/part1/6.png" alt="" width="100%" /></a></p>
<p>Now that we have our base menu in place, let’s change the other menu screens to what we need.  Let’s work with the Options screen first.  There are not going to be a bunch of options to set, but this leaves it open to you if you want to add in some more options for your game.  There are going to be two options that can be set, Main Volume and SFX Volume.  These will be stored in a static class that will contain global information for the game, and when the player saves, it will save to that players save slot.<br />
So in our library let’s add a new class called Settings. This will be a static class so we have access to it throughout our library.</p>
<pre class="brush: csharp; title: ;">
	public static class Settings
	{
		public static int MainVolume = 75;
		public static int SFXVolume = 75;
	}
</pre>
<p>Now let’s go take a look at the OptionsMenuScreen.  Most of the sample code here can be gotten rid of, but lets first add in some backgrounds for screens other than the Title Screen.  We will add in another texture called Background001 to our Content folder in our main application.  Than we will create our fields and add in our LoadContent method to load the background.<br />
Our new fields:</p>
<pre class="brush: csharp; title: ;">

		ContentManager content;
		Texture2D background;
</pre>
<p>Our LoadContent method:</p>
<pre class="brush: csharp; title: ;">
#region Load Content

		public override void LoadContent()
		{
			if (content == null) content = new ContentManager(ScreenManager.Game.Services, &quot;Content&quot;);
			background = content.Load&lt;Texture2D&gt;(&quot;Textures\\Background001&quot;);
		}

		#endregion
</pre>
<p>Then our Draw method:</p>
<pre class="brush: csharp; title: ;">
	#region Drawing

		public override void Draw(GameTime gameTime)
        {
            SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
            Viewport viewport = ScreenManager.GraphicsDevice.Viewport;
            Rectangle fullscreen = new Rectangle(0, 0, viewport.Width, viewport.Height);
            byte fade = TransitionAlpha;

            Color transitionColor = new Color(fade, fade, fade);

            spriteBatch.Begin(SpriteBlendMode.AlphaBlend);

                spriteBatch.Draw(background, fullscreen, transitionColor);

            spriteBatch.End();

            base.Draw(gameTime);
        }

        #endregion
</pre>
<p>So now, if you run our application and go to the options menu you will see a nice wood background.</p>
<p><a href="http://www.sgtconker.com/wp-content/uploads/contest/2010/rpg/part1/7.png"><img class="alignnone" title="Menu Background" src="http://www.sgtconker.com/wp-content/uploads/contest/2010/rpg/part1/7.png" alt="" width="100%" /></a></p>
<p>Next, we are going to add another tweak to the MenuScreen to allow us to set the position of the Menu Title, so if we need to we can move it to wherever we wish.  We are also going to have it default to center horizontally on the screen.  So open MenuScreen.cs and add in the property</p>
<pre class="brush: csharp; title: ;">
public Vector2 TitlePosition { get; set; }
</pre>
<p>Then in our constructor set TitlePosition to whatever.  The original default is TitlePosition = new Vector2(426, 80);  Now in our Draw method change our code to use the new TitlePosition, and then add a new method to center the title when we load the screen.</p>
<pre class="brush: csharp; title: ;">
	public void CenterTitle()
		{
			if (ScreenManager != null)
			{
				TitlePosition = new Vector2((ScreenManager.GraphicsDevice.Viewport.Width / 2) - (ScreenManager.Font.MeasureString(menuTitle).X / 2), 80);
			}
		}
</pre>
<p>Now we can go back to our OptionsMenuScreen.LoadContent and add the line CenterTitle() so our title centers when we load the screen.<br />
So next we need to create our menu items for Main Volume and SFX Volume.  Lets create two new MenuEntries for our menu items in the constructor, and then hook them in.  So this is what our OptionsMenuScreen constructor should now look like.</p>
<pre class="brush: csharp; title: ;">
  public OptionsMenuScreen() : base(&quot;Options&quot;)
        {
			// Create our menu entries.
			mainVolume = new MenuEntry(string.Empty);
			sfxVolume = new MenuEntry(string.Empty);

            SetMenuEntryText();

            MenuEntry backMenuEntry = new MenuEntry(&quot;Back&quot;);

            // Hook up menu event handlers.
			mainVolume.Selected += MainVolumeEntrySelected;
			sfxVolume.Selected += SFXVolumeEntrySelected;
            backMenuEntry.Selected += OnCancel;

            // Add entries to the menu.
			MenuEntries.Add(mainVolume);
			MenuEntries.Add(sfxVolume);
            MenuEntries.Add(backMenuEntry);
        }
</pre>
<p>As you can see we created two more fields mainVolume, and sfxVolume, and added a new method SetMenuEntryText().</p>
<pre class="brush: csharp; title: ;">
/// &lt;summary&gt;
        /// Fills in the latest values for the options screen menu text.
        /// &lt;/summary&gt;
        void SetMenuEntryText()
        {
			mainVolume.Text = String.Format(&quot;Main Volume: {0} %&quot;, Settings.MainVolume);
			sfxVolume.Text = String.Format(&quot;SFX Volume: {0} %&quot;, Settings.SFXVolume);
        }
</pre>
<p>Then we need to setup our event hooks for when the items are selected.</p>
<pre class="brush: csharp; title: ;">
/// &lt;summary&gt;
		/// Event handler for when the Main Volume menu entry is selected.
		/// &lt;/summary&gt;
		void MainVolumeEntrySelected(object sender, PlayerIndexEventArgs e)
		{
			Settings.MainVolume += 5;
			if (Settings.MainVolume &gt; 100) Settings.MainVolume = 0;

			SetMenuEntryText();
		}

		/// &lt;summary&gt;
		/// Event handler for when the SFX Volume menu entry is selected.
		/// &lt;/summary&gt;
		void SFXVolumeEntrySelected(object sender, PlayerIndexEventArgs e)
		{
			Settings.SFXVolume += 5;
			if (Settings.SFXVolume &gt; 100) Settings.SFXVolume = 0;

			SetMenuEntryText();
		}
</pre>
<p>So now, when we run it we should have something like this.</p>
<p><a href="http://www.sgtconker.com/wp-content/uploads/contest/2010/rpg/part1/8.png"><img class="alignnone" title="Options" src="http://www.sgtconker.com/wp-content/uploads/contest/2010/rpg/part1/8.png" alt="" width="100%" /></a></p>
<p>When we select each item, the volume increases 5% and will wrap around to 0%.  In addition, it saves it to our Settings class.<br />
Next, we will add in a Credits screen.  This will be straightforward and will only have one menu item. So on our Screens folder add a new class and name it CreditsScreen.</p>
<pre class="brush: csharp; title: ;">
    class CreditsScreen: MenuScreen
    {
        #region Fields

		ContentManager content;
		Texture2D background;

        #endregion

        #region Initialization

        /// &lt;summary&gt;
        /// Constructor.
        /// &lt;/summary&gt;
		public CreditsScreen() : base(&quot;Credits&quot;)
        {
			MenuEntry backMenuEntry = new MenuEntry(&quot;Back&quot;);
            backMenuEntry.Selected += OnCancel;
            MenuEntries.Add(backMenuEntry);
        }

        #endregion

		#region Load Content

		public override void LoadContent()
		{
			if (content == null) content = new ContentManager(ScreenManager.Game.Services, &quot;Content&quot;);
			background = content.Load&lt;Texture2D&gt;(&quot;Textures\\Background001&quot;);
			CenterTitle();
			if (ScreenManager != null)
			{
				MenuPosition = new Vector2(100f, ScreenManager.GraphicsDevice.Viewport.Height - (ScreenManager.GraphicsDevice.Viewport.Height * 0.1f));
			}
		}

		#endregion

       	#region Drawing

		public override void Draw(GameTime gameTime)
        {
            SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
            Viewport viewport = ScreenManager.GraphicsDevice.Viewport;
            Rectangle fullscreen = new Rectangle(0, 0, viewport.Width, viewport.Height);
            byte fade = TransitionAlpha;

            Color transitionColor = new Color(fade, fade, fade);

			Vector2 position = new Vector2(100, 150);

			float transitionOffset = (float)Math.Pow(TransitionPosition, 2);

			if (ScreenState == ScreenState.TransitionOn)
				position.X -= transitionOffset * 256;
			else
				position.X += transitionOffset * 512;

            spriteBatch.Begin(SpriteBlendMode.AlphaBlend);

                spriteBatch.Draw(background, fullscreen, transitionColor);

				spriteBatch.DrawString(ScreenManager.Font, &quot;[ Design / Concept / Programming / Art ] - Aaron T Foley&quot;, position, Color.White);
				spriteBatch.DrawString(ScreenManager.Font, &quot;[ Design / Testing ] - Ginger Foley&quot;, position + new Vector2(0f, ScreenManager.Font.LineSpacing * 2), Color.White);
				spriteBatch.DrawString(ScreenManager.Font, &quot;[ Music ] - Neil Lynn&quot;, position + new Vector2(0f, ScreenManager.Font.LineSpacing * 4), Color.White);

            spriteBatch.End();

            base.Draw(gameTime);
        }

        #endregion
    }
</pre>
<p>As you can see there is nothing special about this screen, but it can be molded into whatever you want.<br />
Our next section will deal with our Continue Story screen and loading from storage.<br />
So our first thing we need to do is create the new screen ContinueGameScreen.  Once again, this will be roughly the same as the Credits screen and the Options screen.</p>
<pre class="brush: csharp; title: ;">
	class ContinueGameScreen : MenuScreen
    {
        #region Fields

		ContentManager content;
		Texture2D background;

        #endregion

        #region Initialization

        /// &lt;summary&gt;
        /// Constructor.
        /// &lt;/summary&gt;
		public ContinueGameScreen() : base(&quot;Continue Game&quot;)
        {
			MenuEntry backMenuEntry = new MenuEntry(&quot;Back&quot;);
            backMenuEntry.Selected += OnCancel;
            MenuEntries.Add(backMenuEntry);
        }

        #endregion

		#region Load Content

		public override void LoadContent()
		{
			if (content == null) content = new ContentManager(ScreenManager.Game.Services, &quot;Content&quot;);
			background = content.Load&lt;Texture2D&gt;(&quot;Textures\\Background001&quot;);
			CenterTitle();
		}

		#endregion

        #region Handle Input

        #endregion

		#region Drawing

		public override void Draw(GameTime gameTime)
        {
            SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
            Viewport viewport = ScreenManager.GraphicsDevice.Viewport;
            Rectangle fullscreen = new Rectangle(0, 0, viewport.Width, viewport.Height);
            byte fade = TransitionAlpha;

            Color transitionColor = new Color(fade, fade, fade);

            spriteBatch.Begin(SpriteBlendMode.AlphaBlend);

                spriteBatch.Draw(background, fullscreen, transitionColor);

            spriteBatch.End();

            base.Draw(gameTime);
        }

        #endregion
    }
</pre>
<p>So this is pretty basic, but we will flesh it out.  Also don’t forget to add in your event hook in your MainMenuScreen to transition to the continue screen.</p>
<pre class="brush: csharp; title: ;">
/// &lt;summary&gt;
        /// Event handler for when the Continue Game menu entry is selected.
        /// &lt;/summary&gt;
        void ContinueGameMenuEntrySelected(object sender, PlayerIndexEventArgs e)
        {
			ScreenManager.AddScreen(new ContinueGameScreen(), e.PlayerIndex);
        }
</pre>
<p>Now that we have the screen loading, let’s get even more dirty.  We will be using a library to handle the storage device for us.  It is a nice library called EasyStorage.</p>
<p><a href="http://easystorage.codeplex.com/"><strong><span style="text-decoration: underline;">EasyStorage</span></strong></a></p>
<p>So download this and in the DLL’s to our solution.  I created a new folder in my solution called EasyStorage and added in the DLL and resource files it uses there.  Then I added the reference to it.</p>
<p>Now we need to determine what we want to see on our Continue Game screen.</p>
<p>My original concept will use 5 slots that display some information about the save that’s currently within that slot.  So we need to create a SaveGameDescription that holds the information we want to display in each slot.</p>
<pre class="brush: csharp; title: ;">
[Serializable]
	public class SaveGameDescription
	{
		public string Filename { get; set; }
		public string PlayerName { get; set; }
		public string PlayerLevel { get; set; }
		public string PlayerClass { get; set; }
		public string Region { get; set; }
		public string Description { get; set; }

		public SaveGameDescription()
		{
			Filename = &quot;&quot;;
			PlayerName = &quot;&quot;;
			PlayerLevel = &quot;0&quot;;
			PlayerClass = &quot;Unknown&quot;;
			Region = &quot;Unknown&quot;;
			Description = &quot;Empty&quot;;
		}
	}
</pre>
<p>Now that we have defined what our SaveGameDescriptions will be, we need somewhere to store them globally.  So we will create a static class called Global that will store data we will need throughout the game such as this.</p>
<pre class="brush: csharp; title: ;">
	public static class Global
	{

		public static List&lt;SaveGameDescription&gt; SaveGameDescriptions { get; set; }

		static Global()
		{
			SaveGameDescriptions = new List&lt;SaveGameDescription&gt;();
		}
	}
</pre>
<p>So now we have some data to work with to create our 5 slots for our continue screen.  So back in our continue game screen we will modify our screen to handle the five slots.<br />
I’m wanting to use the MenuEntry system to do this, but each item has a default of the Fonts Line Spacing to space the items out on the screen.  So we will have to modify MenuScreen again to have an adjustable LineSpacing.<br />
So in MenuScreen.cs add the property,</p>
<pre class="brush: csharp; title: ;">
public float LineSpacing { get; set; }
</pre>
<p>and in the constructor set it to 0.  This will be the amount each item will space in addition to the default Font.LineSpacing. Then in the Draw method modify the following line.</p>
<pre class="brush: csharp; title: ;">
position.Y += menuEntry.GetHeight(this) + LineSpacing;
</pre>
<p>So now we can set our additional line spacing in our screens to whatever we choose.<br />
So here is the final ContinueGameScreen.cs.  Right now it doesn’t actually load any save data, but it provides the shell for doing it.  It does load save descriptions, and if one doesn’t exist it creates a blank one so it can display information on the slot.</p>
<pre class="brush: csharp; title: ;">
	class ContinueGameScreen : MenuScreen
    {
        #region Fields

		ISaveDevice saveDevice;

		ContentManager content;
		Texture2D background;

		MenuEntry slot1;
        MenuEntry slot2;
        MenuEntry slot3;
        MenuEntry slot4;
        MenuEntry slot5;

		private SaveGameDescription loadedSaveGameDescription;
		private SaveGameDescription savedSaveGameDescription;

		public string StorageContainerName = &quot;Vacant Skies&quot;;

		private readonly XmlSerializer serializer = new XmlSerializer(typeof(SaveGameDescription));

        #endregion

		#region Initialization

		/// &lt;summary&gt;
        /// Constructor.
        /// &lt;/summary&gt;
		public ContinueGameScreen() : base(&quot;Continue Game&quot;)
        {
			MenuEntry backMenuEntry = new MenuEntry(&quot;Back&quot;);
            backMenuEntry.Selected += OnCancel;

			slot1 = new MenuEntry(&quot;Slot 1&quot;);
			slot2 = new MenuEntry(&quot;Slot 2&quot;);
			slot3 = new MenuEntry(&quot;Slot 3&quot;);
			slot4 = new MenuEntry(&quot;Slot 4&quot;);
			slot5 = new MenuEntry(&quot;Slot 5&quot;);

			SetMenuText();

			slot1.Selected += Slot1Selected;
			slot2.Selected += Slot2Selected;
			slot3.Selected += Slot3Selected;
			slot4.Selected += Slot4Selected;
			slot5.Selected += Slot5Selected;

			MenuEntries.Add(slot1);
			MenuEntries.Add(slot2);
			MenuEntries.Add(slot3);
			MenuEntries.Add(slot4);
			MenuEntries.Add(slot5);
			MenuEntries.Add(backMenuEntry);
        }

        #endregion

		#region Load Content

		public override void LoadContent()
		{
			if (content == null) content = new ContentManager(ScreenManager.Game.Services, &quot;Content&quot;);
			background = content.Load&lt;Texture2D&gt;(&quot;Textures\\Background001&quot;);
			CenterTitle();
			LineSpacing = ScreenManager.Font.LineSpacing * 1.25f;

			LoadStorageDevice();
		}

		#endregion

        #region Handle Input

		void Slot1Selected(object sender, PlayerIndexEventArgs e)
		{
			SetMenuText();
		}

		void Slot2Selected(object sender, PlayerIndexEventArgs e)
		{
			SetMenuText();
		}

		void Slot3Selected(object sender, PlayerIndexEventArgs e)
		{
			SetMenuText();
		}

		void Slot4Selected(object sender, PlayerIndexEventArgs e)
		{
			SetMenuText();
		}

		void Slot5Selected(object sender, PlayerIndexEventArgs e)
		{
			SetMenuText();
		}

        #endregion

		#region Drawing

		public override void Draw(GameTime gameTime)
        {
            SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
            Viewport viewport = ScreenManager.GraphicsDevice.Viewport;
            Rectangle fullscreen = new Rectangle(0, 0, viewport.Width, viewport.Height);
            byte fade = TransitionAlpha;

            Color transitionColor = new Color(fade, fade, fade);

            spriteBatch.Begin(SpriteBlendMode.AlphaBlend);

                spriteBatch.Draw(background, fullscreen, transitionColor);

            spriteBatch.End();

            base.Draw(gameTime);
        }

		#endregion

		void SetMenuText()
		{
			if (Global.SaveGameDescriptions.Count &gt; 1)
			{
				SaveGameDescription save = Global.SaveGameDescriptions[0];
				slot1.Text = string.Format(&quot;Slot 1 | Name: {0} Class: {1} Level: {2} Region: {3}\r\n       | {4}&quot;, save.PlayerName, save.PlayerClass, save.PlayerLevel, save.Region, save.Description);
			}
			if (Global.SaveGameDescriptions.Count &gt; 2)
			{
				SaveGameDescription save = Global.SaveGameDescriptions[1];
				slot2.Text = string.Format(&quot;Slot 2 | Name: {0} Class: {1} Level: {2} Region: {3}\r\n       | {4}&quot;, save.PlayerName, save.PlayerClass, save.PlayerLevel, save.Region, save.Description);
			}
			if (Global.SaveGameDescriptions.Count &gt; 3)
			{
				SaveGameDescription save = Global.SaveGameDescriptions[2];
				slot3.Text = string.Format(&quot;Slot 3 | Name: {0} Class: {1} Level: {2} Region: {3}\r\n       | {4}&quot;, save.PlayerName, save.PlayerClass, save.PlayerLevel, save.Region, save.Description);
			}
			if (Global.SaveGameDescriptions.Count &gt; 4)
			{
				SaveGameDescription save = Global.SaveGameDescriptions[3];
				slot4.Text = string.Format(&quot;Slot 4 | Name: {0} Class: {1} Level: {2} Region: {3}\r\n       | {4}&quot;, save.PlayerName, save.PlayerClass, save.PlayerLevel, save.Region, save.Description);
			}
			if (Global.SaveGameDescriptions.Count &gt; 1)
			{
				SaveGameDescription save = Global.SaveGameDescriptions[4];
				slot5.Text = string.Format(&quot;Slot 5 | Name: {0} Class: {1} Level: {2} Region: {3}\r\n       | {4}&quot;, save.PlayerName, save.PlayerClass, save.PlayerLevel, save.Region, save.Description);
			}
		}

		void LoadStorageDevice()
		{
#if WINDOWS
			saveDevice = new PCSaveDevice(StorageContainerName);
			ReadSaves();
#else
			// add the GamerServicesComponent
			Components.Add(new GamerServicesComponent(this));

			// create and add our SaveDevice
			SharedSaveDevice sharedSaveDevice = new SharedSaveDevice(StorageContainerName);
			Components.Add(sharedSaveDevice);

			// hook an event for when the device is selected to run our test
			sharedSaveDevice.DeviceSelected += (s, e) =&gt; ReadSaves();

			// hook two event handlers to force the user to choose a new device if they cancel the
			// device selector or if they disconnect the storage device after selecting it
			sharedSaveDevice.DeviceSelectorCanceled += (s, e) =&gt; e.Response = SaveDeviceEventResponse.Force;
			sharedSaveDevice.DeviceDisconnected += (s, e) =&gt; e.Response = SaveDeviceEventResponse.Force;

			// prompt for a device on the first Update we can
			sharedSaveDevice.PromptForDevice();

			// make sure we hold on to the device
			saveDevice = sharedSaveDevice;
#endif

			SetMenuText();
		}

		private void ReadSaves()
		{
			Global.SaveGameDescriptions.Clear();
			for (int i = 1; i &lt;= 5; i++)
			{
				string filename = String.Format(&quot;SaveSlot{0}-Description.xml&quot;, i);
				if (!saveDevice.FileExists(filename))
				{
					Trace.WriteLine(String.Format(&quot;Failed to find file {0}.&quot;, filename));
					savedSaveGameDescription = new SaveGameDescription();
					if (!saveDevice.Save(filename, SerializeSave))
					{
						Trace.WriteLine(string.Format(&quot;Failed to save file {0}.&quot;, filename));
					}
				}
				else
				{
					if (!saveDevice.Load(filename, DeserializeSave))
					{
						Trace.WriteLine(String.Format(&quot;Failed to load file {0}.&quot;, filename));
					}
					Global.SaveGameDescriptions.Add(loadedSaveGameDescription);
				}
			}
		}

		private void DeserializeSave(Stream stream)
		{
			loadedSaveGameDescription = serializer.Deserialize(stream) as SaveGameDescription;
			Trace.WriteLine(&quot;Save Game Description Loaded: &quot; + loadedSaveGameDescription);
		}

		private void SerializeSave(Stream stream)
		{
			Trace.WriteLine(&quot;Game Description Saved: &quot; + savedSaveGameDescription);
			serializer.Serialize(stream, savedSaveGameDescription);
		}
    }
</pre>
<p>So now if you run our application you should see something like this in the continue screen.</p>
<p><a href="http://www.sgtconker.com/wp-content/uploads/contest/2010/rpg/part1/9.png"><img class="alignnone" title="Continue Screen" src="http://www.sgtconker.com/wp-content/uploads/contest/2010/rpg/part1/9.png" alt="" width="100%" /></a></p>
<p>So this concludes part one of the Action RPG Tutorial Series.  In our next part we will be diving into creating the game world and populating it.</p>
<p><strong>Download: <a href="http://www.sgtconker.com/wp-content/uploads/contest/2010/rpg/part1/Part1_Source.zip">Part1_Source.zip</a></strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.sgtconker.com/2010/09/article-vacant-skies-action-rpg-tutorial-series/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Building a 2D RPG</title>
		<link>http://www.sgtconker.com/2010/01/building-a-2d-rpg/</link>
		<comments>http://www.sgtconker.com/2010/01/building-a-2d-rpg/#comments</comments>
		<pubDate>Fri, 22 Jan 2010 08:11:37 +0000</pubDate>
		<dc:creator>Captain ZSquare</dc:creator>
				<category><![CDATA[2D]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[UI]]></category>
		<category><![CDATA[edg3]]></category>
		<category><![CDATA[RPG]]></category>

		<guid isPermaLink="false">http://www.sgtconker.com/?p=936</guid>
		<description><![CDATA[edg3 from RealDev started a series about Building a 2D RPG using XNA, and currently has the first two parts on his site.
They both deal with building the basic skeleton of the game, starting with planning and gamestate management and continuing with keyboard and mouse input.
If your interested in other RPG-related tutorials and content for [...]]]></description>
			<content:encoded><![CDATA[<p>edg3 from <a href="http://realdev.co.za/blog/">RealDev</a> started a series about Building a 2D RPG using XNA, and currently has the first two parts on his site.</p>
<p>They both deal with building the basic skeleton of the game, starting with <a href="http://realdev.co.za/blog/?p=136">planning and gamestate management</a> and continuing with <a href="http://realdev.co.za/blog/?p=142">keyboard and mouse input</a>.</p>
<p>If your interested in other RPG-related tutorials and content for XNA, here's some:</p>
<ul>
<li>Nick "Not an MVP Anymore" Gravelyn's<a href="http://nickgravelyn.com/archive/#tileengine"> Tile Engine Series</a></li>
<li>Jamie McMahon series of <a href="http://xna.jtmbooks.com/rpgtutorials.html">44 RPG Tutorials</a></li>
<li>The <a href="http://creators.xna.com/en-US/starterkit/roleplayinggame">Role Playing Game Starter Kit</a> on XNA Creator's Club</li>
<li>Jim "Evil MVP" Perry's book <a href="http://www.amazon.com/RPG-Programming-XNA-Game-Studio/dp/1598220659/ref=sr_1_1?ie=UTF8&amp;s=books&amp;qid=1235005867&amp;sr=8-1">RPG Programming with XNA Game Studio 3.0</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.sgtconker.com/2010/01/building-a-2d-rpg/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

