<?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; Input</title>
	<atom:link href="http://www.sgtconker.com/category/xna/input/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: Input Playback</title>
		<link>http://www.sgtconker.com/2010/08/article-input-playback/</link>
		<comments>http://www.sgtconker.com/2010/08/article-input-playback/#comments</comments>
		<pubDate>Sat, 14 Aug 2010 05:04:42 +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[Input]]></category>
		<category><![CDATA[XNA]]></category>
		<category><![CDATA[Absolutely Fine Tutorial Contest]]></category>
		<category><![CDATA[Input Playback]]></category>
		<category><![CDATA[Jesse Chounard]]></category>

		<guid isPermaLink="false">http://www.sgtconker.com/?p=1550</guid>
		<description><![CDATA[by Jesse Chounard

Lately I’ve noticed a trend in games to allow players to save and play back recordings of their play upon completion of a match.  This allows players to analyze their mistakes, as well as learn new tactics and techniques from their opponents.  This feature is becoming common in all sorts of games.  You [...]]]></description>
			<content:encoded><![CDATA[<h4 style="text-align: center;">by Jesse Chounard</h4>
<p style="text-align: center;"><img class="aligncenter" src="http://www.sgtconker.com/wp-content/uploads/contest/2010/playback.PNG" alt="Input Playback" /></p>
<p>Lately I’ve noticed a trend in games to allow players to save and play back recordings of their play upon completion of a match.  This allows players to analyze their mistakes, as well as learn new tactics and techniques from their opponents.  This feature is becoming common in all sorts of games.  You can find it in real time strategy games like StarCraft, first person shooters like Halo 3, and fighting games like Super Street Fighter 4.</p>
<p>In many cases, these gameplay recordings are often uploaded to a server on the internet, and are available for download by anyone.  The recordings don’t require buffering or waiting for a big download to finish.  Instead, the playback just starts right up.  How is this possible?  Great looking high definition video files are gigantic.  Also, video compression takes a huge amount of computation, so wouldn’t it slow the gameplay down to record everything?</p>
<p>It turns out that there’s a really simple trick.  We’re not recording video.  Instead, we just store all of the user input, and then later we can use those inputs to exactly recreate the gameplay in our game engine.  So while it looks like we’re watching a stored video, instead we’re just watching the computer playing the game using our stored inputs instead of using the game controller for input.</p>
<p>In this tutorial, I’ll show you a simple method that you can use to achieve gameplay recording and playback, and also list a few other uses for this technique.</p>
<p><span id="more-1550"></span><br />
What exactly do we need to record?</p>
<p>1.    The most obvious thing to record is the input from the players.  The standard Xbox 360 gamepad has fourteen digital buttons (4 D-Pad directions, A, B, X, Y, LB, RB, Start, Back, and pushing down on either analog stick), and six analog inputs (X and Y for both analog sticks, and left and right triggers.)<br />
2.    If our game runs with a variable time step, we need to record the amount of time that has elapsed since our last recording.  This is simple enough, since the XNA framework provides this in the GameTime class that’s passed in to the default Update method.</p>
<p>Let’s take a look at how we might manage this data in our code.</p>
<p>Once per frame, we need to store a flag to tell us whether each of our digital buttons is held down or not.  We could store a boolean for each of the buttons, but it’s probably better to pack them down a bit more.  We can use an enumeration, declared with the Flags attribute to contain all of our digital button states.</p>
<pre class="brush: csharp; title: ;">
[Flags]
public enum ButtonFlags: short{
        None = 0x0000,

        Up = 0x0001,
        Down = 0x0002,
        Left = 0x0004,
        Right = 0x0008,

        A = 0x0010,
        B = 0x0020,
        // etc.
}
</pre>
<p>Then it’s a pretty simple matter to set or check a button’s status.</p>
<pre class="brush: csharp; title: ;">
        ButtonFlags buttonFlags;
</pre>
<p>To set a button pressed:</p>
<pre class="brush: csharp; title: ;">
        buttonFlags |= ButtonFlags.A;
</pre>
<p>To check for a button press:</p>
<pre class="brush: csharp; title: ;">
if((buttonFlags &amp;amp; ButtonFlags.A) != ButtonFlags.None)
{
         // button A is pressed
}
</pre>
<p>All of the analog inputs on the Xbox 360 gamepad are reported with a single floating point number.  We can also represent the amount of elapsed time in a float.  If we put all of those together in a structure, we arrive at something that looks like this:</p>
<pre class="brush: csharp; title: ;">
public struct InputState
{
         public float FrameTime;
         public float LeftStickX, LeftStickY;
         public float RightStickX, RightStickY;
         public float LeftTrigger, RightTrigger;
         public ButtonFlags InputFlags;
}
</pre>
<p>And that structure is all we need to store to represent an entire frame.  That’s a whole heck of a lot smaller than a frame of video, especially in high definition.  And you can make it even smaller if you don’t need all of the inputs for your game, or if you can treat the analog inputs as digital ones.  (If you only care if a trigger is pushed, but not to what degree it’s depressed, you can move it in with the digital buttons.)</p>
<p>Now we need to tie recording in to our gameplay.  At the start of each Update method (once per frame), fill out an InputState, and store it away.  Then update your game normally.  If you can move your update code to a new function that takes an InputState as a parameter, it will simplify things when it comes time to play back the data.</p>
<p>Here’s what our Update method might look like:</p>
<pre class="brush: csharp; title: ;">
protected override void Update(GameTime gameTime)
{
        if (currentState == GameState.Recording)
        {
                InputState inputState;

                SetInputState(out inputState,
                (float)gameTime.ElapsedGameTime.TotalSeconds);
                SaveInput(inputState);
                UpdateGame(inputState);
        }
}
</pre>
<p>SetInputState just checks each button, and stores whether or not it’s pressed.  SaveInput would store the information to disk, or to a temporary buffer where we could read it later.  And UpdateGame might look like this:</p>
<pre class="brush: csharp; title: ;">
void UpdateGame(InputState inputState)
{
        if ((inputState.InputFlags &amp;amp; ButtonFlags.Left) != ButtonFlags.None)
        {
                // move player left
        }
       else if ((inputState.InputFlags &amp;amp; ButtonFlags.Right) != ButtonFlags.None)
        {
                // move player right
        }
}
</pre>
<p>And that’s it for recording.  Nice and easy!  Now how about the playback?  Well, that’s pretty easy too.</p>
<p>We’re going to need a couple of variables to keep track of where we are in the play back, and how much time has passed since we started playing.</p>
<pre class="brush: csharp; title: ;">
float recordingTime = 0, playbackTime = 0;
int playbackPosition = 0;
float playbackTimeScale = 1;
</pre>
<p>The first two (recordingTime and playbackTime) are used to compare how much time has elapsed in playback versus how much time elapsed in the original recording.  We can compare them to determin when we need to move to the next frame.   playbackPosition is the frame index in the recording.  playbackTimeScale determines how fast we play back the recording.  We’ll play around with that in a second.</p>
<pre class="brush: csharp; title: ;">
protected override void Update(GameTime gameTime)
{
        if(currentState == GameState.Recording)
        {
                 // see above
         }
         else if (currentState == GameState.Playback)
         {
                 playbackTime += (float)gameTime.ElapsedGameTime.TotalSeconds * playbackTimeScale;

                 while (playbackTime &amp;gt;= recordingTime)
                 {
                         InputState inputState;
                         ReadInputState(out inputState, playbackPosition)
                         playbackPosition++;
                         recordingTime += inputState.FrameTime;
                         UpdateGame(inputState);
                 }
        }
}
</pre>
<p>And that’s all it takes to play back our recordings.  It’s truly very simple.  If you play around with the playbackTimeScale variable you get really cool slow motion or fast forward.  (0.5f would move at half speed, where 2.0f would be double speed.)</p>
<p>In the included sample application, you can switch between recording and playback mode using F1 and F2 on the keyboard.  You can use the gamepad D-Pad or the keyboard arrow keys to move around.</p>
<p>But what else can we do with this technique?</p>
<p>1.    You could implement a training mode, and use a recorded playback to show the player how to use a new technique.<br />
2.    You could use a playback in a puzzle game to show the puzzle solution if the player gets stuck and gives up.  (This was used in Professor Fizzwizzle, one of my favorite indie games.)<br />
3.    This could be a big help in debugging.  If you find a way to crash your game, but it’s difficult to repeat, you could record the inputs and get exactly the same inputs every time.  Also, if you have very fast gameplay and you’re having trouble seeing what’s going wrong, you can slow the playback time down and see everything in super slow motion.<br />
4.    If you’re making a gameplay trailer, but don’t have enough horsepower in your PC to capture the video (with an application like Fraps) without slowing down the game too much, you could use a playback to help.  Advance the playback 16.66 milliseconds per frame, and write out a screenshot.  Repeat that until the end of the playback.  Then you can use an external program to stitch all of the screenshots together into a 60 frame per second movie.  (Alec Holowka used a technique like this to make the HD trailer for Aquaria.)</p>
<p>That pretty much covers everything.  Please leave a comment if anything here is unclear or if you see a way this could be improved.  I’d love to hear what interesting uses you come up with for your playbacks.</p>
<p><strong>Download sample code:</strong> <a href="http://www.sgtconker.com/wp-content/uploads/contest/2010/PlaybackSample.zip">PlaybackSample.zip</a> (<a href="http://www.sgtconker.com/wp-content/uploads/contest/2010/jesse_license.txt">license</a>)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sgtconker.com/2010/08/article-input-playback/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Windows Phone 7 &#8211; XNA Brightness and Contrast</title>
		<link>http://www.sgtconker.com/2010/06/windows-phone-7-xna-brightness-and-contrast/</link>
		<comments>http://www.sgtconker.com/2010/06/windows-phone-7-xna-brightness-and-contrast/#comments</comments>
		<pubDate>Tue, 22 Jun 2010 23:40:05 +0000</pubDate>
		<dc:creator>CorporalX</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Input]]></category>
		<category><![CDATA[UI]]></category>
		<category><![CDATA[WP7]]></category>
		<category><![CDATA[XNA]]></category>

		<guid isPermaLink="false">http://www.sgtconker.com/?p=1479</guid>
		<description><![CDATA[With the addition of Windows Phone 7 support to XNA comes some limitations. If one wanted to have brightness and contrast controls for their game, previous methods may not be available. Considering features such as programmable shaders or device gamma ramp to achieve such a task will leave you out of luck. However there is [...]]]></description>
			<content:encoded><![CDATA[<p>With the addition of Windows Phone 7 support to XNA comes some limitations. If one wanted to have brightness and contrast controls for their game, previous methods may not be available. Considering features such as programmable shaders or device gamma ramp to achieve such a task will leave you out of luck. However there is a simple (and perhaps old school) way of doing it, and that is blend states.</p>
<p>Click <em>Continue reading</em> to see how!<br />
<span id="more-1479"></span></p>
<p>If you look around for information on how to adjust brightness and contrast with blend states, you might find this:</p>
<p>Draw a full screen quad and use these color blend states:</p>
<p><strong>Brightness: source = <em>ONE</em>, dest = <em>ONE</em><br />
Contrast: source = <em>DESTCOLOR</em>, dest = <em>ZERO</em></strong></p>
<p>While these would work, they might not be as you expect. Drawing with a 24/32bit per texel texture, the first would only allow you to adjust the brightness up from white, and the latter would only let you reduce contrast. That is probably not what people want. I suggest different settings:</p>
<p><strong>Brightness: source = <em>ZERO</em>, dest = <em>SOURCECOLOR</em><br />
Contrast: source = <em>DESTCOLOR</em>, dest = <em>SOURCECOLOR</em></strong></p>
<p>This will allow brightness to be reduced instead of raised, and contrast can be increased as well as reduced.</p>
<p>So how do you actually do this in XNA 4 on Windows Phone 7?</p>
<p>First you will need a 1x1 texel white texture either through the content pipeline, or procedurally. </p>
<p>Add this member to your game class:</p>
<pre class="brush: csharp; title: ;">
Texture2D whiteTexture;
</pre>
<p>In the LoadContent override method, add this to create the texture procedurally:</p>
<pre class="brush: csharp; title: ;">
whiteTexture = new Texture2D(GraphicsDevice, 1, 1);
whiteTexture.SetData&lt;Color&gt;(new Color[] { Color.White });
</pre>
<p>You will also need a couple of integer members to hold brightness and contrast state:</p>
<pre class="brush: csharp; title: ;">
int brightness;
int contrast;
</pre>
<p>Also, two blend states, one for brightness, and one for contrast:</p>
<pre class="brush: csharp; title: ;">
BlendState brightnessBlend;
BlendState contrastBlend;
</pre>
<p>In the Initialize override method, we can set these other members (note that alpha blend states must match color blend states on WP7/Reach):</p>
<pre class="brush: csharp; title: ;">
brightness = 255;
contrast = 128;

brightnessBlend = new BlendState();
brightnessBlend.ColorSourceBlend = brightnessBlend.AlphaSourceBlend =  Blend.Zero;
brightnessBlend.ColorDestinationBlend = brightnessBlend.AlphaDestinationBlend = Blend.SourceColor;

contrastBlend = new BlendState();
contrastBlend.ColorSourceBlend = contrastBlend.AlphaSourceBlend = Blend.DestinationColor;
contrastBlend.ColorDestinationBlend = contrastBlend.AlphaDestinationBlend = Blend.SourceColor;
</pre>
<p>Finally, in the Draw override method, after you have drawn to the screen, do the following (this assumes spriteBatch is initialized and that the default blend state is wanted next frame):</p>
<pre class="brush: csharp; title: ;">
spriteBatch.Begin(SpriteSortMode.Immediate, brightnessBlend);
spriteBatch.Draw(whiteTexture, new Rectangle(0, 0, 480, 800), new Color (brightness, brightness, brightness, 255));
spriteBatch.End();

spriteBatch.Begin(SpriteSortMode.Immediate, contrastBlend);
spriteBatch.Draw(whiteTexture, new Rectangle(0, 0, 480, 800), new Color(contrast, contrast, contrast, 255));
spriteBatch.End();

GraphicsDevice.BlendState = BlendState.Opaque;
</pre>
<p>That's it, but there are a couple more things to mention. First is that the color values (the brightness and contrast integers) should be between 0 and 255, although you could use floats too. To clamp an integer between these values use:</p>
<pre class="brush: csharp; title: ;">
value = Math.Max(Math.Min(value, 255), 0);
</pre>
<p>To test runtime adjustment of the brightness and contrast, I used input from the 4 quadrants of the screen. The top half adjusts brightness, the bottom contrast. The left side reduces the value and the right side increases it. To do this, add the following code to the Update override method:</p>
<pre class="brush: csharp; title: ;">
foreach (TouchLocation t in TouchPanel.GetState())
{
   if (t.Position.Y &lt;= 400)
      Adjust(t, ref brightness);
   else
      Adjust(t, ref contrast);
}
</pre>
<p>And the Adjust method  (here it adjusts the value by 3 for each touch change at your pleasure, it also includes the clamping mentioned above):</p>
<pre class="brush: csharp; title: ;">
private void Adjust(TouchLocation t, ref int adjustee)
{
   if (t.Position.X &lt; 240)
      adjustee -= 3;
   else
      adjustee += 3;

   adjustee = Math.Max(Math.Min(adjustee, 255), 0);
}
</pre>
<p>You could expose this via sliders in an options page. The brightness would be particularly useful as you don't want people exiting the game to adjust screen brightness.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sgtconker.com/2010/06/windows-phone-7-xna-brightness-and-contrast/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Dress Me Up &#8211; Windows Phone 7</title>
		<link>http://www.sgtconker.com/2010/04/dress-me-up-windows-phone-7/</link>
		<comments>http://www.sgtconker.com/2010/04/dress-me-up-windows-phone-7/#comments</comments>
		<pubDate>Thu, 08 Apr 2010 13:26:49 +0000</pubDate>
		<dc:creator>Sgt. Conker</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Input]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[WP7]]></category>
		<category><![CDATA[XNA]]></category>
		<category><![CDATA[Touch]]></category>

		<guid isPermaLink="false">http://www.sgtconker.com/?p=1382</guid>
		<description><![CDATA[
Matthew "BRUTAL" Randall has been playing with WP7 &#38; XNA 4.0. He has developed a game/app called Dress Me Up.
Simple premise, yet makes good use of touch.
Check out the video on his site here
]]></description>
			<content:encoded><![CDATA[<p><img class="alignright" title="Dress Me Up" src="http://www.sgtconker.com/wp-content/uploads/2010/04/4conker.jpg" alt="" width="152" height="304" /></p>
<p><a href="http://matthewrandall.com/">Matthew "BRUTAL" Randall</a> has been playing with WP7 &amp; XNA 4.0. He has developed a game/app called Dress Me Up.</p>
<p>Simple premise, yet makes good use of touch.</p>
<p>Check out the video on his site <a href="http://matthewrandall.com/?p=20">here</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.sgtconker.com/2010/04/dress-me-up-windows-phone-7/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>FGF 0.1.2.0 Released</title>
		<link>http://www.sgtconker.com/2010/02/fgf-0-1-2-0-released/</link>
		<comments>http://www.sgtconker.com/2010/02/fgf-0-1-2-0-released/#comments</comments>
		<pubDate>Sun, 21 Feb 2010 21:41:44 +0000</pubDate>
		<dc:creator>Captain boki</dc:creator>
				<category><![CDATA[Input]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[XNA]]></category>
		<category><![CDATA[FGF]]></category>
		<category><![CDATA[Gesture Recognition]]></category>

		<guid isPermaLink="false">http://www.sgtconker.com/2010/02/fgf-0-1-2-0-released/</guid>
		<description><![CDATA[Now with gesture recognition! And if you have to ask what FGF actually is: It’s the love child of John “Wild Gestures” Sedlak and expands to Focused Games Framework.
]]></description>
			<content:encoded><![CDATA[<p><a href="http://jsedlak.org/2010/02/21/fgf-0-1-2-0-released-with-gesture-recognition/"><em>Now with gesture recognition</em></a><em>!</em> And if you have to ask what <em>FGF</em> actually is: It’s the love child of <a href="http://jsedlak.org/">John “Wild Gestures” Sedlak</a> and expands to <a href="http://jsedlak.org/tag/fgf/">Focused Games Framework</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sgtconker.com/2010/02/fgf-0-1-2-0-released/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Article: Using XNA Content pipeline extensions for localization. (Part 2)</title>
		<link>http://www.sgtconker.com/2010/02/article-using-xna-content-pipeline-extensions-for-localization-part-2/</link>
		<comments>http://www.sgtconker.com/2010/02/article-using-xna-content-pipeline-extensions-for-localization-part-2/#comments</comments>
		<pubDate>Sat, 20 Feb 2010 10:53:43 +0000</pubDate>
		<dc:creator>Sgt. Conker</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Input]]></category>
		<category><![CDATA[XNA]]></category>
		<category><![CDATA[Content Pipeline]]></category>
		<category><![CDATA[Language]]></category>
		<category><![CDATA[Localization]]></category>

		<guid isPermaLink="false">http://www.sgtconker.com/?p=1116</guid>
		<description><![CDATA[After publishing part one and having a good week to think about part two, I found that some of my design choices, which seemed nice, where actually at bit cumbersome.]]></description>
			<content:encoded><![CDATA[<h4 style="text-align: center;">by <a href="http://roy-t.nl">Roy Triesscheijn</a></h4>
<p><a href="http://www.sgtconker.com/wp-content/uploads/2010/02/flag.png"><img class="alignright" title="flag" src="http://www.sgtconker.com/wp-content/uploads/2010/02/flag-300x194.png" alt="" width="240" height="155" /></a></p>
<h4>Recap</h4>
<p>So… last time we made our strings localizable and added-in a new content manager. Today we are going to make all our content localizable, but first we should revisit and refactor “yesterday’s code”.</p>
<p>After publishing part one and having a good week to think about part two, I found that some of my design choices, which seemed nice, where actually at bit cumbersome.<br />
Also the xml parsing (in BABProcessor) wasn’t as robust as I wanted it to be because I forgot about localized formats for dates and numbers.<br />
Fixing our xml loading is easy, so let’s first fix that!</p>
<p><span id="more-1116"></span></p>
<h4>Refactoring BABProcessor</h4>
<p>Load up your previous code, or the source code from last week and go to the BABProcessor.cs file. In the switch in our method Process we parse our version number without caring for localized number formats.<br />
Because of this the version number “1.0” might be parsed as 10 instead of 1 on some computers. So change the code in case version to this:</p>
<pre class="brush: csharp; title: ;">Double.TryParse(node.InnerText, NumberStyles.Any, CultureInfo.InvariantCulture,out output.version);</pre>
<p>Here we tell Double.TryParse to parse the number with an InvariantCulture, so 1.0 will always be interpreted as 1.<br />
The next troubling line is where we parse dates. In Europe we usually write dates as 31-01-2010 (dd-mm-yyyy) but in the U.S. 01-31-2010 (mm-dd-yyyy) is more common, and in Japan they use 2010-01-31 (yyyy-mm-dd). Based on the computers local settings dates will be parsed differently,<br />
so let’s drop down to the revision date case and change the code to this:</p>
<pre class="brush: csharp; title: ;">DateTime.TryParseExact(node.InnerText, &quot;dd-mm-yyyy&quot;, CultureInfo.InvariantCulture, DateTimeStyles.None, out output.revision);  </pre>
<p>Here we explicitly specify the format used for parsing the revision date in our xml file. (Of course you can change this to something of your liking).<br />
One last thing, I forgot to delete the following line from the package case:</p>
<pre class="brush: csharp; title: ;">Dictionary&lt;string, string&gt; package = new Dictionary&lt;string, string&gt;();</pre>
<p>You can remove this as it’s not used at all, sorry about that, I totally missed that line when doing my final checkup.<br />
Alright so that’s it for cleaing up our BABProcessor.</p>
<h4>Refactoring BabylonContent</h4>
<p>We’re also going to refactor our new content manager. As I was tinkering with the code for localizing other content/assets I noticed that the code for strings was doing some extra unneeded caching.<br />
I forgot that all content we load using our Content Manager is cached for us, so we don’t need the extra caching. (This is not <a href="http://roy-t.nl/index.php/2008/08/27/9/">the first time</a> I forgot this).<br />
But remembering this again allows us to make our content manger much simpler.<br />
Remove the following lines:</p>
<pre class="brush: csharp; title: ;">
private Dictionary&lt;string, Dictionary&lt;string, string&gt;&gt; packages;
language = ProperString(value);
</pre>
<p>Now replace the entire GetString method with this method:</p>
<pre class="brush: csharp; title: ;">
private string GetString(string path, string package, string key, string packageLanguage)
{
	try
	{
		BABFile localization = base.Load&lt;BABFile&gt;(path + package + &quot;.&quot; + packageLanguage);
        if (localization.keys.Keys.Contains(key))
        {
			return localization.keys[key];
        }
    }
	catch (ContentLoadException e){}
	//Now try to load the content using the default language
    //but only if the current language isn't the default language
    //else we would get stuck in ãn infinite loop.
    if (!packageLanguage.Equals(DEFAULTLANGUAGE))
    {
		return GetString(path, package, key, DEFAULTLANGUAGE);
    }
    else
    {
		//The string searched for couldnt be found in the
        //translated file or the default file.
        //Replace this by an exception if you want to test your game better
        return &quot;&quot;;
    }
}
</pre>
<p>As you can see this method is a lot shorter and no longer an exception is thrown if the key doesn’t exist. It also fixes another problem I had with the GetString method, you couldn’t do this:</p>
<pre class="brush: csharp; title: ;">Content.Load&lt;String&gt;(@”SomePath\Package.key”);</pre>
<p>So I fixed that in this version, nothing really new here so I’m moving on to the next subject. Add a new Load method.</p>
<pre class="brush: csharp; title: ;">
public T Load&lt;T&gt;(string assetName, string specificLanguage)
{
	if (typeof(T) == typeof(String))
    {
		string folder = assetName.Substring(0, assetName.LastIndexOf('\\') + 1);
        string file = assetName.Substring(assetName.LastIndexOf('\\') + 1);
        string[] packageKey = file.Split('.');
        if (packageKey.Length &gt; 1)
        {
			//we convert to object and then T because we can't convert a valuetype to a (T) directly
            return (T)(object)GetString(folder, packageKey[0], packageKey[1], specificLanguage);
        }
        else
        {
			return base.Load&lt;T&gt;(assetName);
		}
	}
</pre>
<p>This parses the path for us so our new GetString method works correct. Now replace the method with the signature Load(string assetName) with this one:</p>
<pre class="brush: csharp; title: ;">
public override T Load&lt;T&gt;(string assetName)
{
	return Load&lt;T&gt;(assetName, language);
}
</pre>
<p>Well this means we are all done refactoring. These last changes allow us to load strings (and later on other content) in a specific language, other than the language currently set. While still having our old behaviour when someone just calls the normal Load method.</p>
<h4>The XML file,  BACFile, Importer and Processor</h4>
<p>Just as last time we are going to define an xml format, load that xml file and process it into a special class, this time called BACFile (for Babylon Content).<br />
Remember the general idea is that you can add in new languages fairly easy. We are going to do this by adding an xml file in every folder that contains content. We call this xml file “LocalizedContent.Language.bac”. In this xml file we specify what files are localized versions of other files. Now every time our new content manager is asked to load content it first opens the “LocalizedContent.Lanuage.bac” file (where Language is the current language, note that  the content manager automatically caches these files for us). If the file can’t be loaded or if there exists no key for the given asset, we just load the asset as normal. If there is a file with a key referencing the file we want to load, we get a new filename from the key, and load that one instead.<br />
Simple huh?  Let’s first define a suitable xml-file:</p>
<pre class="brush: plain; title: ;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
&lt;XNABabylonContentFile&gt;
  &lt;version&gt;1.0&lt;/version&gt;
  &lt;revisionDate&gt;3-2-2010&lt;/revisionDate&gt;
  &lt;author&gt;Roy Triesscheijn&lt;/author&gt;
  &lt;language&gt;English&lt;/language&gt;
  &lt;!--Files that are already in the correct language can just reference themselves--&gt;
  &lt;!--Or can be left out--&gt;
  &lt;localization&gt;
    &lt;key con=&quot;Texture01&quot; loc=&quot;Texture01&quot;/&gt;
  &lt;/localization&gt;
&lt;/XNABabylonContentFile&gt;
</pre>
<p>As you can see this file defines that for the content (con) “Texture01” the localized english version is “Texture01”.<br />
Now because parsing and processing these .bac files is gonna be almost the same as processing the bab files from part1, I’m just going to put down the code here, with little comments. (You could also just download the sourcecode and copy BACFile.cs, BACImporter.cs and BACProcessor.cs to your project).</p>
<p><strong>BACFile.cs</strong></p>
<p>First we need a container, create a new class, mark it serializable and write code simmilar to this in the class body:</p>
<pre class="brush: csharp; title: ;">
public string language;
public double version;
public string author;
public DateTime revision;
//Other than in the BABFile the BACFile
//doesnt store a direct translation but a string
//naming the translated file.
public Dictionary&lt;string, string&gt; keys;

public BACFile()
{
	keys = new Dictionary&lt;string, string&gt;();
}
</pre>
<p><strong>BACImporter.cs</strong></p>
<p>Now we need an importer, create a new class called BACImporter, and just copy the contents of BABImporter into the new class file. All you need to change is the class name (obviously to BACImporter). And the ContentImporter directives (register extension “.bac” instead of “.bab”, change the display name, and set defaultprocessor to “BACProcessor”.)<br />
Keep the method Import the same, but change the error message so we know it was a babylon content file, and not a babylon string file, that was invalid.</p>
<p><strong>BACProcessor.cs</strong><br />
Again just copy the content of BABProcessor into a new class called BACProcessor. Now change</p>
<pre class="brush: csharp; title: ;">using TOutput = XNABabylon.Importers.BABFile;</pre>
<p>To</p>
<pre class="brush: csharp; title: ;">using TOutput = XNABabylon.Importers.BACFile;</pre>
<p>Change the display name to “XNA Babylon .bac Processor” .  Now in the method Process change the line:</p>
<pre class="brush: csharp; title: ;">TOutput output = new BABFile();</pre>
<p>To:</p>
<pre class="brush: csharp; title: ;">
TOutput output = new BACFile();
</pre>
<p>And change the lines:</p>
<pre class="brush: csharp; title: ;">
if(input.GetElementsByTagName(&quot;XNABabylonStringFile&quot;).Count &gt; 0)
{
	foreach (XmlNode node in input.GetElementsByTagName(&quot;XNABabylonStringFile&quot;)[0].ChildNodes)
</pre>
<p>To:</p>
<pre class="brush: csharp; title: ;">
if (input.GetElementsByTagName(&quot;XNABabylonContentFile&quot;).Count &gt; 0)
{
	foreach (XmlNode node in input.GetElementsByTagName(&quot;XNABabylonContentFile&quot;)[0].ChildNodes)
</pre>
<p>So almost there. Locate the case package, remove it and add  this new case instead</p>
<pre class="brush: csharp; title: ;">
case &quot;localization&quot;:
//Loop trough all the keys and store the name of the original content (con)
//and name of the translated file (loc) into a dictionary
foreach (XmlNode key in node.ChildNodes)
{
    output.keys.Add(key.Attributes[&quot;con&quot;].InnerText, key.Attributes[&quot;loc&quot;].InnerText);
}
break;
</pre>
<p>Test our new additions to the content pipeline extension by creating the .bac file provided a bit above and adding it to your test project, make sure to set the Build Action to compile and to set the bac importer and processor. If everything is well, you should be able to compile without problems.</p>
<h4>Adding new methods to our content manager</h4>
<p>With all this new data available, we should update our content manager to use it. Go to BabylonContent.cs and let’s create a new method with the following signature:</p>
<pre class="brush: csharp; title: ;">private T GetContent&lt;T&gt;(string path, string file, string packageLanguage)</pre>
<p>This method will function just like the GetString method. And will be very short tbh. All the code in the method body is this:</p>
<pre class="brush: csharp; title: ;">
try
{
    BACFile localization = base.Load&lt;BACFile&gt;(path + &quot;LocalizedContent.&quot; + packageLanguage);
    if (localization.keys.Keys.Contains(file))
    {
        return base.Load&lt;T&gt;(path + localization.keys[file]);
    }
}
catch(ContentLoadException e){}

//If we got to here we couldnt load the localization file or localized content
//So try to load the unlocalized/default content.
return base.Load&lt;T&gt;(path + file);
</pre>
<p>As you can see we do nothing more than loading the LocalizedContent.Language.bac file in the requested folder, checking if there is a key for the requested asset, if so load that one, else, or on an exception, just load the normal one.<br />
We can use this for all content types, but that means that all content needs to take the extra steps trough localization, which would be silly if we know in advance that some piece of content doesn’t need to be localized.<br />
We can control it ourselves by adding this method (which we do):</p>
<pre class="brush: csharp; title: ;">
public T Load&lt;T&gt;(string assetName, bool skipLocalization)
{
	if (skipLocalization)
    {
		return base.Load&lt;T&gt;(assetName);
    }
    else
    {
		return Load&lt;T&gt;(assetName);
    }
}
</pre>
<p>But there might be some types of files that we never want to be localized (spritefonts for example). Therefor we are going to make a list of types we do want localized.<br />
Todo this, add the folowing list and helper functions:</p>
<pre class="brush: csharp; title: ;">
//Stores all the types we want our processor to handle
//Types not in this list will just be directly forwarded to the base class
private List&lt;Type&gt; processable;

//'Properties' for the processable list

/// &lt;summary&gt;
/// Add a new type to the processable list.
/// Assets of this type will now be localized
/// when loaded (if possible).
/// &lt;/summary&gt;
public void AddProcessableType(Type t)
{
    processable.Add(t);
}

/// &lt;summary&gt;
/// Removes a type from the processable list
/// Assets of thys type will no longer be
/// localized when loaded.
/// &lt;/summary&gt;
public void RemoveProcessableType(Type t)
{
    processable.Remove(t);
}

/// &lt;summary&gt;
/// Clears all the types from the processable
/// list. No more content will be localized
/// when loaded from now on. Until new
/// types are added via AddProcessableType(..)
/// &lt;/summary&gt;
public void ClearProcessableTypes()
{
    processable.Clear();
}

/// &lt;summary&gt;
/// Returns an array of all types currently
/// in the processable list. Assets of these
/// types will be localized (if possible).
/// &lt;/summary&gt;
public Type[] GetProcessableTypes()
{
    return processable.ToArray();
}
</pre>
<p>This way we can adjust, at runtime, what types of files should not be localized.<br />
In the constructor add the following lines:</p>
<pre class="brush: csharp; title: ;">
processable = new List&lt;Type&gt;();
//Add some default types that we process
processable.Add(typeof(String));
processable.Add(typeof(Texture));
processable.Add(typeof(Texture2D));
processable.Add(typeof(SoundEffect));
</pre>
<p>This way we have some sensible default types that will be localized (unless they are removed from our processable list).<br />
All we need to do now, is adjust our Load&lt;&gt; function to incorporate these changes, and ofcourse we still need to add a call to our GetContent method!<br />
Add these lines in the method with signature</p>
<pre class="brush: csharp; title: ;">public T Load&lt;T&gt;(string assetName, string specificLanguage)</pre>
<p>In between the if and the else (so we get an if, else if, else).</p>
<pre class="brush: csharp; title: ;">
else if (processable.Contains(typeof(T)))
{
string folder = assetName.Substring(0, assetName.LastIndexOf('\\') + 1);
string file = assetName.Substring(assetName.LastIndexOf('\\') + 1);
return (T)GetContent&lt;T&gt;(folder, file, specificLanguage);
}
</pre>
<p>Ah now it should all start coming togheter. Still a few checkups though. The normal (overriden) load method should look like this:</p>
<pre class="brush: csharp; title: ;">
public override T Load&lt;T&gt;(string assetName)
{
	return Load&lt;T&gt;(assetName, language);
}
</pre>
<p>Okay now we have 3 Load methods, let’s recap a bit what they are for.</p>
<ul>
<li>1.	Load(string assetName)</li>
<li>2.	Load(string assetName, bool skipLocalization)</li>
<li>3.	Load(string assetName, string specificLanguage)</li>
</ul>
<p>Okay 1 is just the normal load function. This should normally be used.<br />
Now 2 allows us to bypass all the fancy stuff and just load the file we want, without the localization overhead (for example, for stuff that doesn’t have to be localized).<br />
And 3 is the workhorse, it is called by 1, with as specificLanguage argument, the language currently set to the application. We can aslo call it ourselves with a language we want translation to. (For example for the title screen where we want to display instructions in multiple languages).<br />
(note that only 1 is visible if you don’t cast to BabylonContent).</p>
<h4>Sample project and conclusions</h4>
<p>This time I will not go into more details in how to make a test project. Please download the source code, a test project is acompanied there. It will show you two flags, and based on the flag chosen it will show the rest of the ‘game’ in that language. It will use all 3 different Load methods to demonstrate there uses.</p>
<p><a href="http://www.sgtconker.com/wp-content/uploads/2010/02/flag.png"><img class="alignnone size-medium wp-image-1127" title="flag" src="http://www.sgtconker.com/wp-content/uploads/2010/02/flag-300x194.png" alt="" width="300" height="194" /></a></p>
<p>I think it’s fair to conclude that this way of localization is fairly easy, the amount of code we need is pretty slim. And it’s hot pluggable into any existing game. Once you h ave created new localized content it’s easy to update your game to use it. (Just update the xml file). I think this method  of localization has never been applied before, but I do think it’s a valid, and efficient way.</p>
<p>Please download the sourcode <a href="http://www.sgtconker.com/Downloads/articles/XNABabylonpt2.zip">HERE</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sgtconker.com/2010/02/article-using-xna-content-pipeline-extensions-for-localization-part-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>HOWTO: show drawing items with the mouse in XNA</title>
		<link>http://www.sgtconker.com/2010/02/howto-show-drawing-items-with-the-mouse-in-xna/</link>
		<comments>http://www.sgtconker.com/2010/02/howto-show-drawing-items-with-the-mouse-in-xna/#comments</comments>
		<pubDate>Wed, 03 Feb 2010 21:33:46 +0000</pubDate>
		<dc:creator>Captain boki</dc:creator>
				<category><![CDATA[2D]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Input]]></category>
		<category><![CDATA[XNA]]></category>

		<guid isPermaLink="false">http://www.sgtconker.com/?p=1040</guid>
		<description><![CDATA[Jakob Krarup answers an unidentified question in the XNA Community Forums about “how to give a player the possibility of adding things to a game, and storing the position of the added images”.
]]></description>
			<content:encoded><![CDATA[<p><a href="http://xnafan.net/">Jakob Krarup</a> answers an unidentified question in the <a href="http://forums.xna.com/forums/">XNA Community Forums</a> about “<a href="http://xnafan.net/?p=196">how to give a player the possibility of adding things to a game, and storing the position of the added images</a>”.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sgtconker.com/2010/02/howto-show-drawing-items-with-the-mouse-in-xna/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Display Orientation on the ZuneHD</title>
		<link>http://www.sgtconker.com/2010/01/display-orientation-on-the-zunehd/</link>
		<comments>http://www.sgtconker.com/2010/01/display-orientation-on-the-zunehd/#comments</comments>
		<pubDate>Fri, 22 Jan 2010 08:19:07 +0000</pubDate>
		<dc:creator>Captain ZSquare</dc:creator>
				<category><![CDATA[2D]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Input]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[XNA]]></category>
		<category><![CDATA[ZuneHD]]></category>
		<category><![CDATA[FGF]]></category>
		<category><![CDATA[John Sedlak]]></category>
		<category><![CDATA[MVP]]></category>
		<category><![CDATA[Zune HD]]></category>

		<guid isPermaLink="false">http://www.sgtconker.com/?p=941</guid>
		<description><![CDATA[John Sedlak has two posts about using his FGF framework while working on the Zune HD and dealing with orientation.
He talks about how to support rotating and resizing of the display on the Zune HD (which supports both landscape and portrait gaming) and then continues with more explanations.
]]></description>
			<content:encoded><![CDATA[<p>John Sedlak has two posts about using his FGF framework while working on the Zune HD and dealing with orientation.</p>
<p>He talks about <a href="http://jsedlak.org/2010/01/11/fgf-display-orientation-on-the-zune-hd/">how to support rotating and resizing of the display on the Zune HD</a> (which supports both landscape and portrait gaming) and then continues with <a href="http://jsedlak.org/2010/01/12/fgf-oriented-drawing/">more explanations</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sgtconker.com/2010/01/display-orientation-on-the-zunehd/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Names Actions Sample</title>
		<link>http://www.sgtconker.com/2010/01/names-actions-sample/</link>
		<comments>http://www.sgtconker.com/2010/01/names-actions-sample/#comments</comments>
		<pubDate>Thu, 07 Jan 2010 18:26:57 +0000</pubDate>
		<dc:creator>Captain ZSquare</dc:creator>
				<category><![CDATA[Input]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[XNA]]></category>
		<category><![CDATA[Michael Quandt]]></category>

		<guid isPermaLink="false">http://www.sgtconker.com/?p=888</guid>
		<description><![CDATA[Michael Quandt posted a new sample a new sample on his site, showing how to "create named actions which support the GamePad, Keyboard and Mouse".
Go read his explanations and download it to see if it could be useful for your own games.
]]></description>
			<content:encoded><![CDATA[<p>Michael Quandt posted a new sample a new sample on his site, showing how to<em> "create named actions which support the GamePad, Keyboard and Mouse".</em></p>
<p>Go<a href="http://mquandt.com/blog/2010/01/xna-input-manager-sample/"> read his explanations</a> and download it to see if it could be useful for your own games.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sgtconker.com/2010/01/names-actions-sample/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Extending the GamePadState</title>
		<link>http://www.sgtconker.com/2009/11/extending-the-gamepadstate/</link>
		<comments>http://www.sgtconker.com/2009/11/extending-the-gamepadstate/#comments</comments>
		<pubDate>Sun, 29 Nov 2009 15:19:25 +0000</pubDate>
		<dc:creator>Captain ZSquare</dc:creator>
				<category><![CDATA[Input]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[XNA]]></category>
		<category><![CDATA[Extensions]]></category>
		<category><![CDATA[MVP]]></category>
		<category><![CDATA[Nick Gravelyn]]></category>

		<guid isPermaLink="false">http://www.sgtconker.com/?p=636</guid>
		<description><![CDATA[Ever wished there was an easier way to test if one of a set of buttons are pressed on a gamepad instead of writing a very long if statement?
Nick "Don't call me 'I do too much' anymore!" Gravelyn shows how you can do exactly that in his new post called Extending GamePadState.

]]></description>
			<content:encoded><![CDATA[<p>Ever wished there was an easier way to test if one of a set of buttons are pressed on a gamepad instead of writing a very long <em>if</em> statement?</p>
<p>Nick "Don't call me <em>'I do too much'</em> anymore!" Gravelyn shows how you can do exactly that in his new post called <a href="http://nickgravelyn.com/2009/11/extending-gamepadstate/">Extending GamePadState</a>.</p>
<h2></h2>
]]></content:encoded>
			<wfw:commentRss>http://www.sgtconker.com/2009/11/extending-the-gamepadstate/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Article : Pie Menu</title>
		<link>http://www.sgtconker.com/2009/10/article-pie-menu/</link>
		<comments>http://www.sgtconker.com/2009/10/article-pie-menu/#comments</comments>
		<pubDate>Wed, 21 Oct 2009 13:33:52 +0000</pubDate>
		<dc:creator>Captain ZSquare</dc:creator>
				<category><![CDATA[2D]]></category>
		<category><![CDATA[Articles]]></category>
		<category><![CDATA[Input]]></category>
		<category><![CDATA[UI]]></category>
		<category><![CDATA[XNA]]></category>

		<guid isPermaLink="false">http://sgt.conkerjo.com/?p=147</guid>
		<description><![CDATA[For the people who want some UI stuff in XNA, here’s a small sample that contains a Pie Menu Component, attached to a cursor.]]></description>
			<content:encoded><![CDATA[<h4 style="text-align: center;">by <a href="http://www.catalinzima.com/">Catalin Zima</a></h4>
<p><strong>Pie Menu</strong><br />
<img class="alignright size-thumbnail wp-image-150" title="piemenupic" src="http://www.sgtconker.co.uk/wp-content/uploads/2009/10/piemenupic-150x150.png" alt="piemenupic" width="150" height="150" /><br />
For the people who want some UI stuff in XNA, here’s a small sample that contains a Pie Menu Component, attached to a cursor. If you don’t know what a pie menu is, read about it on <a href="http://en.wikipedia.org/wiki/Pie_menu">wikipedia</a>.<br />
<span id="more-147"></span></p>
<p>Now, about the sample.</p>
<p>My PieMenu supports deep menus. Currently it is just a quick version, made in two days. Because of this, the graphics are not spectacular, and some things may not be extremely flexible right now (the parameters passed to delegates).</p>
<p>But as it is, each menu entry has associated with it an image, a text description, and a delegate, for the action that should be performed. The PieMenu also supports submenus, as seen in this sample.</p>
<p>The cursor can operate in two modes: mouse-friendly and gamepad friendly. In the mouse friendly mode, the menu options are selected with the cursor, while in gamepad friendly mode, they are selected with the left thumbstick.</p>
<p>The current sample contains the following menus:</p>
<ul>
<li>Change Gamerpic: allows navigation through a series of submenus, to select a gamerpic that will be displayed in the window</li>
<li>Change Background Color: randomly chooses a new background color</li>
<li>Toggle Input Mode: toggles between the mouse and gamepad friendly input modes. Default is mouse, so if you don’t have a gamepad, don’t worry.</li>
<li>Exit : exits the sample.</li>
</ul>
<p>This is just as an example. The menu can be easily customized. Also, the Cursor.ShowPieMenu() function has an overload that allows you to specify the menu that will be shown. This allows for different menus, depending on the selected object (this is NOT illustrated in this sample)</p>
<p>Controls:</p>
<ul>
<li>Gamepad A or Mouse Click : open menu, or selected submenu</li>
<li>Gamepad B, or Mouse Click when no submenu selected: return to upper menu / exit menu</li>
</ul>
<p>You can find the sample <a href="http://www.sgtconker.co.uk/Downloads/articles/PieMenu.zip">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sgtconker.com/2009/10/article-pie-menu/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

