<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" media="screen" href="/styles/xslt/rss.xslt"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:c9="http://channel9.msdn.com">
<channel>
	<title>Channel 9</title>
    <atom:link rel="self" type="application/rss+xml" href="http://channel9.msdn.com/Niners/DennisDel/Posts/RSS"></atom:link>
    <itunes:summary></itunes:summary>
    <itunes:author>Microsoft</itunes:author>
    <itunes:subtitle></itunes:subtitle>
    <image>
      <url>http://mschnlnine.vo.llnwd.net/d1/Dev/App_Themes/C9/images/feedimage.png</url>
      <title>Channel 9</title>
      <link>http://channel9.msdn.com/Niners/DennisDel/Posts</link>
    </image>
    <itunes:image href=""></itunes:image>
    <itunes:category text="Technology"></itunes:category>
    <description>Channel 9 keeps you up to date with the latest news and behind the scenes info from Microsoft that developers love to keep up with. From LINQ to SilverLight – Watch videos and hear about all the cool technologies coming and the people behind them.</description>
    <link>http://channel9.msdn.com/Niners/DennisDel/Posts</link>
    <language>en</language>
    <pubDate>Fri, 24 May 2013 18:51:21 GMT</pubDate>
    <lastBuildDate>Fri, 24 May 2013 18:51:21 GMT</lastBuildDate>
    <generator>Rev9</generator>
    <c9:totalResults>29</c9:totalResults>
    <c9:pageCount>2</c9:pageCount>
    <c9:pageSize>25</c9:pageSize>
  <item>
      <title>MissionControl - A Flexible API for Remote Device Control</title>
      <description><![CDATA[<p>In a race to optimize everything, developers often go to extremes to build software that performs routine tasks. MissionControl is a system that allows users to program a control center that stores interfaces with attached hardware sensors, allowing the users to control any other devices that can be activated via the underlying protocol. For demo purposes, the MissionControl build at this point is compatible with the Phidgets IR hybrid sensor.</p><p>The system has two core components:</p><ul><li>A server application, which is a Win32 console application that handles incoming queries and returns data to the connected clients. This application runs on the desktop machine with the connected sensor. </li><li>The Windows Phone application that sends requests to the target server and can trigger a variety of pre-programmed commands. </li></ul><h1>The Basics</h1><h3>Hardware and Communication Infrastructure</h3><p>One of the most important parts of the project is the signal capture and replication hardware. For the purposes of this project, I decided to use a dual-mode <a href="http://www.phidgets.com/products.php?product_id=1055_0">Phidgets IR sensor</a>. It supports both IR code capture and subsequent replication. From a user’s perspective, this device also eliminates a substantial code-learning overhead as well as the potential error rate. Instead of searching for a device-specific hexadecimal sequence that later has to be transformed in a working IR code, the user simply has to point his remote control at the sensor and press the button that he wants accessible from a mobile device. Given that the capturing software is running on the target machine, once the sensor detects that a code can be repeated within an acceptable precision range, it will be automatically captured and stored, with all required transformations worked out in the backend using the free Phidgets SDK.</p><h3><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image0026.jpg"><img title="clip_image002" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image002_thumb3.jpg" alt="clip_image002" width="368" height="246" border="0"></a></h3><p>Even though I can, I don’t have to handle the binary code content received through the sensor—the Phidgets .NET libraries carry built-in types that contain all the processed metadata that I will discuss later in this article.</p><p>This sensor is connected through a USB port to a machine that acts as a communication gateway. This server should have port 6169 open for inbound connections.</p><p><strong>NOTE:</strong> <em>The port number can be changed, but you have to keep it consistent between your server and client applications.</em></p><p>The communication between the phone and the computer running the client is performed via a TCP channel—<a href="http://en.wikipedia.org/wiki/Internet_socket">sockets</a> are used to perform the initial connections and serialized data transfer. You can see the generalized data flow between the devices that are involved in the procedure in the graphic below:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image0046.jpg"><img title="clip_image004" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image004_thumb3.jpg" alt="clip_image004" width="520" height="289" border="0"></a></p><p>The server (desktop client) handles the local storage and release of all incoming IR codes. The mobile client has to know the location of the server—once specified and confirmed, it can send one of the pre-defined commands to it and either query the server for existing command groups (sets) or invoke one of the stored IR codes. When I pass data between devices, I use JSON for the serializable components. The data is also processed before being sent in order to speed-up the process—for example, on the server side the sets are serialized together with the associated codes. Like this:</p><p><pre class="brush: js">
[
{
    &quot;Name&quot;:&quot;batman&quot;,
    &quot;IsList&quot;:false,
    &quot;Commands&quot;:[
    {
        &quot;Name&quot;:&quot;test command&quot;,
        &quot;Code&quot;:{
            &quot;Mask&quot;:{
                &quot;BitSize&quot;:12,
                &quot;CodeData&quot;:&quot;AAA=&quot;
            },
            &quot;BitSize&quot;:12,
            &quot;Encoding&quot;:2,
            &quot;CarrierFrequency&quot;:38000,
            &quot;DutyCycle&quot;:50,
            &quot;Gap&quot;:44761,
            &quot;Header&quot;:[
            2374,
            606
            ],
            &quot;CodeData&quot;:&quot;DJA=&quot;,
            &quot;MinRepeat&quot;:5,
            &quot;One&quot;:[
            1189,
            606
            ],
            &quot;Repeat&quot;:null,
            &quot;Trail&quot;:0,
            &quot;Zero&quot;:[
            582,
            606
            ]
        }
    },
    {
        &quot;Name&quot;:&quot;turn off&quot;,
        &quot;Code&quot;:{
            &quot;Mask&quot;:{
                &quot;BitSize&quot;:12,
                &quot;CodeData&quot;:&quot;AAA=&quot;
            },
            &quot;BitSize&quot;:12,
            &quot;Encoding&quot;:2,
            &quot;CarrierFrequency&quot;:38000,
            &quot;DutyCycle&quot;:50,
            &quot;Gap&quot;:44770,
            &quot;Header&quot;:[
            2360,
            613
            ],
            &quot;CodeData&quot;:&quot;DJA=&quot;,
            &quot;MinRepeat&quot;:5,
            &quot;One&quot;:[
            1169,
            613
            ],
            &quot;Repeat&quot;:null,
            &quot;Trail&quot;:0,
            &quot;Zero&quot;:[
            585,
            613
            ]
        }
    }
    ]
}
]
</pre></p><p>The inherent problem with the JSON data above is the fact that the phone client does not need the information related to the code binary sequence and all the metadata that goes with it. So it is effectively stripped down and reduced to the names of the sets (when a list of sets is requested) and commands (when a list of commands is requested).</p><h3>The Data Model</h3><p>As you saw from the description above, the server organizes individual infrared codes in sets. A single set is a bundle of codes that may or may not be related to each other—ultimately, this is the user’s decision. A good example of using sets is organizing IR commands by rooms, devices or code types. Each set has a unique name on the server, therefore eliminating the possibility of a request conflict.</p><p>Each set stores individual commands built around the <strong>Command</strong> model:</p><p><pre class="brush: csharp">
namespace Coding4Fun.MissionControl.API.Models 
{ 
    public class Command 
    { 
        public Command() 
        { 
        } 
    
    public string Name { get; set; }     
    public SerializableIRCode Code { get; set; } 
    } 
}
</pre></p><p>Despite the obvious <strong>Name</strong> property, you can see that I am using a <strong>SerializableIRCode</strong> instance that is specific to each model. Before going any further, I need to mention that the Phidgets SDK offers the <strong>IRLearnedCode</strong> model to store code contents. I could have used it instead, but there is an issue that prevents me from doing that—there is no public constructor defined for <strong>IRLearnedCode</strong>, therefore there is no way to serialize it, either with the built-in .NET serialization capabilities or JSON.NET, which I am using in the context of the project.</p><p>Instead, I have this:</p><p><pre class="brush: csharp">
using Phidgets; 
namespace Coding4Fun.MissionControl.API.Models 
{     
    public class SerializableIRCode     
    {         
        public SerializableIRCode()         
        { 
            
        } 
        
    IRLearnedCode code;         
    public ToggleMask Mask { get; set; } 
    public int BitSize { get; set; } 
    public Phidgets.IRCodeInfo.IREncoding Encoding { get; set; } 
    public int CarrierFrequency { get; set; } 
    public int DutyCycle { get; set; } 
    public int Gap { get; set; } 
    public int[] Header { get; set; } 
    public byte[] CodeData { get; set; } 
    public int MinRepeat { get; set; } 
    public int[] One { get; set; } 
    public int[] Repeat { get; set; } 
    public int Trail { get; set; } 
    public int[] Zero { get; set; } 
    }     
}
</pre></p><p>It is an almost identical 1:1 copy of the original class, storing both the layout of the IR code and additional information related to its replication mechanism. You can learn more about each property listed in the model above by reading the <a href="http://www.phidgets.com/docs/IR_Remote_Control_Primer">official document on the topic</a>.</p><p><strong>ToggleMask</strong>, the identity bit carrier that helps marking the code as repeated or not, is also implemented through a built-in Phidgets SDK model, and it has the same problem as <strong>IRLearnedCode</strong>. I implemented this model to replace it in the serializable code:</p><p><pre class="brush: csharp">
namespace Coding4Fun.MissionControl.API.Models 
{ 
    public class ToggleMask 
    { 
        public ToggleMask() 
        { 
            
        } 

    public int BitSize { get; set; }         
    public byte[] CodeData { get; set; } 
    } 
}
</pre></p><p>I also needed an easy way to store all sets at once and carry all associated codes in a single instance retrieved from the storage. Here is the <strong>Set</strong> class:</p><p><pre class="brush: csharp">
namespace Coding4Fun.MissionControl.API.Models 
{     
    public class Set 
    { 
        public Set() 
        { 
            Commands = new List&lt;Command&gt;(); 
        } 
        
    public string Name { get; set; } 
    public bool IsList { get; set; } 
    public List&lt;Command&gt; Commands { get; set; } 
    } 
}
</pre></p><p>Notice that there is an <strong>IsList</strong> flag that allows me to specify how to display this specific list on the connecting device. This adds some level of flexibility for situations where the user wants to build a virtual remote for closely-related keys, such as digits. With that in mind, displaying those as a list might be inconvenient, wasting visual space on the client. But if the flag is set to false, the list can be displayed as a pad.</p><p>Also, when the server performs the data exchange, it provides a single “envelope” that allows the connecting device to easily understand what the server is trying to do:</p><p><pre class="brush: csharp">
namespace Coding4Fun.MissionControl.API.Models 
{     
    public class ServerResponse     
    {     
    public string Identifier { get; set; }     
    public string Marker { get; set; }     
    public string Content { get; set; }     
    } 
}
</pre></p><p>The <strong>Identifier</strong> property carries the server IP address. That way, when a device receives a response, it is able to either accept it, because it knows that a response is requested from a target location, or discard it because the user is no longer using the specific server.</p><p><strong>Marker</strong> carries the command type of the sent command, therefore giving the Windows Phone application a hint as to what to do with the data. The server can send the following commands:</p><ul><li><em>SET_LIST</em> – returns the list of sets that are currently available on the server. </li><li><em>SET_COMMANDS<strong>:</strong>SET_NAME<strong>:</strong>IS_LIST</em> – returns the list of commands that are associated with a given set that is currently stored on the server. </li><li><em>NOTIFICATION</em> – send a simple notification to the client; no further action is required. </li></ul><p>Last but not least, <strong>Content</strong> is used to push the necessary data that is associated with the given <strong>Marker</strong>. It can be either a JSON-based string that lists the sets or commands, or a plain-text message that is used as an alert for the end-user.</p><h1>Server Architecture</h1><p>The server is the only component of this entire system that does all the heavy lifting. It learns commands, stores them and then generates new IR signal requests, as controlled from any of the connected clients. Let’s take a closer look at what happens behind the scenes—to start, I am going to document the network infrastructure.</p><h3>The Network Layer</h3><p>In order to be a reliable system, the server needs to be always ready to accept an incoming connection. For that purpose, it is possible to use the <a href="http://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener.aspx">TcpListener</a> class—an “always on” receiver that can handle incoming TCP connections. I integrated it in my <strong>CoreStarter</strong> class that is used to start the listener when the application is launched:</p><p><pre class="brush: csharp">
namespace Coding4Fun.MissionControl.API 
{ 
    public class CoreStarter 
    { 
        static TcpListener listener; 
        
        public static void LaunchSocket()     
        {     
            Console.WriteLine(&quot;Starting socket server on port {0}...&quot;, Constants.DEFAULT_PORT); 
            listener = new TcpListener(NetworkHelper.GetLocalIPAddress(), Constants.DEFAULT_PORT); 
            listener.Start(); 
            
            for (int i = 0; i &lt; Constants.MAX_CONCURRENT_CLIENTS; i&#43;&#43;) 
            {     
                Thread socketThread = new Thread(new ThreadStart(ListenForData));     
                socketThread.Start(); 
            } 
        } 
        
        private static void ListenForData() 
        { 
            Console.WriteLine(&quot;Listener thread started.&quot;); 

            while (true) 
            { 
                Socket acceptedSocket = listener.AcceptSocket(); 
                using (MemoryStream coreStream = new MemoryStream()) 
                {     
                    try 
                    { 
                        Console.WriteLine(&quot;Incoming connection: {0}&quot;, acceptedSocket.RemoteEndPoint); 
                        
                        using (Stream sourceStream = new NetworkStream(acceptedSocket)) 
                        {     
                            sourceStream.ReadTimeout = Constants.SOCKET_READ_TIMEOUT; 
                            
                            byte[] buffer = new byte[Constants.DEFAULT_BUFFER_SIZE]; 
                            int i; 
                
                            while ((i = sourceStream.Read(buffer, 0, buffer.Length)) != 0) 
                            { 
                                coreStream.Write(buffer, 0, i); 
                            } 
                        } 
                    } 
                    catch 
                    { 
                        string data = Encoding.ASCII.GetString(coreStream.ToArray()); 
        
                        CommandHelper.InterpretCommand(data, acceptedSocket.RemoteEndPoint.ToString()); 
                    } 
                } 
            } 
        } 
    } 
}
</pre></p><p>When <strong>LaunchSocket</strong> is called, the listener is activated on the current machine. As I mentioned above, the port number can be arbitrarily assigned, but has to be consistent between connecting apps in order for the TCP links to be established. Because I expect that more than one device will be connecting to the service at a time, the listener is set as active across a constant number of threads.</p><p><strong>NOTE:</strong> By default, a there is a maximum limit of 5 simultaneous clients. Although this number can be adjusted, be aware of the requirements of each environment in which a limited number of potential devices can connect. Even though the performance footprint of each thread is minimal, it can have a negative effect if used in unnecessarily large instances.</p><p><strong>ListenForData</strong> is used to read the incoming stream. When an inbound connection is accepted, the data is read with the help of a fixed content buffer. Then a read timeout is specified to prevent situations where the stream was completely read but the application still waits to pull non-existent data. Once the timeout milestone is hit, an exception is thrown, which marks the end of the stream—at this point, the plain text data that was received (remember that both the server and client exchange text data only) is passed to the command interpreter—<strong>CommandHelper</strong>, with a reference to the source of the command.</p><p>The commands from the device are passed as serialized key-value pairs (<a href="http://msdn.microsoft.com/en-us/library/5tbh8a42.aspx">KeyValuePair&lt;T, T&gt;</a>), the key being the command with any possible suffixes, and the value being the contents of the command itself that helps the server identify the specific item in the local storage.</p><p><strong>InterpretCommand</strong>,in this case, does three things sequentially:</p><ol><li>Deserialize the incoming string and create a <strong>KeyValuePair&lt;string,string&gt;</strong> instance. </li><li>Process the command and check whether it is recognizable. </li><li>Send a response to the client, if deemed necessary by the command type. </li></ol><p>The serialization and deserialization is done via <a href="http://james.newtonking.com/projects/json-net.aspx">JSON.NET</a>. You can install this package in your console managed Win32 project and the Windows Phone application project via NuGet:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image0056.gif"><img title="clip_image005" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image005_thumb3.gif" alt="clip_image005" width="553" height="65" border="0"></a></p><p>The deserialization step is as simple as one line of C# code:</p><p><pre class="brush: csharp">
KeyValuePair&lt;string, string&gt; result = JsonConvert.DeserializeObject&lt;KeyValuePair&lt;string, string&gt;&gt;(rawCommand.Remove(0, rawCommand.IndexOf('{')));
</pre></p><p>The string is sanitized to ensure that only JSON content is being passed to the serializer.</p><p>Because of a relatively limited command set, I can put together the entire interpretation stack like this:</p><p><pre class="brush: csharp">
// Get the initial list of sets on the target server
if (result.Key == Constants.COMMAND_INIT)
{
    SendSets(sourceLocation);
}
// Create a new set on the target server
else if (result.Key.Contains(Constants.COMMAND_CREATE_SET))
{
    CreateSet(result, sourceLocation);
    SendSets(sourceLocation);
}
// Get the commands that are associated with a given set.
else if (result.Key == Constants.COMMAND_GET_COMMANDS)
{
    SendCommands(result.Value, sourceLocation);
}
// The client requested the server to learn a new command.
else if (result.Key.Contains(Constants.COMMAND_LEARN_COMMAND))
{
    LearnCommand(result, sourceLocation);
}
// The client requested one of the commands to be executed on the 
// target server.
else if (result.Key.Contains(Constants.COMMAND_EXECUTE))
{
    ExecuteCommand(result);
}
// The client has requested a set to be deleted from the target server.
else if (result.Key == Constants.COMMAND_DELETE_SET)
{
    DeleteSet(result.Value);
    SendSets(sourceLocation);
}
// The client has requested a set to be deleted from the target server.
else if (result.Key.Contains(Constants.COMMAND_DELETE_COMMAND))
{
    DeleteCommand(result);
    SendCommands(result.Key.Split(new char[] { ':' })[1], sourceLocation);
}
</pre></p><p>All commands are constants, declared in the local helper class:</p><p><pre class="brush: csharp">
public const string COMMAND_INIT = &quot;INIT&quot;; 

public const string COMMAND_CREATE_SET = &quot;CREATE_SET&quot;; 

public const string COMMAND_GET_COMMANDS = &quot;GET_COMMANDS&quot;; 

public const string COMMAND_LEARN_COMMAND = &quot;LEARN_COMMAND&quot;; 

public const string COMMAND_EXECUTE = &quot;EXECUTE&quot;; 

public const string COMMAND_DELETE_SET = &quot;DELETE_SET&quot;;
public const string COMMAND_DELETE_COMMAND = &quot;DELETE_COMMAND&quot;;
</pre></p><p>Notice that these are not the commands that the server sends back, but rather the commands it receives from connecting Windows Phone devices.</p><p>Let’s now take a look at the breakdown for each command.</p><p><strong>SendSets:</strong></p><p><pre class="brush: csharp">
/// &lt;summary&gt; 
/// Send the list of sets to the client that requested those. 
/// &lt;/summary&gt; 
/// &lt;param name=&quot;sourceLocation&quot;&gt;The location of the requesting client.&lt;/param&gt; 
private static void SendSets(string sourceLocation) 
{ 
    Console.WriteLine(&quot;Received an initial set query from {0}&quot;, sourceLocation);     
    ServerResponse response = new ServerResponse(); 
    response.Marker = &quot;SET_LIST&quot;; 
    response.Content = JsonConvert.SerializeObject(StorageHelper.GetRawSetNames()); 
    response.Identifier = NetworkHelper.GetLocalIPAddress().ToString(); 
    NetworkHelper.SendData(sourceLocation, JsonConvert.SerializeObject(response)); 
    Console.WriteLine(&quot;Sent the set list to {0}&quot;, sourceLocation);     
}
</pre></p><p>When this command is received, the server does not have to do much processing. It is only invoked when the client establishes the initiating link and needs to know what possible sets it can get from the target machine. The request is logged in the console and a server response is prepared that contains a serialized list of set names, which is later serialized as well and sent back to the source machine location.</p><p><strong>StorageHelper</strong> and <strong>NetworkHelper</strong> will be documented later in this article.</p><p><strong>CreateSet:</strong></p><p><pre class="brush: csharp">
/// &lt;summary&gt; 
/// Create a new set and store it on the local server. 
/// &lt;/summary&gt; 
/// &lt;param name=&quot;result&quot;&gt;The original deserialized command.&lt;/param&gt; 
/// &lt;param name=&quot;sourceLocation&quot;&gt;The location of the requesting client.&lt;/param&gt; 
private static void CreateSet(KeyValuePair&lt;string,string&gt; result, string sourceLocation) 
{ 
    bool isSuccessful = false; 
    string[] data = result.Key.Split(new char[] { ':' }); 
    
    Console.WriteLine(&quot;There is an attempt to create the {0} set from {1}.&quot;, result.Value, sourceLocation); 
    
    if (data[1].ToLower() == &quot;list&quot;) 
        isSuccessful = StorageHelper.AddSet(result.Value); 
    else 
        isSuccessful = StorageHelper.AddSet(result.Value, false); 
    
    if (isSuccessful) 
        Console.WriteLine(&quot;The {0} set was successfully created.&quot;, result.Value); 
    else 
        Console.WriteLine(&quot;Something happened and the {0} set was not created.&quot;, result.Value);     
}
</pre></p><p>When a mobile device attempts to create a new set on the server, it sends a command in the following format:</p><p><strong>CREATE_SET</strong>:<strong>list/pad</strong>, <strong>SET_NAME</strong></p><p>CreateSet will get the type of the set that was created, will check whether a set with the same name already exists and will either create it or ignore the command altogether. No notification is sent to the connecting device, but either the failure or the success of the command is registered in the local console.</p><p><strong>SendCommands:</strong></p><p><pre class="brush: csharp">
/// &lt;summary&gt;
/// Send a list of commands that are associated with the pushed set.
/// &lt;/summary&gt;
/// &lt;param name=&quot;setName&quot;&gt;The original deserialized command.&lt;/param&gt;
/// &lt;param name=&quot;sourceLocation&quot;&gt;The location of the requesting client.&lt;/param&gt;
private static void SendCommands(string setName, string sourceLocation)
{
    Console.WriteLine(&quot;There was a request to get the commands for the {0} set from {1}.&quot;, setName, sourceLocation);
    
    bool isList = StorageHelper.IsSetAList(setName);
    
    ServerResponse response = new ServerResponse();
    response.Marker = string.Format(&quot;SET_COMMANDS:{0}:{1}&quot;, setName, isList);
    response.Identifier = NetworkHelper.GetLocalIPAddress().ToString();
    response.Content = JsonConvert.SerializeObject(StorageHelper.GetRawCommandNames(setName));
    
    NetworkHelper.SendData(sourceLocation, JsonConvert.SerializeObject(response));
    
    Console.WriteLine(&quot;Command list for the {0} set were sent to {1}.&quot;, setName, sourceLocation);
}
</pre></p><p>Commands are sent in the same manner as sets—once the set is recognized, the names of the associated commands are retrieved and serialized inside a <strong>ServerResponse</strong> instance and then pushed back to the requesting device.</p><p><strong>LearnCommand:</strong></p><p><pre class="brush: csharp">
/// &lt;summary&gt; 
/// Learn a new command and store it on the target server. 
/// &lt;/summary&gt; 
/// &lt;param name=&quot;result&quot;&gt;The original deserialized command.&lt;/param&gt; 
/// &lt;param name=&quot;sourceLocation&quot;&gt;The location of the requesting client.&lt;/param&gt; 
private static void LearnCommand(KeyValuePair&lt;string,string&gt; result, string sourceLocation) 
{     
    Console.WriteLine(&quot;[!] Server in COMMAND LEARNING MODE! Point the remote towards the sensor and send a command.&quot;); 
    
    string[] data = result.Key.Split(new char[] { ':' });     
    var set = StorageHelper.GetSingleSet(StorageHelper.GetSets(), data[1]); 
    
    if (set != null)     
    {     
        if ((from c in set.Commands where c.Name == result.Value select c).FirstOrDefault() != null) 
        {     
            Console.WriteLine(&quot;Cannot learn command {0} for the following set: {1}. Command already exists.&quot;, data[1], result.Value); 
            
            ServerResponse response = new ServerResponse();     
            response.Marker = &quot;NOTIFICATION&quot;;     
            response.Identifier = NetworkHelper.GetLocalIPAddress().ToString(); 
            response.Content = &quot;We could not save the following command - &quot; &#43; result.Value &#43; &quot;. It already exists in the set.&quot;; 
            
            NetworkHelper.SendData(sourceLocation, JsonConvert.SerializeObject(response));     
        } 
        else 
        { 
            if (sensor == null) 
                sensor = new IR(); 
            
            sensor.open(-1); 

            sensor.waitForAttachment(); 
    
            sensor.Learn &#43;= (sender, args) =&gt; 
            { 
                Console.WriteLine(&quot;[!] Server learned the command and is no longer in COMMAND LEARNING MODE.&quot;); 
                IRLearnedCode code = args.LearnedCode; 
                code.CodeInfo.MinRepeat = 5; 
            
                Command command = new Command(); 
                command.Name = result.Value; 
                command.Code = IRCodeWorker.GetSerializableIRCode(code); 
                
                StorageHelper.AddCommand(command, set.Name); 
                
                ServerResponse response = new ServerResponse(); 
                response.Marker = &quot;NOTIFICATION&quot;; 
                response.Identifier = NetworkHelper.GetLocalIPAddress().ToString(); 
                response.Content = &quot;The following command has been stored: &quot; &#43; result.Value; 
                
                NetworkHelper.SendData(sourceLocation, JsonConvert.SerializeObject(response)); 
            }; 
        } 
    } 
}
</pre></p><p>Once a request was received that the server needs to learn a new command, an initial verification is done to make sure that the requested command name and set are not already taken. If neither the command nor the set exist, both will be created.</p><p>After the basic setup is complete, the IR sensor is activated and will be waiting for the command to be learned. The way it works is quite simple – the sensor will remain in learning mode until the point where it recognizes a command without error, being 100% sure that it can be reproduced internally. You will need to point your remote towards the sensor and hold the button you want captured for one or two seconds in order for the command to be learned.</p><p><strong>NOTE:</strong> To ensure that a proper transmission is done, I manually set the minimal repeat value to 5. This is the number of times the sensor will fire the same code towards the target. That is the optimal value for a target device to receive the code if the remote is pointed directly at it without necessarily triggering the same command twice or more.</p><p>After the command is learned, the code is processed and transformed into a serializable instance. The connecting client is then notified about whether the command was learned.</p><p><strong>ExecuteCommand:</strong></p><p><pre class="brush: csharp">
/// &lt;summary&gt; 
/// Execute one of the commands currently stored on the local server. 
/// &lt;/summary&gt; 
/// &lt;param name=&quot;result&quot;&gt;The original deserialized command.&lt;/param&gt; 
private static void ExecuteCommand(KeyValuePair&lt;string,string&gt; result) 
{ 
    string[] data = result.Key.Split(new char[] { ':' }); 

    var set = StorageHelper.GetSingleSet(StorageHelper.GetSets(), data[1]); 
    
    if (set != null) 
    {     
        var command = StorageHelper.GetSingleCommand(StorageHelper.GetCommands(set.Name), result.Value); 

        IRLearnedCode code = IRCodeWorker.GetLearnedCode(command.Code); 
        
        if (sensor == null) 
            sensor = new IR(); 

        sensor.open(-1); 
        sensor.waitForAttachment(); 
        sensor.transmit(code.Code, code.CodeInfo); 
        sensor.close(); 
    } 
}
</pre></p><p>Command execution relies on the hardware sensor. The phone sends a command execution request in the following format:</p><p><strong>EXECUTE</strong>:<strong>SET_NAME</strong>, <strong>COMMAND_NAME</strong></p><p>Once the command is parsed out and found in the local storage, the IR code is transformed back to a model that is recognizable by the Phidgets SDK and transmitted towards the location where the sensor is pointed at the time of the execution.</p><p><strong>DeleteSet:</strong></p><p><pre class="brush: csharp">
/// &lt;summary&gt; 
/// Delete a single set and all the associated commands 
/// &lt;/summary&gt; 
/// &lt;param name=&quot;target&quot;&gt;The name of the set.&lt;/param&gt; 
private static void DeleteSet(string target) 
{ 
    var sets = StorageHelper.GetSets(); 
    var targetSet = StorageHelper.GetSingleSet(sets, target); 
    
    if (targetSet != null) 
    { 
        StorageHelper.RemoveSet(sets, targetSet); 
    } 
}
</pre></p><p>When deleting a set, only the name of the set should be specified. The user will get a warning on the client side that requires a confirmation of the deletion. The server will blindly execute the command.</p><p><strong>DeleteCommand:</strong></p><p><pre class="brush: csharp">
private static void DeleteCommand(KeyValuePair&lt;string, string&gt; result)
{
    var sets = StorageHelper.GetSets();
    string setName = result.Key.Split(new char[] {':'})[1];
    var targetSet = StorageHelper.GetSingleSet(sets, setName);
    var command = (from c in targetSet.Commands where c.Name == result.Value select c).FirstOrDefault();
    
    if (command != null)
    {
        targetSet.Commands.Remove(command);
        StorageHelper.SerializeSets(sets);
    }
}
</pre></p><p>Not only can the user remove entire sets, but he can also target specific commands from a given set. Once a <strong>DELETE_COMMAND</strong> directive is recognized, the set name is parsed out from the original string, that follows the <strong>DELETE_COMMAND:SET_NAME, COMMAND_NAME</strong> format, and a simple LINQ query extracts the command instance, removes it and stores the set content on the local hard drive.</p><p>Notice that for some commands, particularly for set creation, deletion and command deletion, the server will return a list of the remaining items. The contents will be automatically updated on the devices, which will be waiting for that response. This measure was deliberately introduced to minimize the chances of a user triggering a command that was already deleted or trying to query a previously removed set.</p><h3>Transforming Codes</h3><p>You might have noticed that I am using <strong>IRCodeWorker.GetSerializableCodeType</strong> to transform a Phidgets SDK native IR code model into a serializable one. This is a helper function that performs a field copy of the existing object. Because of the differences in the model structure, it has to be done manually:</p><p><pre class="brush: csharp">
public static SerializableIRCode GetSerializableIRCode(IRLearnedCode code) 
{ 
    SerializableIRCode sCode = new SerializableIRCode();     
    sCode.BitSize = code.Code.BitCount;     
    sCode.Encoding = code.CodeInfo.Encoding;     
    sCode.CarrierFrequency = code.CodeInfo.CarrierFrequency;     
    sCode.CodeData = code.Code.Data;     
    sCode.DutyCycle = code.CodeInfo.DutyCycle;     
    sCode.Gap = code.CodeInfo.Gap;     
    sCode.Header = code.CodeInfo.Header;     
    sCode.MinRepeat = 5;     
    sCode.One = code.CodeInfo.One;     
    sCode.Repeat = code.CodeInfo.Repeat;     
    sCode.Trail = code.CodeInfo.Trail;     
    sCode.Zero = code.CodeInfo.Zero;     
    sCode.Mask = new ToggleMask()     
    {         
        BitSize = code.CodeInfo.ToggleMask.BitCount,         
        CodeData = code.CodeInfo.ToggleMask.Data         
    }; 
    
    return sCode;     
}
</pre></p><p>The reverse process is easier because I can pass each of the existing properties to the <strong>IRCodeInfo</strong> constructor. The only difference is the fact that I need to use Reflection to create an instance of <strong>IRLearnedCode</strong> because there is no public constructor defined and a dynamic object has to be created:</p><p><pre class="brush: csharp">
internal static IRLearnedCode GetLearnedCode(SerializableIRCode serializableIRCode) 
{ 
    IRCode code = new IRCode(serializableIRCode.CodeData, serializableIRCode.BitSize);     
    IRCodeInfo info = new IRCodeInfo(serializableIRCode.Encoding, serializableIRCode.BitSize, serializableIRCode.Header,     
    serializableIRCode.Zero, serializableIRCode.One, serializableIRCode.Trail, serializableIRCode.Gap, serializableIRCode.Repeat, 
serializableIRCode.MinRepeat, serializableIRCode.Mask.CodeData, IRCodeInfo.IRCodeLength.Constant,
serializableIRCode.CarrierFrequency, serializableIRCode.DutyCycle); 
    
    object[] parameters = new object[] { code, info }; 
    
    BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Instance; 
    object instantType = Activator.CreateInstance(typeof(IRLearnedCode), flags, null, parameters, null); 

    return (IRLearnedCode)instantType; 
}
</pre></p><h3>Command and Set Management</h3><p>Looking back at the code that I put together for the command interpreter, there is one class that does all local content manipulation—<strong>StorageHelper</strong>. This is a simple class that performs LINQ queries on set as well as command collections, and makes sure that all the changes are preserved in the <strong>sets.xml</strong> file in the application folder that is used as the only storage place for all the content that is being manipulated by the server.</p><p><pre class="brush: csharp">
namespace Coding4Fun.MissionControl.API.Helpers 
{ 
    public class StorageHelper 
    { 
        
        /// &lt;summary&gt; 
        /// Lists all available sets that are currently stored on the server.         
        /// &lt;/summary&gt; 
        /// &lt;returns&gt;List of sets on the machine.&lt;/returns&gt;         
        internal static List&lt;Set&gt; GetSets()         
        {             
            List&lt;Set&gt; sets = null; 
            
            string rawContent = GetRawSets();             
            sets = JsonConvert.DeserializeObject&lt;List&lt;Set&gt;&gt;(rawContent); 
            
            return sets;             
        } 
        
        /// &lt;summary&gt;         
        /// Returns the list of commands that are associated with the given set.         
        /// &lt;/summary&gt;         
        /// &lt;param name=&quot;setName&quot;&gt;The name of the target set.&lt;/param&gt;         
        /// &lt;returns&gt;List of commands associated with the given set.&lt;/returns&gt;         
        internal static List&lt;Command&gt; GetCommands(string setName)         
        {             
            List&lt;Command&gt; commandList = null; 
            
            var sets = GetSets(); 
            
            Set singleSet = null;             
            if (sets != null)             
                singleSet = (from c in sets where c.Name == setName select c).FirstOrDefault(); 
            
            if (singleSet != null)         
            {         
                commandList = singleSet.Commands;     
            } 
            
            return commandList; 
        } 
        
        /// &lt;summary&gt;     
        /// Gets the list of names for the commands in the requested set. 
        /// &lt;/summary&gt; 
        /// &lt;param name=&quot;setName&quot;&gt;The name of the target set.&lt;/param&gt; 
        /// &lt;returns&gt;List of commands associated with the given set.&lt;/returns&gt; 
        internal static List&lt;string&gt; GetRawCommandNames(string setName) 
        { 
            List&lt;Command&gt; commandList = GetCommands(setName); 
            
            List&lt;string&gt; stringSet = null; 
            
            if (commandList != null) 
            {     
                stringSet = commandList.Select(x =&gt; x.Name).ToList();     
            } 
            
            return stringSet;     
        } 
        
        /// &lt;summary&gt; 
        /// Get the list of names for all sets on the local server. 
        /// &lt;/summary&gt; 
        /// &lt;returns&gt;List of sets on the machine.&lt;/returns&gt; 
        internal static List&lt;string&gt; GetRawSetNames() 
        {     
            List&lt;Set&gt; sets = GetSets(); 
            
            List&lt;string&gt; stringSet = null; 
    
            if (sets != null) 
            {     
                stringSet = sets.Select(x =&gt; x.Name).ToList();     
            } 
            
            return stringSet; 
        } 
        
        /// &lt;summary&gt; 
        /// Get the raw string contents of sets.xml. Should only be used in the 
        /// context of this class. 
        /// &lt;/summary&gt; 
        /// &lt;returns&gt;JSON string representing stored sets and commands.&lt;/returns&gt; 
        internal static string GetRawSets() 
        { 
            string sets = string.Empty; 
            
            if (File.Exists(&quot;sets&quot;)) 
            { 
                using (StreamReader reader = new StreamReader(File.OpenRead(&quot;sets&quot;))) 
                { 
                    sets = reader.ReadToEnd(); 
                } 
            } 
            else 
            { 
                FileStream stream = File.Create(&quot;sets.xml&quot;); 
                
                stream.Close();     
            } 
            
            return sets; 
        } 
        
        /// &lt;summary&gt; 
        /// Check whether a set is marked with a IsList flag. 
        /// &lt;/summary&gt; 
        /// &lt;param name=&quot;setName&quot;&gt;The name of the target set.&lt;/param&gt; 
        /// &lt;returns&gt;TRUE - set is a list. FALSE - set is not a list.&lt;/returns&gt; 
        internal static bool IsSetAList(string setName) 
        { 
            bool isList = true; 
            var sets = GetSets(); 
            Set set = null; 

            if (sets != null) 
                set = (from c in sets where c.Name == setName select c).FirstOrDefault(); 
            
            if (set != null) 
                isList = set.IsList; 
            
            return isList;     
        } 
        
        /// &lt;summary&gt; 
        /// Serialize the set collection to sets.xml 
        /// &lt;/summary&gt; 
        /// &lt;param name=&quot;sets&quot;&gt;Collection to be serialized.&lt;/param&gt; 
        /// &lt;returns&gt;true if sets are serialized.&lt;/returns&gt; 
        private static bool SerializeSets(List&lt;Set&gt; sets) 
        { 
            try 
            { 
                using (StreamWriter writer = new StreamWriter(&quot;sets.xml&quot;, false)) 
                {     
                    string data = JsonConvert.SerializeObject(sets); 
            
                    writer.Write(data); 
                } 
                
                return true; 
            } 
            catch 
            {     
                return false;     
            } 
        } 
        
        /// &lt;summary&gt; 
        /// Add a new set to the existing global set collection. 
        /// &lt;/summary&gt; 
        /// &lt;param name=&quot;name&quot;&gt;Set name.&lt;/param&gt; 
        /// &lt;returns&gt;true if successfully added set.&lt;/returns&gt; 
        internal static bool AddSet(string name, bool isList = true) 
        { 
            var sets = GetSets(); 

            if (sets == null) 
                sets = new List&lt;Set&gt;(); 
            
            var singleSet = GetSingleSet(sets, name); 

            if (singleSet == null) 
                sets.Add(new Set { Name = name, IsList = isList }); 
            
            if (SerializeSets(sets)) 
                return true; 
            else 
                return false; 
        } 
        
        /// &lt;summary&gt; 
        /// Retrieves a single set from a collection that has a specific name. 
        /// &lt;/summary&gt; 
        /// &lt;param name=&quot;sets&quot;&gt;The source collection from which to extract the set.&lt;/param&gt; 
        /// &lt;param name=&quot;name&quot;&gt;The name of the set to get.&lt;/param&gt; 
        /// &lt;returns&gt;An instance of the found set, if any.&lt;/returns&gt; 
        internal static Set GetSingleSet(List&lt;Set&gt; sets, string name) 
        { 
            if (sets != null) 
                return (from c in sets where c.Name == name select c).FirstOrDefault(); 
            else 
                return null; 
        } 
        
        /// &lt;summary&gt; 
        /// Add a IR command to an existing set. If the set is not found, it will be created. 
        /// &lt;/summary&gt; 
        /// &lt;param name=&quot;command&quot;&gt;The command instance to be added.&lt;/param&gt; 
        /// &lt;param name=&quot;targetSet&quot;&gt;The name of the target set.&lt;/param&gt; 
        /// &lt;returns&gt;true if the command was successfully added.&lt;/returns&gt; 
        internal static bool AddCommand(Command command, string targetSet) 
        { 
            var sets = GetSets(); 
            
            if (sets == null) 
                sets = new List&lt;Set&gt;(); 
            
            var singleSet = GetSingleSet(sets, targetSet); 
            
            if (singleSet == null) 
                singleSet = new Set { Name = targetSet }; 
            
            var singleCommand = (from c in singleSet.Commands where c.Name == command.Name select c).FirstOrDefault(); 
            
            if (singleCommand == null) 
            { 
                singleSet.Commands.Add(command); 
                
                if (SerializeSets(sets)) 
                    return true; 
                else 
                    return false; 
            } 
            else 
                return false; 
        } 
        
        /// &lt;summary&gt; 
        /// Retrieve a single command instance from one of the sets on the local server. 
        /// &lt;/summary&gt; 
        /// &lt;param name=&quot;commands&quot;&gt;Original list of commands.&lt;/param&gt; 
        /// &lt;param name=&quot;name&quot;&gt;Name of the command to be retrieved.&lt;/param&gt; 
        /// &lt;returns&gt;An instance of the command, if found. NULL if not.&lt;/returns&gt; 
        internal static Command GetSingleCommand(List&lt;Command&gt; commands, string name) 
        { 
            if (commands != null) 
                return (from c in commands where c.Name == name select c).FirstOrDefault(); 
            else 
                return null; 
        } 
        
        /// &lt;summary&gt; 
        /// Remove a set from a local machine. 
        /// &lt;/summary&gt; 
        /// &lt;param name=&quot;sets&quot;&gt;Original list of sets.&lt;/param&gt; 
        /// &lt;param name=&quot;targetSet&quot;&gt;Name of the set to remove.&lt;/param&gt; 
        internal static void RemoveSet(List&lt;Set&gt; sets, Set targetSet) 
        { 
            sets.Remove(targetSet); 
            
            SerializeSets(sets); 
        } 
    } 
}
</pre></p><h2>Sending Data Back to the Client</h2><p><strong>SendData</strong> in the <strong>NetworkHelper</strong> class handles all outbound connections. Here is its structure:</p><p><pre class="brush: csharp">
/// &lt;summary&gt; 
/// Send data to the target network machine. 
/// &lt;/summary&gt; 
/// &lt;param name=&quot;destination&quot;&gt;The target machine IP.&lt;/param&gt; 
/// &lt;param name=&quot;data&quot;&gt;Data to be sent, in string format.&lt;/param&gt; 
/// &lt;param name=&quot;sanitizeIp&quot;&gt;Determines whether to remove the port from the given IP string.&lt;/param&gt; 
public static void SendData(string destination, string data, bool sanitizeIp = true) 
{ 
    using (Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) 
    {     
        string completeIp = string.Empty; 
        
        if (sanitizeIp)     
            completeIp = destination.Remove(destination.IndexOf(&quot;:&quot;), destination.Length - destination.IndexOf(&quot;:&quot;)); 
        
        client.Connect(completeIp, 6169); 
        client.Send(Encoding.UTF8.GetBytes(data));     
    }     
}
</pre></p><p>A new stream socket is created in order to connect to the target machine over the TCP pipe. If IP sanitization is enabled, the port is stripped from the address in order to pass a valid IP. A <strong>Socket</strong> instance cannot directly handle IPs of the format:</p><p><strong><em>255.255.255.0:PORT_NUMBER</em></strong></p><p>Later, in a synchronous manner, a connection is established and the data is sent.</p><p>At this point, you can see that the barebones service offers a flexible way to manage content. It can be accessed by any application type as long as the server can be accessed and the application can send commands in the pre-defined format and the content requested is actually located on the target server. This allows for high levels of extensibility and interoperability, as the server usage is not limited to a single platform. If I decide to create a Windows Store application that would allow me to control my TV, I simply need to add socket connection layer that will send plain strings to the machine where the IR sensor is connected.</p><p>Similarly, if some functionality needs to be added, it is possible to do so without ever touching the client applications. A modification in the endpoint will be reflected with no direct effect on all connection applications as long as all handled returned and requested values are preserved. The only additional requirement is that if the client applications want to take advantage of newly introduced capabilities, they need to have an updated command transmission layer for the new command types.</p><p>In <strong>Program.cs</strong>, I simply need to start the server through the <strong>CoreStarter</strong> class:</p><p><pre class="brush: csharp">
namespace Coding4Fun.MissionControl.API 
{ 
    class Program     
    {         
        static void Main(string[] args)         
        {             
            Console.WriteLine(&quot;Coding4Fun MissionControl Server&quot;);             
            CoreStarter.LaunchSocket();             
        }         
    }     
}
</pre></p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image0076.jpg"><img title="clip_image007" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image007_thumb3.jpg" alt="clip_image007" width="527" height="267" border="0"></a></p><h1>Mobile client overview</h1><p>The mobile client does not have the capability to send commands directly to the IR sensor. Instead, it connects to a remote machine that has the IR sensor plugged in and attempts to invoke a command from the list returned by the service. A single mobile client can support control over multiple servers.</p><p><strong>NOTE:</strong> Make sure that at the time of working with the Windows Phone client, the server is actually running on your local machine. To make it easier to test, also open port 6169 for incoming connections in Windows Firewall.</p><p>When building a Windows Phone application, make sure you have the <a href="http://developer.windowsphone.com/en-us/downloadsdk">proper version of the SDK installed</a>, as well as a <a href="http://en.wikipedia.org/wiki/Second_Level_Address_Translation">SLAT-compatible</a> machine if you plan on testing the application in the emulator.</p><h2>Networking Infrastructure</h2><p>The Windows Phone application also relies on a network infrastructure somewhat similar to that of the server. There is a TCP listener that is created when the application is started:</p><p><pre class="brush: csharp">
// Code to execute when the application is launching (eg, from Start) 
// This code will not execute when the application is reactivated 
private void Application_Launching(object sender, LaunchingEventArgs e) 
{ 
    ServiceSerializer.DeserializeServices(); 
    
    listener.OnClientConnected &#43;= listener_OnClientConnected; 
    listener.Start(6169); 
}
</pre></p><p>Here, listener is an instance of <strong>TcpSocketListener</strong>—a custom class designed to handle incoming network connections:</p><p><pre class="brush: csharp">
namespace Coding4Fun.MissionControl.WP.Network 
{ 
    public class TcpSocketListener : SocketConnectorBase     
    {     
        StreamSocketListener coreSocket; 
        
        public async void Start(int port)     
        {     
            coreSocket = new StreamSocketListener();         
            coreSocket.ConnectionReceived &#43;= coreSocket_ConnectionReceived; 
            
            try     
            {         
                await coreSocket.BindServiceNameAsync(port.ToString());         
            }     
            catch (Exception ex) 
            {     
                Debug.WriteLine(ex.Message); 
                
                coreSocket.Dispose();     
                coreSocket = null; 
                OnConnectionCompleted(new ConnectionEventArgs { IsSuccessful = false, DeviceID = string.Empty }); 
            } 
        } 
        
        async void coreSocket_ConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args) 
        { 
            Debug.WriteLine(&quot;Connection received!&quot;); 
            
            DataReader reader = new DataReader(args.Socket.InputStream); 
            
            try 
            { 
                while (true) 
                { 
                    StringBuilder builder = new StringBuilder(); 
        
                    uint actualLength = 1; 

                    while (actualLength &gt; 0) 
                    {     
                        actualLength = await reader.LoadAsync(256); 
                        builder.Append(reader.ReadString(actualLength)); 
                    } 
                    
                    OnConnectionCompleted(new ConnectionEventArgs 
                    { 
                        Socket = args.Socket, 
                        IsSuccessful = true, 
                        DeviceID = args.Socket.Information.RemoteHostName.DisplayName, 
                        Token = builder.ToString() 
                    }); 
                    break; 
                } 
            } 
            catch (Exception exception) 
            { 
                Debug.WriteLine(exception.Message); 
                
                OnConnectionCompleted(new ConnectionEventArgs { IsSuccessful = false }); 
            } 
        } 
    } 
}
</pre></p><p>A <strong>StreamSocketListener</strong> is used for the connection core. When a connection is received, a continuous loop reads the entire contents of the incoming stream. <strong>OnConnectionCompleted</strong> is declared in the base class—<strong>SocketConnectorBase</strong>.</p><p><pre class="brush: csharp">
namespace Coding4Fun.MissionControl.WP.Network 
{ 
    public class SocketConnectorBase 
    { 
        public event EventHandler&lt;ConnectionEventArgs&gt; OnClientConnected; 
        public virtual void OnConnectionCompleted(ConnectionEventArgs connectionArgs) 
        { 
            if (OnClientConnected != null) 
            { 
                OnClientConnected(this, connectionArgs); 
            } 
        } 
        
        public event EventHandler&lt;bool&gt; OnSendCompletedEvent; 
        public virtual void OnSendCompleted(bool succeeded) 
        { 
            if (OnSendCompletedEvent != null) 
            { 
                OnSendCompletedEvent(this, succeeded); 
            } 
        } 
    } 
    
    public class ConnectionEventArgs : EventArgs 
    { 
        public StreamSocket Socket { get; set; }     
        public string DeviceID { get; set; }     
        public string Token { get; set; }     
        public bool IsSuccessful { get; set; }     
    } 
}
</pre></p><p><strong>ConnectionEventArgs</strong> here is used to identify the content that is passed to the client. <strong>DeviceID</strong> gives access to the source IP, <strong>IsSuccessful</strong> tells the developer whether the established connection is active and the <strong>Token</strong> carries the raw string if any was received.</p><p>Sending data is simplified to the maximum with the help of the <strong>SocketClient</strong> class, which relies on a <a href="http://msdn.microsoft.com/en-us/library/windows/apps/windows.networking.sockets.streamsocket.aspx">StreamSocket</a> instance that handles outbound connections and writing to the output stream:</p><p><pre class="brush: csharp">
namespace Coding4Fun.MissionControl.WP.Network 
{ 
    public class SocketClient : SocketConnectorBase 
    {     
        StreamSocket _socket; 
        
        public SocketClient() 
        {     
            _socket = new StreamSocket();     
        } 
        
        public SocketClient(StreamSocket socket) 
        {     
            _socket = socket;     
        } 
        
        public async void Connect(string hostName, int portNumber) 
        { 
            try 
            { 
                await _socket.ConnectAsync(new HostName(hostName), portNumber.ToString(), SocketProtectionLevel.PlainSocket); 
            
                OnConnectionCompleted(new ConnectionEventArgs { IsSuccessful = true }); 
            } 
            catch (Exception ex) 
            {     
                Debug.WriteLine(ex.Message); 
                
                OnConnectionCompleted(new ConnectionEventArgs { IsSuccessful = false });     
            } 
        } 
        
        public async void Send(string dataToSend) 
        { 
            try 
            {     
                using (DataWriter writer = new DataWriter(_socket.OutputStream)) 
                { 
                    // Write the length of the binary data that is being 
                    // sent to the client. 
                    writer.WriteUInt32((UInt32)dataToSend.Length); 
                    
                    writer.WriteString(dataToSend); 
        
                    // Send the actual data. 
                    await writer.StoreAsync(); 
                    
                    writer.DetachStream(); 
                    
                    OnSendCompleted(true); 
                } 
            } 
            catch 
            { 
                _socket.Dispose();     
                _socket = null;     
                OnSendCompleted(false);     
            }     
        }     
    }     
}
</pre></p><p>As with the listener class, <strong>SocketClient</strong> supports <strong>OnConnectionCompleted</strong> to notify the application that the connection attempt completed.</p><p>Back in <strong>App.xaml.cs</strong>, the data from the incoming connection captured by the <strong>TcpSocketListener</strong> instance is passed to the <strong>ResponseHelper</strong> class:</p><p><pre class="brush: csharp">
void listener_OnClientConnected(object sender, ConnectionEventArgs e) 
{ 
    ResponseHelper.HandleIncomingResponse(e.Token); 
}
</pre></p><p>This class reads the possible three commands sent by the server and interprets them, creating internal collections from the raw data if the current server IP matches the one obtained in the <strong>ServerResponse</strong> (the same model in the desktop application):</p><p><pre class="brush: csharp">
using Coding4Fun.MissionControl.WP.Models;
using Coding4Fun.MissionControl.WP.ViewModels;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Windows;

namespace Coding4Fun.MissionControl.WP.Misc
{
        public class ResponseHelper
        {
                public static void HandleIncomingResponse(string rawResponse)
                {
                        if (rawResponse != null)
                        {
                                ServerResponse response = JsonConvert.DeserializeObject&lt;ServerResponse&gt;(rawResponse);
                
                                if (response.Marker == Constants.COMMAND_SERVER_NOTIFICATION)
                                {
                                        Deployment.Current.Dispatcher.BeginInvoke(() =&gt;
                                        {
                                                MessageBox.Show(response.Content, &quot;Server Response&quot;, MessageBoxButton.OK);
                                        });
                                }
                                else
                                {
                                        if (CommonViewModel.Instance.IsWaiting)
                                        {
                                                if (response.Identifier == CommonViewModel.Instance.CurrentServer.Location)
                                                {
                                                        // returns the list of sets that are associated with the current server.
                                                        if (response.Marker == Constants.COMMAND_SERVER_SET_LIST)
                                                        {
                                
                                                                List&lt;string&gt; items = JsonConvert.DeserializeObject&lt;List&lt;string&gt;&gt;(response.Content);
                                
                                                                if (items != null)
                                                                {
                                                                        List&lt;Group&lt;string&gt;&gt; groupedItems = Group&lt;string&gt;.CreateGroups(items,
                                                                        CultureInfo.CurrentCulture, (string s) =&gt; { return s[0].ToString(); }, true);
                                                                        SetsPageViewModel.Instance.Sets = groupedItems;
                                                                }
                                                                else
                                                                {
                                                                        SetsPageViewModel.Instance.Sets = new List&lt;Group&lt;string&gt;&gt;();
                                                                }
                                
                                                                Deployment.Current.Dispatcher.BeginInvoke(() =&gt;
                                                                    {
                                                                            CommonViewModel.Instance.IsWaiting = false;
                                    
                                                                            if (!App.RootFrame.CurrentSource.ToString().Contains(&quot;SetsPage&quot;))
                                                                            {
                                                                                    App.RootFrame.Navigate(new Uri(&quot;/Views/SetsPage.xaml&quot;, UriKind.Relative));
                                                                            }
                                                                    });
                                
                                                        }
                                                        // returns the list of commands associated with a given set.
                                                        else if (response.Marker.Contains(Constants.COMMAND_SERVER_SET_COMMANDS))
                                                        {
                                                            string[] data = response.Marker.Split(new char[] { ':' });
                                                                if (data[1] == CommonViewModel.Instance.CurrentSet)
                                                                {
                                                                        bool isList = false;
                                                                        bool.TryParse(data[2].ToLower(), out isList);
                                    
                                                                        if (isList)
                                                                        {
                                                                                CommonViewModel.Instance.CurrentSetType = &quot;list&quot;;
                                                                        }
                                                                        else
                                                                        {
                                                                                CommonViewModel.Instance.CurrentSetType = &quot;pad&quot;;
                                                                        }
                                    
                                                                        CommandsPageViewModel.Instance.Commands = new System.Collections.ObjectModel.ObservableCollection&lt;string&gt;(JsonConvert.DeserializeObject&lt;List&lt;string&gt;&gt;(response.Content));
                                    
                                                                        Deployment.Current.Dispatcher.BeginInvoke(() =&gt;
                                                                            {
                                                                                    CommonViewModel.Instance.IsWaiting = false;
                                                                                    App.RootFrame.Navigate(new Uri(&quot;/Views/CommandsPage.xaml&quot;, UriKind.Relative));
                                                                            });
                                                                }
                                                        }
                                                }
                                        }
                                }
                        }
                }
        }
}
</pre></p><p>If the response comes from a server that is different than the one that is currently active, the data is discarded as the user no longer needs it. Also, for specific commands, the mobile application will be on standby, waiting for a response (unless the user decides to cancel the request) – the <strong>IsWaiting</strong> flag is an application-wide indicator that a pending server action is in the queue.</p><p>Same as with the server, the commands in the Windows Phone application are represented through pre-defined constants:</p><p><pre class="brush: csharp">
public const string COMMAND_SERVER_SET_LIST = &quot;SET_LIST&quot;; 

public const string COMMAND_SERVER_SET_COMMANDS = &quot;SET_COMMANDS&quot;; 

public const string COMMAND_SERVER_NOTIFICATION = &quot;NOTIFICATION&quot;;
</pre></p><p>Let’s now take a closer look at how it is handled internally to build the visual layer.</p><h4>Handling the Data</h4><p>The first thing users will see when the application is launched is the list of registered servers:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/wp_ss_20130507_0003%5B4%5D.png"><img title="wp_ss_20130507_0003" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/wp_ss_20130507_0003_thumb%5B2%5D.png" alt="wp_ss_20130507_0003" width="288" height="480" border="0"></a></p><p>This is <strong>ServiceListPage.xaml</strong>. The list of servers that were added is retrieved from the isolated storage on application startup, with the help of the standard serialization routine implemented in the <a href="https://coding4fun.codeplex.com/">Coding4Fun Toolkit</a>—specifically, its storage subset (you can get it <a href="http://nuget.org/packages/Coding4Fun.Toolkit.Storage/">via NuGet</a>):</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image0116.jpg"><img title="clip_image011" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image011_thumb3.jpg" alt="clip_image011" width="535" height="61" border="0"></a></p><p>The one-liner that initializes the internal server collection is as follows:</p><p><pre class="brush: csharp">
MainPageViewModel.Instance.Servers = Serialize.Open&lt;ObservableCollection&lt;Server&gt;&gt;(Constants.SERVERS_FILE);
</pre></p><p>&nbsp;</p><p>Here, the <strong>SERVERS_FILE</strong> constant is equal to <strong>servers.xml</strong>. It is a good idea to use constants for file names in order to be able to later modify the location through a single change instead of digging through the many source files in a solution to find references to the old location.</p><p>The user can define an unlimited number of servers, as long as he can access those. There is no restriction on the location of the server itself—it can work with the desktop in your room just as well as with a PC on the other end of the world (yes, this was tested).</p><p>When adding a new server, the user is redirected to <strong>AddServicePage.xaml</strong>, where he can fill in connection details, as well as the location of an image that would help him identify that specific item in the general list:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/wp_ss_20130423_0005%5B4%5D.png"><img title="wp_ss_20130423_0005" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/wp_ss_20130423_0005_thumb%5B2%5D.png" alt="wp_ss_20130423_0005" width="288" height="480" border="0"></a></p><p>Once data entry is complete, it is validated internally to make sure that the server is not already registered with the same name and location. If the validation step passes, the server is added to the list of local access points and the user is returned back to the server selection page:</p><p><pre class="brush: csharp">
private void AttemptAddService()
{
        if (!string.IsNullOrWhiteSpace(txtName.Text) &amp;&amp; !string.IsNullOrWhiteSpace(txtLocation.Text))
        {
                Server server = new Server
                    {
                            Name = txtName.Text,
                            Location = txtLocation.Text,
                            ImageURL = !string.IsNullOrWhiteSpace(txtAvatar.Text) ? txtAvatar.Text : string.Empty
                    };
        
                if (!CollectionHelper.CheckServerExists(server))
                {
                        MainPageViewModel.Instance.Servers.Add(server);
            
                        Serialize.Save(Constants.SERVERS_FILE, MainPageViewModel.Instance.Servers);
                        NavigationService.GoBack();
                }
                else
                {
                        Alert.Send(&quot;The service with this name or location is already registered.&quot;);
                }
        }
        else
        {
                Alert.Send(&quot;The service needs a name and a location.&quot;);
        }
}
</pre></p><p>When a server selection is made by the user, it is necessary to show <strong>SetsPage.xaml</strong>. However, it is necessary to also check whether the server is active or not prior to the actual navigation. With the help of internal bindings, I am doing it through a <strong>RelayCommand</strong>:</p><p><pre class="brush: csharp">
public RelayCommand SelectServerCommand { get; private set; }
private async void SelectServer(object server)
{
        CommonViewModel.Instance.IsWaiting = true;
        CommonViewModel.Instance.CurrentServer = (Server)server;
    
        bool result = await CommonViewModel.Instance.CommandClient.SendCommand(CommonViewModel.Instance.CurrentServer.Location, 
        Constants.COMMAND_SERVER_HELLO, string.Empty);
        if (!result)
        {
                Alert.Send(Constants.MESSAGE_SERVER_CONNECT_FAIL);
                CommonViewModel.Instance.CurrentServer = null;
        
                CommonViewModel.Instance.IsWaiting = false;
        }
}
</pre></p><p>&nbsp;</p><p><strong>COMMAND_SERVER_HELLO</strong> represents the initial handshake command that I mentioned earlier—it requests the list of sets on the target server. To streamline command processing, <strong>CommandClient</strong> is used and wraps around the <strong>SocketClient</strong> class, giving me the possibility to call <strong>SendCommand</strong> with the command metadata without having to explicitly handle socket interactions in my views:</p><p><pre class="brush: csharp">
namespace Coding4Fun.MissionControl.WP.Network 
{     
    public class CommandClient     
    {     
        private SocketClient client; 
        
        public Task&lt;bool&gt; SendCommand(string key, string value, Action&lt;bool&gt; onCompleted = null) 
        {     
            var taskCompletionSource = new TaskCompletionSource&lt;bool&gt;(); 
            
            client = new SocketClient();     
            client.OnClientConnected &#43;= (s, args) =&gt;     
            {     
                if (args.IsSuccessful)     
                {     
                    string data = JsonConvert.SerializeObject(new KeyValuePair&lt;string, string&gt;(key, value));     
                    client.Send(data);     
                } 
            
                taskCompletionSource.SetResult(args.IsSuccessful); 
                client = null; 
            }; 
            
            client.Connect(Binder.Instance.CurrentService.Location, 6169); 
            return taskCompletionSource.Task;     
        } 
    } 
}
</pre></p><p>From here on, <strong>ResponseHelper</strong> is once again involved, grouping all the data alphabetically—remember this call:</p><p><pre class="brush: csharp">
// returns the list of sets that are associated with the current server. 
if (response.Marker == Constants.COMMAND_SERVER_SET_LIST) 
{     
    List&lt;string&gt; items = JsonConvert.DeserializeObject&lt;List&lt;string&gt;&gt;(response.Content);     
    if (items != null) 
    {     
        List&lt;Group&lt;string&gt;&gt; groupedItems = Group&lt;string&gt;.CreateGroups(items,     
    CultureInfo.CurrentCulture, (string s) =&gt; { return s[0].ToString(); }, true);     
        Binder.Instance.Sets = groupedItems;     
    } 
    else 
    {     
        Binder.Instance.Sets = new List&lt;Group&lt;string&gt;&gt;();     
    } 
}
</pre></p><p>&nbsp;</p><p>The grouped collection is later bound to a <a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj244365(v=vs.105).aspx">LongListSelector</a> instance:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/wp_ss_20130507_0001%5B4%5D.png"><img title="wp_ss_20130507_0001" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/wp_ss_20130507_0001_thumb%5B2%5D.png" alt="wp_ss_20130507_0001" width="288" height="480" border="0"></a></p><p>For each handshake call to the server, the set collection will be re-initialized, in case the server was updated by another device while the user was not taking any actions.</p><p>Adding a set takes the user to <strong>AddSetPage.xaml</strong>, where the user input is once again validated and the appropriate command sent to the currently selected server:</p><p><pre class="brush: csharp">
private async void AttemptAddSet()
{
        if (!string.IsNullOrWhiteSpace(txtName.Text))
        {
                this.Focus();
        
                bool commandSent = await CommonViewModel.Instance.CommandClient.SendCommand(CommonViewModel.Instance.CurrentServer.Location, 
                    string.Format(Constants.COMMAND_CREATE_SET, ((ListPickerItem)lstType.SelectedItem).Content.ToString()), txtName.Text);
                if (!commandSent)
                {
                        Alert.Send(Constants.MESSAGE_SERVER_CONNECT_FAIL);
                }
                else
                {
                        CommonViewModel.Instance.IsWaiting = true;
                        NavigationService.GoBack();
                }
        }
        else
        {
                Alert.Send(Constants.MESSAGE_NO_NAME_FAIL);
        }
}
</pre></p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/wp_ss_20130430_0002%5B4%5D-1.png"><img title="wp_ss_20130430_0002" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/wp_ss_20130430_0002_thumb%5B2%5D-1.png" alt="wp_ss_20130430_0002" width="288" height="480" border="0"></a></p><p>The end-user is also able to specify whether the new set is a list or a pad. Since the server does not explicitly define the type of a set beyond marking whether it’s a list, it is possible to have an arbitrary type here.</p><p>To give you an idea of what it looks like in the current release of MissionControl, here is the pad representation of a set of commands:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/wp_ss_20130507_0002%5B13%5D.png"><img title="wp_ss_20130507_0002" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/wp_ss_20130507_0002_thumb%5B11%5D.png" alt="wp_ss_20130507_0002" width="288" height="480" border="0"></a></p><p>It is a convenient way to display buttons for typical actions, such as channel switching through digits. Since we can safely assume many of those will be tapped sequentially, a list would be inconvenient to scroll through.</p><p>On the other hand, some remote control commands work well with a list because no sequences are invoked most of the time:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/wp_ss_20130507_0004%5B4%5D.png"><img title="wp_ss_20130507_0004" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/wp_ss_20130507_0004_thumb%5B2%5D.png" alt="wp_ss_20130507_0004" width="288" height="480" border="0"></a></p><p>If the pad is not desired, it can easily be swapped with another design and internal template - the appearance is swapped dynamically and is not hard-bound to a string value.</p><p>Once a set is selected, a connection attempt is made to the current server in order to check whether there is still a communication channel available with the resource that fetched the initial list of commands. If a connection is established, the server will also return a set of commands that are available in the set at the time of the request.</p><p><pre class="brush: csharp">
private async void AttemptLoadCommands()
{
        bool commandSent = await CommonViewModel.Instance.CommandClient.SendCommand(CommonViewModel.Instance.CurrentServer.Location,
            Constants.COMMAND_GET_COMMANDS, CommonViewModel.Instance.CurrentSet);
        if (!commandSent)
        {
                Alert.Send(Constants.MESSAGE_SERVER_CONNECT_FAIL);
                CommonViewModel.Instance.IsWaiting = false;
        }
}
</pre></p><p>You’ve probably already noticed that both for commands and sets, the initial routine verifies the connection to the server. The server might go dark after the set list is loaded, therefore rendering any attempt to process other commands impossible. To avoid scenarios in which the user is waiting for a response from a server that doesn’t run, the user is notified before being redirected to the subsequent view, if the connection fails. That way unnecessary navigation passes are out of the picture.</p><p>If the user selects a command from one of the lists demonstrated above, an <strong>EXECUTE</strong> directive is issued via the <strong>CommandClient</strong> class:</p><p><pre class="brush: csharp">
private async void lstCommands_SelectionChanged(object sender, SelectionChangedEventArgs e) 
{ 
    if (lstCommands.SelectedItem != null)
    { 
        string selectedItem = lstCommands.SelectedItem.ToString(); 
        
        CommandClient commandClient = new CommandClient(); 
        bool commandSent = await commandClient.SendCommand(string.Format(Constants.COMMAND_EXECUTE, 
        
        Binder.Instance.CurrentSet), selectedItem); 
    
        if (!commandSent) 
        {     
            Alert.Send(Constants.MESSAGE_SERVER_CONNECT_FAIL);     
        } 
        
        lstCommands.SelectedItem = null; 
    } 
}
</pre></p><p>Once the server receives the command, it will send it to the target without additional notifications being released to the connecting client.</p><p>When it comes to learning a new remote control code in <strong>LearnCodePage.xaml</strong>, the procedure is exactly the same as with any other part of the server communication process — a <strong>LEARN_CODE</strong> command is sent to the server with the associated set and new command name, and the server will wait for incoming IR input, leaving the connecting device free (no waiting lock is issued):</p><p><pre class="brush: csharp">
private async void AttemptLearnCode()
{
        if (!string.IsNullOrWhiteSpace(txtName.Text))
        {
                CommonViewModel.Instance.IsWaiting = true;
                this.Focus();
        
                bool commandSent = await CommonViewModel.Instance.CommandClient.SendCommand(CommonViewModel.Instance.CurrentServer.Location,
                    string.Format(Constants.COMMAND_LEARN_NEW, CommonViewModel.Instance.CurrentSet), txtName.Text);
                if (!commandSent)
                {
                        Alert.Send(Constants.MESSAGE_SERVER_CONNECT_FAIL);
                }
                else
                {
                        Alert.Send(Constants.MESSAGE_COMMAND_LEARN_WAIT);
                        NavigationService.GoBack();
                }
        
                CommonViewModel.Instance.IsWaiting = false;
        }
        else
        {
                Alert.Send(Constants.MESSAGE_NO_NAME_FAIL);
        }
}
</pre></p><p>Once the server learns a new command — if, and only if, the user still works in the context of the same server — an alert will be displayed, telling the user whether the command was successfully learned.</p><p>For convenience purposes, I also implemented a quick launch panel, where frequently-used commands can be placed. Whenever a user wants to add something here, he will tap-and-hold on an existing command in any of the sets that are available for any given server, and select the &quot;add to quick launch&quot; option. Once completed, the stored commands will be available on the main page, even when the user is not directly connected to the server that carries the command:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/wp_ss_20130507_0005%5B4%5D.png"><img title="wp_ss_20130507_0005" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/wp_ss_20130507_0005_thumb%5B2%5D.png" alt="wp_ss_20130507_0005" width="288" height="480" border="0"></a></p><p>Because this interaction layer is placed outside the boundaries of a single server or set, I needed to create a special data model to store the quick commands and the related connection information, that would let me call the server even when it is not the currently selected one:</p><p><pre class="brush: csharp">
namespace Coding4Fun.MissionControl.WP.Models
{
        public class Favorite
        {
            public string CommandName { get; set; }
            public string ParentSet { get; set; }
            public string ServerLocation { get; set; }
        }
}
</pre></p><p>Same as with the list of servers, the list of favorites is deserialized on application startup:</p><p><pre class="brush: csharp">
MainPageViewModel.Instance.Favorites = Serialize.Open&lt;ObservableCollection&lt;Favorite&gt;&gt;(Constants.FAVORITES_FILE);
</pre></p><p>&nbsp;</p><p>Logically, we would also need to have a way to eliminate trailing commands for servers or sets that have been removed, since those can no longer be invoked or might have a different meaning on servers that were added and have the same IP as the previous owner. This is easily done with a simple LINQ expression that is passed to <strong>RemoveTrailingFavorites </strong>in the <strong>CollectionHelper </strong>class:</p><p><pre class="brush: csharp">
internal static void RemoveTrailingFavorites(Func&lt;Favorite,bool&gt; predicate)
{
        var favorites = MainPageViewModel.Instance.Favorites.Where(predicate).ToList();
    
        if (favorites.Count() &gt; 0)
        {
                foreach (var favorite in favorites)
                {
                        Deployment.Current.Dispatcher.BeginInvoke(() =&gt;
                            {
                                    MainPageViewModel.Instance.Favorites.Remove(favorite);
                            });
                }
        
                Serialize.Save(Constants.FAVORITES_FILE, MainPageViewModel.Instance.Favorites);
        }
}
</pre></p><p>A typical usage scenario is reflected in the server removal snippet:</p><p><pre class="brush: csharp">
public static bool RemoveServer(Server server)
{
        try
        {
                RemoveTrailingFavorites(x=&gt; x.ServerLocation == server.Location);
        
                MainPageViewModel.Instance.Servers.Remove(server);
        
                Serialize.Save(Constants.SERVERS_FILE, MainPageViewModel.Instance.Servers);
        
                return true;
        }
        catch
        {
                return false;
        }
}
</pre></p><p>Because an <a href="http://msdn.microsoft.com/en-us/library/ms668604(v=vs.95).aspx" target="_blank">ObservableCollection&lt;T&gt;</a> is used for both the list of servers and quick launch commands, the view will be instantly updated to reflect the changes.</p><h1>Improvements to the project</h1><p>This specific project relies on a hybrid IR transmitter and receiver, which is not exactly cheap. As a step forward for this project, it can be adapted to use a central microcontroller that acts as a server (e.g. <a href="http://www.netduino.com/" target="_blank">Netduino</a>) and a series of IR emitters (instead of using a composite receiver/emitter) connected to it. Reduced cost for the IR infrastructure is key, as not every single component needs the capability to learn IR commands. You can have a single command capturing endpoint and multiple transmitters. This will also eliminate the need for a desktop client, since the server on the microcontroller can be built to be accessible via a web-browser.</p><p>Another important aspect not covered in this article is security. With the current workflow, anyone who has direct access to the server IP is able to do anything he wants with the data handled by the server. I am basing my writing on the assumption that you are testing the application on a secure local network and that the the odds of something like this happening are close to zero. However, for other environments where tampering with a server might be unacceptable, consider implementing a layer of security between the server and the client.</p><h2>Conclusion</h2><p>With affordable microcontrollers and sensors, home and office automation can be a nice bonus resulting from little investment. This article covers the implementation of a proof-of-concept server and application that can be easily extended and adapted to a variety of environments and devices.</p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/DennisDel/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:b029d939c55f459c9663a1b70159bff4">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/MissionControl-A-Flexible-API-for-Remote-Device-Control</comments>
      <itunes:summary>In a race to optimize everything, developers often go to extremes to build software that performs routine tasks. MissionControl is a system that allows users to program a control center that stores interfaces with attached hardware sensors, allowing the users to control any other devices that can be activated via the underlying protocol. For demo purposes, the MissionControl build at this point is compatible with the Phidgets IR hybrid sensor. The system has two core components: A server application, which is a Win32 console application that handles incoming queries and returns data to the connected clients. This application runs on the desktop machine with the connected sensor. The Windows Phone application that sends requests to the target server and can trigger a variety of pre-programmed commands. The BasicsHardware and Communication InfrastructureOne of the most important parts of the project is the signal capture and replication hardware. For the purposes of this project, I decided to use a dual-mode Phidgets IR sensor. It supports both IR code capture and subsequent replication. From a user’s perspective, this device also eliminates a substantial code-learning overhead as well as the potential error rate. Instead of searching for a device-specific hexadecimal sequence that later has to be transformed in a working IR code, the user simply has to point his remote control at the sensor and press the button that he wants accessible from a mobile device. Given that the capturing software is running on the target machine, once the sensor detects that a code can be repeated within an acceptable precision range, it will be automatically captured and stored, with all required transformations worked out in the backend using the free Phidgets SDK. Even though I can, I don’t have to handle the binary code content received through the sensor—the Phidgets .NET libraries carry built-in types that contain all the processed metadata that I will discuss later in this article. </itunes:summary>
      <itunes:duration>229</itunes:duration>
      <link>http://channel9.msdn.com/coding4fun/articles/MissionControl-A-Flexible-API-for-Remote-Device-Control</link>
      <pubDate>Mon, 13 May 2013 15:12:48 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/MissionControl-A-Flexible-API-for-Remote-Device-Control</guid>
      <media:thumbnail url="http://media.ch9.ms/ch9/330a/ce7e23b2-7e59-47e3-ba68-af17f8ab330a/MissionControl_100.jpg" height="56" width="100"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/330a/ce7e23b2-7e59-47e3-ba68-af17f8ab330a/MissionControl_220.jpg" height="123" width="220"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/330a/ce7e23b2-7e59-47e3-ba68-af17f8ab330a/MissionControl_512.jpg" height="288" width="512"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/330a/ce7e23b2-7e59-47e3-ba68-af17f8ab330a/MissionControl_960.jpg" height="540" width="960"></media:thumbnail>
      <media:group>
        <media:content url="http://media.ch9.ms/ch9/330a/ce7e23b2-7e59-47e3-ba68-af17f8ab330a/MissionControl.mp3" expression="full" duration="229" fileSize="3674107" type="audio/mp3" medium="audio"></media:content>
        <media:content url="http://media.ch9.ms/ch9/330a/ce7e23b2-7e59-47e3-ba68-af17f8ab330a/MissionControl.mp4" expression="full" duration="229" fileSize="22113376" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/330a/ce7e23b2-7e59-47e3-ba68-af17f8ab330a/MissionControl.webm" expression="full" duration="229" fileSize="16308048" type="video/webm" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/330a/ce7e23b2-7e59-47e3-ba68-af17f8ab330a/MissionControl.wma" expression="full" duration="229" fileSize="1867511" type="audio/x-ms-wma" medium="audio"></media:content>
        <media:content url="http://media.ch9.ms/ch9/330a/ce7e23b2-7e59-47e3-ba68-af17f8ab330a/MissionControl.wmv" expression="full" duration="229" fileSize="15574259" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/330a/ce7e23b2-7e59-47e3-ba68-af17f8ab330a/MissionControl_high.mp4" expression="full" duration="229" fileSize="48262843" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/330a/ce7e23b2-7e59-47e3-ba68-af17f8ab330a/MissionControl_mid.mp4" expression="full" duration="229" fileSize="33783291" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/330a/ce7e23b2-7e59-47e3-ba68-af17f8ab330a/MissionControl_Source.wmv" expression="full" duration="229" fileSize="135746099" type="video/x-ms-wmv" medium="video"></media:content>
      </media:group>      
      <enclosure url="http://media.ch9.ms/ch9/330a/ce7e23b2-7e59-47e3-ba68-af17f8ab330a/MissionControl.wmv" length="15574259" type="video/x-ms-wmv"></enclosure>
      <dc:creator>Clint Rutkas, Den Delimarsky</dc:creator>
      <itunes:author>Clint Rutkas, Den Delimarsky</itunes:author>
      <slash:comments>5</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/MissionControl-A-Flexible-API-for-Remote-Device-Control/RSS</wfw:commentRss>
      <category>Networking</category>
      <category>Windows</category>
      <category>Windows  Phone</category>
    </item>
  <item>
      <title>Dynamic Lockscreen Changer for Windows Phone 8, Built With ASP.NET MVC and Azure Mobile Services</title>
      <description><![CDATA[<p>With the release of Windows Phone 8, <a href="http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj206968%28v=vs.105%29.aspx">a few new developer API</a> endpoints were made available that allow third-party applications to change the device lockscreen image. In this article, I am establishing the infrastructure and building a mobile application that provides the ability to choose from a number of dynamic image sets, from which images can be selected and then cycled as lockscreen wallpapers.</p><h1>What do you need</h1><p>You will need to download and install <a href="http://www.asp.net/mvc/mvc3">ASP.NET MVC3</a> to work on the web frontend and <a href="http://dev.windowsphone.com/en-us/downloadsdk">Windows Phone 8 SDK</a> to work on the mobile applications. An <a href="http://www.windowsazure.com/en-us/develop/mobile/">Azure Mobile Services</a> account will be necessary, and of course don’t forget to download and install the <a href="http://www.windowsazure.com/en-us/develop/mobile/developer-tools/">Azure Mobile Services client libraries</a>. All three components are available at no additional charge.</p><p><strong>NOTE:</strong> <em>Without the Azure Mobile Services SDK installed on the development machine, the compilation process will fail for the Windows Phone application.</em></p><h1>Setting up The Data Store</h1><p>First we need to establish the general design of the application and organize the workflow. The application will provide two ways to assign the dynamic lockscreen:</p><ul><li>With the help of custom image sets that are provided by the service; </li><li>With the help of self-created image sets, aggregated from images provided by the service but ultimately managed by the end-user. </li></ul><p>Let’s talk about the general data model. Every image belongs to a certain category and to keep track of each we need a table with two columns—category ID and category name. We also need another core table containing the image references themselves, with the following columns: image URL, descriptive name, and the category ID to which it belongs. The overall structure looks like this:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image001%5B7%5D.png"><img title="clip_image001" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image001_thumb%5B4%5D.png" alt="clip_image001" width="321" height="141" border="0"></a></p><p>Now to the Windows Azure Management Portal and creating a new Mobile Service.</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image003%5B5%5D.jpg"><img title="clip_image003" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image003_thumb%5B2%5D.jpg" alt="clip_image003" width="560" height="387" border="0"></a></p><p>Once created, you need to specify database information, just like you would with a standard SQL Server database:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image005%5B6%5D.jpg"><img title="clip_image005" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image005_thumb%5B3%5D.jpg" alt="clip_image005" width="564" height="368" border="0"></a></p><p>As the database is being created, you can easily integrate it with SQL Server Management Studio. You will need the server address, which may be obtained in the Azure Management Portal. To login, use the credentials that you set when creating the core database.</p><p>Create the two tables mentioned above, with the following column configuration:</p><p><strong>Categories</strong></p><ul><li>ID - <strong>int</strong> </li><li>Name – <strong>varchar(100)</strong> </li></ul><p><strong>Images</strong></p><ul><li>ID – <strong>int</strong> </li><li>URL – <strong>varchar(500)</strong> </li><li>Name – <strong>varchar(100)</strong> </li><li>CategoryID – <strong>int</strong> </li></ul><p>You can create these tables either in the SQL Server Management Studio or through the Azure Management Portal. However, you will need the Management Studio to create the column structure, as the Azure Management Portal does not offer this functionality right now.</p><p>By default, the <strong>id</strong> column will be created automatically. To add the Name column to the Categories table, run this query:</p><p><pre class="brush: sql">
ALTER TABLE c4flockscreen.Categories
ADD Name VARCHAR(100)
</pre></p><p>To add the missing columns to the Images table, simply execute this query:</p><p><pre class="brush: sql">
ALTER TABLE c4flockscreen.Images
ADD URL VARCHAR(500),
Name VARCHAR(100),
CategoryID INT
</pre></p><p>Now that the database is ready, we’ll proceed to working on the web layer, which will effectively be the administrative portal for the service.</p><h1>Creating the Web Portal</h1><p>There should be a way to easily manage images and constantly expand the collection of possible lockscreen wallpapers. One way to do this is create a basic management portal that can carry basic CRUD operations.</p><p>Start by creating an empty project:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image007%5B5%5D.jpg"><img title="clip_image007" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image007_thumb%5B2%5D.jpg" alt="clip_image007" width="321" height="291" border="0"></a></p><p>If you are not yet aware of the Model-View-Controller (MVC) development pattern, <a href="http://msdn.microsoft.com/en-us/library/ff649643.aspx">here is a good read</a> explaining the fundamentals.</p><p>Create a new controller in the <strong>Controllers</strong> folder, named <strong>HomeController</strong>. This will be the only controller created in this project. For now, add an <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.actionresult%28v=vs.108%29.aspx">ActionResult</a>-based function that will return the main view:</p><p><pre class="brush: csharp">
using System.Web.Mvc;

namespace Coding4Fun.Lockscreen.Web.Controllers
{
    public class HomeController : Controller    
    {    
        public ActionResult MainView()    
        {    
            return View();    
        }
    }
}
</pre></p><p>Having the controller without the proper views is pointless, so create a new view in <strong>Views/Home</strong> and name it <strong>MainView</strong>. For now, do not focus on the visual layout of the page, but rather on the functional aspect of the web frontend. If you run the application now, you will most likely get a 404 response. That is because the associated home view is by default not found. Open <strong>App_Start/RouteConfig.cs</strong> and make sure that the default view is set to <strong>MainView</strong> instead of <strong>Index</strong>.</p><p><pre class="brush: csharp">
routes.MapRoute(
name: &quot;Default&quot;,
url: &quot;{controller}/{action}/{id}&quot;,
defaults: new { controller = &quot;Home&quot;, action = &quot;MainView&quot;, id = UrlParameter.Optional }
);
</pre></p><p>The core is created and now if running the web application you will see a basic HTML page:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image009%5B5%5D.jpg"><img title="clip_image009" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image009_thumb%5B2%5D.jpg" alt="clip_image009" width="508" height="345" border="0"></a></p><p>We now need to handle data from the Azure Mobile Services database. Out-of-the-box, there is no ASP.NET SDK available, but the database can be easily <a href="http://msdn.microsoft.com/en-us/library/windowsazure/jj710108.aspx">accessed through a REST API</a>. But before that, we need to define the data models for the Categories and Images table. Begin by creating two classes in the Models folder:</p><p><strong>Category.cs:</strong></p><p><pre class="brush: csharp">
public class Category
{
public int? id { get; set; }
public string Name { get; set; }
}
</pre></p><p><strong>Image.cs:</strong></p><p><pre class="brush: csharp">
public class Image
{
public int? id { get; set; }    
public string URL { get; set; }
public string Name { get; set; }
public int CategoryID { get; set; }
}
</pre></p><p>Each of the properties is tied to the associated column in the database we created earlier. Notice that the ID values are nullable. This is introduced because the index will by default be automatically assigned. When new instances of Category or Image are created, I will not explicitly set the <strong>id</strong> property, so keeping it null instead of at a potential default value of 0 will ensure that it is properly set on the backend.</p><p>Let’s now create the connectivity engine that will allow us to query the content of the data store. For this purpose, I created a <strong>DataStore</strong> folder and a <strong>DataEngine</strong> class inside it. We will need a unique API key for each of our requests, so open the Azure Management Portal and obtain it from there:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image010%5B5%5D.png"><img title="clip_image010" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image010_thumb%5B2%5D.png" alt="clip_image010" width="749" height="333" border="0"></a></p><p>In order to keep consistency between projects, and to be able to re-use the same Azure Mobile Services API key and core URL, I created an <strong>AuthConstants</strong> class in the context of the <strong>Coding4Fun.Lockscreen.Core</strong> project. It carries three static fields:</p><p><pre class="brush: csharp">
public static class AuthConstants
{
    public static string AmsApiKey = &quot;YOUR_KEY_HERE&quot;;    
    public const string AmsUrl = &quot;https://c4flockscreen.azure-mobile.net/&quot;;
    public const string AmsTableUrl = AmsUrl &#43; &quot;tables/&quot;;
}
</pre></p><p>Back in the ASP.NET project, the query operations are carried with the help of <a href="http://msdn.microsoft.com/en-us/library/system.net.http.httpclient.aspx">HttpClient</a> initialized in the class constructor, which also includes the key used to authenticate the requests via the X-ZUMO-APPLICATION header:</p><p><pre class="brush: csharp">
private HttpClient client;

public DataEngine()
{    
    client = new HttpClient();    
    client.DefaultRequestHeaders.Add(&quot;X-ZUMO-APPLICATION&quot;, KEY);
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(&quot;application/json&quot;));    
}
</pre></p><p>This is the basic data harness. I also implemented two core methods in order to get all existing categories:</p><p><pre class="brush: csharp">
public IEnumerable&lt;Category&gt; GetAllCategories()
{
    var result = client.GetStringAsync(string.Concat(CORE_URL,&quot;Categories&quot;)).Result;
    IEnumerable&lt;Category&gt; categories = JsonConvert.DeserializeObject&lt;IEnumerable&lt;Category&gt;&gt;(result);
    return categories;    
}
</pre></p><p>And images:</p><p><pre class="brush: csharp">
public IEnumerable&lt;Image&gt; GetAllImages()
{
    var result = client.GetStringAsync(string.Concat(CORE_URL, &quot;Images&quot;)).Result;
    IEnumerable&lt;Image&gt; images = JsonConvert.DeserializeObject&lt;IEnumerable&lt;Image&gt;&gt;(result);
    return images;    
}
</pre></p><p>For each of these, a basic request is made with the table name appended to the base URL (represented by the <strong>CORE_URL</strong> constant). Since <a href="http://www.hanselman.com/blog/VisualStudio2012RCIsReleasedTheBigWebRollup.aspx">JSON.NET is now bundled with ASP.NET</a>, I am able to easily deserialize the returned JSON data array to an <strong>IEnumerable&lt;Type&gt;</strong>. There is one problem, however, with the <strong>GetAllImages</strong> approach. It implies that even if I want to use LINQ to query the existing image collection, I have to first download the entire set locally.</p><p>Fortunately, the Azure Mobile Services REST API provides an endpoint with filtering, and that’s what I am using in <strong>GetCategoryById</strong> and <strong>GetImagesByCategoryId</strong>:</p><p><pre class="brush: csharp">
public Category GetCategoryById(int id)
{    
    string composite = string.Concat(CORE_URL, &quot;Categories?$filter=(id%20eq%20&quot;, id.ToString(), &quot;)&quot;);    
    var result = client.GetStringAsync(composite).Result;
    IEnumerable&lt;Category&gt; categories = JsonConvert.DeserializeObject&lt;IEnumerable&lt;Category&gt;&gt;(result);
    return categories.FirstOrDefault();
}

public IEnumerable&lt;Image&gt; GetImagesByCategoryId(int id)
{    
    string composite = string.Concat(CORE_URL, &quot;Images?$filter=(CategoryID%20eq%20&quot;, id.ToString(), &quot;)&quot;);    
    var result = client.GetStringAsync(composite).Result;
    IEnumerable&lt;Image&gt; images = JsonConvert.DeserializeObject&lt;IEnumerable&lt;Image&gt;&gt;(result);
    return images();
}
</pre></p><p>Notice the <strong>?$filter=</strong> parameter, in which the conditional is URL encoded and is wrapped in parentheses. For the category query, I am checking the <strong>id </strong>value, and for the image I’m checking <strong>CategoryID</strong>.</p><p>In the <strong>Views/Home</strong> folder, create a new view and name it Images. It will be used to list existing images that are associated with one of the selected categories. You also need to adjust the controller code to handle the incoming data:</p><p><pre class="brush: csharp">
using Coding4Fun.Lockscreen.Web.DataStore;
using System.Web.Mvc;

namespace Coding4Fun.Lockscreen.Web.Controllers
{    
    public class HomeController : Controller    
    {    
        DataEngine engine;    
        public HomeController()
        {    
            engine = new DataEngine();    
        }
        
        public ActionResult MainView()
        {    
            var categories = engine.GetAllCategories();    
            return View(categories);
        }
        
        public ActionResult Images(int categoryId)
        {    
            var images = engine.GetImagesByCategoryId(categoryId);    
            if (images != null)
            {    
                return View(images);    
            }
            
            return View(&quot;MainView&quot;);
        }
    }
}
</pre></p><p>For the main view, I am getting the list of categories and passing them as the bound model. For the Images view, the category ID is passed as an argument that will later enable the engine to return a list of all images that have <strong>CategoryID</strong> set to that value. In case the returned list is not null, the view is shown. Otherwise, the main view is the terminal point.</p><p>In its current state, I’ll be able to use the frontend to list existing categories and images, but not to add, remove, or update items. Adding a category and an image is a matter of modifying an <strong>HttpClient</strong> request, with the help of <a href="http://msdn.microsoft.com/en-us/library/system.net.http.httprequestmessage.aspx">HttpRequestMessage</a>. For example, here is how I can add a category through my DataEngine class:</p><p><pre class="brush: csharp">
public HttpStatusCode AddCategory(Category category)
{    
    var serializedObject = JsonConvert.SerializeObject(category, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore });
    var request = new HttpRequestMessage(HttpMethod.Post, string.Concat(CORE_URL, &quot;Categories&quot;));
    request.Content = new StringContent(serializedObject, Encoding.UTF8, &quot;application/json&quot;);
    var response = client.SendAsync(request).Result;
    return response.StatusCode;
}
</pre></p><p>JSON.NET capabilities are used to serialize the object that needs to be inserted. The POST request is executed against the standard table URL, with the UTF8 encoded JSON string. Since the client is already carrying the basic authentication header, all that needs to be done is calling the <a href="http://msdn.microsoft.com/en-us/library/hh138176.aspx">SendAsync</a> function.</p><p>Updating a category follows the same approach, though a <a href="http://tools.ietf.org/html/rfc5789">PATCH method</a> is used for the request and the URL contains the index of the category that needs to be updated:</p><p><pre class="brush: csharp">
public HttpStatusCode UpdateCategory(Category category)
{    
    var request = new HttpRequestMessage(new HttpMethod(&quot;PATCH&quot;), string.Concat(CORE_URL, &quot;Categories&quot;, &quot;/&quot;, category.id));    
    var serializedObject = JsonConvert.SerializeObject(category);
    request.Content = new StringContent(serializedObject, Encoding.UTF8, &quot;application/json&quot;);
    var response = client.SendAsync(request).Result;
    return response.StatusCode;
}
</pre></p><p>To delete a category from the data store, one simply needs to pass a parameter to it that identifies the index of the category that needs to be removed:</p><p><pre class="brush: csharp">
public HttpStatusCode DeleteCategoryFromId(int categoryId)
{    
    var request = new HttpRequestMessage(HttpMethod.Delete, string.Concat(CORE_URL, &quot;Categories&quot;, &quot;/&quot;, categoryId));    
    var response = client.SendAsync(request).Result;
    return response.StatusCode;
}
</pre></p><p>For images, the same methods can be used, with the <strong>Images</strong> table passed as the name for the target in the composite URL. Let’s now get back to working on some of the views. A static category list is not fun, so let’s create a way to add new categories. Right click on the <strong>Views/Home</strong> folder and select <strong>Add View</strong>:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image012%5B5%5D-1.jpg"><img title="clip_image012" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image012_thumb%5B2%5D-1.jpg" alt="clip_image012" width="342" height="338" border="0"></a></p><p>A great thing about the view creation process in Visual Studio is the fact that you are able to use a basic scaffold template for a strongly-typed view. In this case, I am associating it with a <strong>Category</strong> class and using the <strong>Create</strong> template. I now need to modify the controller code to process requests to AddCategory. I need to handle two types of requests, GET and POST, because the view will be displayed to both add an item and submit an item:</p><p><pre class="brush: csharp">
public ActionResult AddCategory()
{    
    return View();    
}

[HttpPost]
public ActionResult AddCategory(Category category)
{    
    if (ModelState.IsValid)    
    {    
        engine.AddCategory(category);    
        return RedirectToAction(&quot;MainView&quot;);    
    }
    
    return View();
}
</pre></p><p>For a GET request, I am simply returning the view. For a POST view, I am adding the category that was defined by the bound model through the local <strong>DataEngine</strong> instance, after which the user is redirected to the main view. But we also need to add an ActionResult for the MainView to obtain the list of items that are currently in the Categories table:</p><p><pre class="brush: csharp">
public ActionResult MainView()
{    
    var categories = engine.GetAllCategories();    
    return View(categories);
}
</pre></p><p>The <strong>DataEngine</strong> instance will return all categories in an <strong>IEnumerable&lt;Category&gt;</strong> form that are passed as the model for the main view. The layout of MainView.cshtml can be as simple as a table:</p><p><pre class="brush: csharp">
@{    
    ViewBag.Title = &quot;Coding4Fun Dynamic Lockscreen&quot;;    
}

&lt;h2&gt;Coding4Fun Dynamic Lockscreen - Categories&lt;/h2&gt;

&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;b&gt;ID&lt;/b&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;b&gt;Category Name&lt;/b&gt;
&lt;/td&gt;
&lt;/tr&gt;

@foreach (var p in Model)
{    
    &lt;tr&gt;    
    &lt;td&gt;
    @p.id
    &lt;/td&gt;
    &lt;td&gt;
    @p.Name
    &lt;/td&gt;
    &lt;td&gt;
@Html.ActionLink(&quot;Images&quot;, &quot;Images&quot;, new { categoryId = p.id })
    &lt;/td&gt;
    &lt;td&gt;
@Html.ActionLink(&quot;Edit&quot;, &quot;EditCategory&quot;, new { categoryId = p.id })
    &lt;/td&gt;
    &lt;td&gt;
@Html.ActionLink(&quot;Delete&quot;, &quot;DeleteCategory&quot;, new { categoryId = p.id })
    &lt;/td&gt;
    &lt;/tr&gt;
}

&lt;/table&gt;

@Html.ActionLink(&quot;Add Category&quot;, &quot;AddCategory&quot;)
</pre></p><p>The <strong>ActionLink</strong> helper allows me to invoke a view and, if necessary, pass specific parameters to it (e.g., when I need to identify the category that needs to be deleted or edited). Some of the views listed here are not yet created, but I can easily use placeholder names in any case.</p><p>The ultimate result for the main page will look like this:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image013%5B5%5D.png"><img title="clip_image013" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image013_thumb%5B2%5D.png" alt="clip_image013" width="610" height="400" border="0"></a></p><p>Notice that you are also able to add new categories now by clicking on the Add Category link on the bottom. This will redirect you to the <strong>AddCategory</strong> view that we created:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image014%5B5%5D.png"><img title="clip_image014" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image014_thumb%5B2%5D.png" alt="clip_image014" width="610" height="400" border="0"></a></p><p>Let’s see how to implement the category editing in the web frontend. First of all, create a new view in <strong>Views/Home</strong> and name it <strong>EditCategory</strong>. Use the <strong>Edit</strong> scaffold template. Like <strong>AddCategory</strong>, <strong>EditCategory</strong> needs to be handled in two separate ways for GET and POST requests in the controller:</p><p><pre class="brush: csharp">
public ActionResult EditCategory(int categoryId)
{    
    Category category;    
    category = engine.GetCategoryById(categoryId);
    if (category != null)
       return View(category);
    return View(&quot;MainView&quot;);
}

[HttpPost]
public ActionResult EditCategory(Category category)
{    
    if (ModelState.IsValid)    
    {    
        engine.UpdateCategory(category);    
        return RedirectToAction(&quot;MainView&quot;);
    }
    
    return View();
}
</pre></p><p>For a <strong>GET</strong> request, we need to identify the category that needs to be added by its index, so we are using a <strong>categoryId</strong> argument passed to the view, which is later used by the <strong>DataEngine</strong> instance to retrieve the category from the data store. For a POST action, the implementation for <strong>UpdateCategory</strong> from above is used, where a PATCH request is run with the serialized object bound to the view.</p><p>For the Delete action, no additional view is necessary but the controller still needs a handler, so we can use a snippet like this:</p><p><pre class="brush: csharp">
public ActionResult DeleteCategory(int categoryId)
{    
    engine.DeleteCategoryFromId(categoryId);    
    return RedirectToAction(&quot;MainView&quot;);
}
</pre></p><p>You can use the same approach to add, delete, and edit items in the list of images. For adding images, however, you might want to pass the category identifier. When images are listed after the category has been selected, it is necessary to provide a way to identify the category to which new entities should be added. To do this, we can. in the main controller. pass the category index to the view when the Images action is being triggered:</p><p><pre class="brush: csharp">
public ActionResult Images(int categoryId)
{    
    var images = engine.GetImagesByCategoryId(categoryId);    
    if (images != null)
    {    
        ViewData[&quot;CID&quot;] = categoryId;    
        return View(images);
    }
    
    return View(&quot;MainView&quot;);
}
</pre></p><p>Afterwards, the <strong>categoryId</strong> value can be obtained by using the <strong>CID</strong> key for <strong>ViewData</strong> inside the view itself.</p><h4>Let’s now take a look at how images are represented for each category. I created a custom view to list all the images associated with the Images category. If you look above at the controller code, you will notice that I am passing the category ID, through which the image set query is executed, and the returned collection is set as the bound model:</h4><p><pre class="brush: csharp">
public ActionResult Images(int categoryId)
{    
    var images = engine.GetImagesByCategoryId(categoryId);    
    if (images != null)
    {    
        ViewData[&quot;CID&quot;] = categoryId;    
        return View(images);
    }
    
    return View(&quot;MainView&quot;);
}
</pre></p><p>When an image needs to be added, call the <strong>AddImage</strong> view. In <strong>HomeController.cs</strong>, it carries implementations for both GET and POST requests:</p><p><pre class="brush: csharp">
public ActionResult AddImage(int categoryId)
{    
    Image image = new Image();    
    image.CategoryID = categoryId;
    return View(image);    
}

[HttpPost]
public ActionResult AddImage(HttpPostedFileBase file, Image image)
{    
    if (file != null &amp;&amp; file.ContentLength &gt; 0)    
    {    
        var fileName = Path.GetFileName(file.FileName);    
        var path = Path.Combine(Server.MapPath(&quot;~/Uploads&quot;), image.CategoryID.ToString(), fileName);
        string dirPath = Path.GetDirectoryName(path);
        
        if (!Directory.Exists(dirPath))
            Directory.CreateDirectory(dirPath);
        
        file.SaveAs(path);

        string applicationUrl = string.Format(&quot;{0}://{1}{2}&quot;,        
            HttpContext.Request.Url.Scheme,
            HttpContext.Request.ServerVariables[&quot;HTTP_HOST&quot;],
            (HttpContext.Request.ApplicationPath.Equals(&quot;/&quot;)) ? string.Empty : HttpContext.Request.ApplicationPath
        );
        
        image.URL = Path.Combine(applicationUrl, &quot;Uploads&quot;, image.CategoryID.ToString(), fileName);
    }
    
    if (ModelState.IsValid &amp;&amp; image.URL != null)
    {    
        engine.AddImage(image);    
        return RedirectToAction(&quot;Images&quot;, new { categoryID = image.CategoryID });
    }
    
    return View();
}
</pre></p><p>When a GET request is executed against the <strong>AddImage</strong> endpoint, I pass the category ID as the flag, signaling which category the image should be included in. When a POST request is executed, it can go two ways—either the user is passing an existing link to a hosted image or the user is uploading his own image to the local server. When an upload is inbound, <a href="http://msdn.microsoft.com/en-us/library/system.web.httppostedfilebase.aspx">HttpPostedFileBase</a> carries the content that needs to be pushed to the server.</p><p>The upload component on the view itself is done by creating a form with a file input:</p><p><pre class="brush: csharp">
&lt;h2&gt;Or you could upload your own file: &lt;/h2&gt;

@if (Model != null)
{    
    using (Html.BeginForm(&quot;AddImage&quot;, &quot;Home&quot;, FormMethod.Post, new { enctype = &quot;multipart/form-data&quot;, image = Model }))
    {    
        @Html.HiddenFor(model =&gt; model.CategoryID);    
        &lt;input type=&quot;file&quot; name=&quot;file&quot; /&gt;
        &lt;input type=&quot;submit&quot; value=&quot;OK&quot; /&gt;
    }
}
</pre></p><p>If there is no file selected, the system assumes that the user just decided to add an existing URL.</p><p>It’s important to mention that the upload workflow relies on the availability of the Upload folder. It is created by default when the project is deployed to the server, but you also need to make sure that the ASP.NET user on the machine where IIS is located has the appropriate write permission for the folder.</p><h1>The Windows Phone 8 Application Foundation</h1><p>Create a new Windows Phone 8 application and add a reference to <a href="http://weblogs.asp.net/scottgu/archive/2012/08/28/announcing-windows-azure-mobile-services.aspx">Windows Azure Mobile Services Managed Client</a>. It should be available in the Extensions section if you installed the Windows Azure Mobile Services SDK as I mentioned at the beginning of the article:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image016%5B5%5D.jpg"><img title="clip_image016" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image016_thumb%5B2%5D.jpg" alt="clip_image016" width="516" height="355" border="0"></a></p><p>In <strong>App.xaml.cs</strong> you need to create an instance of <a href="http://msdn.microsoft.com/en-us/library/windowsazure/microsoft.windowsazure.mobileservices.mobileserviceclient.aspx">MobileServiceClient</a> that will be used as the central connection point to the database. Notice that I am using the predefined AMS and API KEY string constants:</p><p><pre class="brush: csharp">
public static MobileServiceClient MobileService =
new MobileServiceClient(AuthConstants.AmsUrl, AuthConstants.AmsApiKey);
</pre></p><p>The mobile application should also carry the data models for both the categories and images. That said, we can reorganize those a bit for a more convenient data binding layout. To ensure that we can reuse the classes from different application components, I am once again using the <strong>Coding4Fun.Lockscreen.Core</strong> project.</p><p>Create a new folder called <strong>Models</strong> and add a new class called <strong>Category</strong>:</p><p><pre class="brush: csharp">
using System.Collections.ObjectModel;

namespace Coding4Fun.Lockscreen.Core.Models
{    
    public class Category    
    {    
        public Category()    
        {    
            Images = new ObservableCollection&lt;Image&gt;();    
        }
    
        public int? id { get; set; }    
        public string Name { get; set; }

        public ObservableCollection&lt;Image&gt; Images { get; set; }
        
        public override string ToString()        
        {    
            return Name;    
        }
    }
}
</pre></p><p>We are still relying on a <a href="http://msdn.microsoft.com/en-us/library/1t3y8s4s%28v=vs.80%29.aspx">nullable index value</a>, but now there is an <a href="http://msdn.microsoft.com/en-us/library/ms668604%28v=vs.95%29.aspx">ObservableCollection</a> for images. The reason for using this specific collection type is because with an <strong>ObservableCollection</strong>, binding updates are performed automatically when new items are added or removed, therefore cutting the need to implement the notification mechanism.</p><p>The ToString function is overridden to simplify data extraction on binding. When a collection with categories will be hooked to a list, for example, I don’t have to create a converter or a property link.</p><p>For the <strong>Image</strong> model, create a new class called <strong>Image</strong> in the same <strong>Models</strong> folder:</p><p><pre class="brush: csharp">
namespace Coding4Fun.Lockscreen.Core.Models
{    
    public class Image    
    {    
        public int? id { get; set; }
        public string URL { get; set; }
        public string Name { get; set; }
        public int CategoryID { get; set; }    
    }
}
</pre></p><h1>Application Workflow &amp; Storage</h1><p>Let’s talk about how image categories will be handled in the application. On application startup, the database is queried for the available categories and each of them is listed on the home screen. If the user taps on one of the categories, the database is queried for the images that are associated with the category index.</p><p>However, the user should also be able to create his own custom categories that will only be available in-app. Those categories can carry images from multiple other categories, if necessary, with the default reference set to the internal storage.</p><p>Since we are working with local storage, let’s create a helper class called <strong>LocalStorageHelper</strong> in the <strong>Coding4Fun.Lockscreen.Core</strong> project in the <strong>Storage</strong> folder. This class will carry basic read and write functions, allowing us to store data internally:</p><p><pre class="brush: csharp">
public static class LocalStorageHelper
{    
    public async static void WriteData(string folderName, string fileName, byte[] content)    
    {    
        IStorageFolder rootFolder = ApplicationData.Current.LocalFolder;
        
        if (folderName != string.Empty)    
        {    
            rootFolder = await rootFolder.CreateFolderAsync(folderName,    
            CreationCollisionOption.OpenIfExists);    
        }
        
        IStorageFile file = await rootFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
        using (var s = await file.OpenStreamForWriteAsync())
        {    
            s.Write(content, 0, content.Length);    
        }
    }
    
    public static async void ClearFolder(string folderName)
    {    
        var folder = await ApplicationData.Current.LocalFolder.GetFolderAsync(folderName);    
        if (folder != null)
        {    
            foreach (IStorageFile file in await folder.GetFilesAsync())    
            {    
                await file.DeleteAsync();    
            }
        }
    }
    
    public static async Task&lt;string&gt; ReadData(string fileName)
    {    
        byte[] data;    
        StorageFolder folder = ApplicationData.Current.LocalFolder;
        StorageFile file = await folder.GetFileAsync(fileName);
        using (Stream s = await file.OpenStreamForReadAsync())
        {        
            data = new byte[s.Length];    
            await s.ReadAsync(data, 0, (int)s.Length);
        }
        
        return Encoding.UTF8.GetString(data, 0, data.Length);
    }    
}
</pre></p><p>Notice that I am using the newly-introduced <a href="http://msdn.microsoft.com/library/windows/apps/BR227230">StorageFolder</a>/<a href="http://msdn.microsoft.com/en-us/library/windows/apps/windows.storage.storagefile.aspx">StorageFile</a> capabilities. If you worked with Windows Store application development, you are probably already familiar with them. <strong>Application.Current.LocalFolder</strong> gives me direct access to the local directory. which can be modified from within the application itself. It works in a manner similar to <strong>IsolatedStorageFile</strong> in Windows Phone 7, but with more flexibility when it comes to creating new folders and files and well doing file sweeps.</p><p>As I mentioned above, there will be internal data stored as XML. For this purpose, I need a class that carries serialization and deserialization routines, and I can simplify this task by using the <a href="http://coding4fun.codeplex.com/">Coding4Fun Toolkit</a> <strong>Serialize.Save&lt;T&gt;</strong> and <strong>Serialize.Open&lt;T&gt;</strong> capabilities. Calls to these functions allow flexible serialization, where by default the static class is not aware of the serialization type, but is instead able to dynamically infer it from the incoming data. Once the byte layout is obtained for the content, I use the <strong>LocalStorageHelper</strong> class to write it to a file.</p><p>As there are multiple UI items that need to be bound to collections and object instances, I have a <strong>CentralBindingPoint</strong> class in my main project that is my main view model (it implements <a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged%28v=vs.95%29.aspx">INotifyPropertyChanged</a>). It implements the singleton pattern, so that the main instance is created on initialization and is subsequently re-used as necessary:</p><p><pre class="brush: csharp">
using Coding4Fun.Lockscreen.Core.Models;
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace Coding4Fun.Lockscreen.Mobile
{    
    public class CentralBindingPoint : INotifyPropertyChanged    
    {    
        static CentralBindingPoint instance = null;    
        static readonly object padlock = new object();
        
        public CentralBindingPoint()
        {    
            Categories = new ObservableCollection&lt;Category&gt;();    
            CustomCategories = new ObservableCollection&lt;Category&gt;();    
        }
        
        public static CentralBindingPoint Instance
        {    
            get    
            {    
                lock (padlock)    
                {    
                    if (instance == null)    
                    {    
                        instance = new CentralBindingPoint();    
                    }
                
                    return instance;        
                }
            }
        }
        
        private ObservableCollection&lt;Category&gt; _categories;
        public ObservableCollection&lt;Category&gt; Categories
        {    
            get    
            {    
                return _categories;    
            }
            set
            {    
                if (_categories != value)        
                {    
                    _categories = value;    
                    NotifyPropertyChanged(&quot;Categories&quot;);
                }
            }
        }
        
        private ObservableCollection&lt;Category&gt; _customCategories;
        public ObservableCollection&lt;Category&gt; CustomCategories
        {    
            get    
            {    
                return _customCategories;    
            }
            set
            {    
                if (_customCategories != value)    
                {    
                    _customCategories = value;    
                    NotifyPropertyChanged(&quot;CustomCategories&quot;);
                }        
            }
        }
    
        private Category _currentCategory;    
        public Category CurrentCategory
        {    
            get    
            {        
                return _currentCategory;    
            }
            set
            {    
                if (_currentCategory != value)    
                {    
                    _currentCategory = value;    
                    NotifyPropertyChanged(&quot;CurrentCategory&quot;);
                }
            }
        }
        
        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(String info)
        {    
            if (PropertyChanged != null)    
            {    
                System.Windows.Deployment.Current.Dispatcher.BeginInvoke(    
                () =&gt;
                {    
                    PropertyChanged(this, new PropertyChangedEventArgs(info));    
                });
            }
        }
    }
}
</pre></p><p>On the main page, I create a <a href="http://msdn.microsoft.com/en-US/library/windowsphone/develop/microsoft.phone.controls.pivot%28v=vs.105%29.aspx">Pivot-based layout</a> to have an easy way to transition between the web collections (categories) and the local ones:</p><p><img src="http://www.codeplex.com/Download?ProjectName=lockscreen&amp;DownloadId=631917" alt="" width="288" height="480" border="0"></p><p>For each of the collection types, there is a <a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.listbox%28v=vs.95%29.aspx">ListBox</a> with a custom <a href="http://msdn.microsoft.com/en-us/library/system.windows.datatemplate%28v=VS.95%29.aspx">DataTemplate</a> assigned for each item. The items are obtained from the <strong>Categories</strong> collection for web sets and the <strong>CustomCategories</strong> collection for local sets, both in the <strong>CentralBindingPoint</strong> view model.</p><p>The categories are loaded with the help of the <strong>DataEngine</strong> class that I added in the Data folder in the main application project. It is a wrapper for the Azure Mobile Services data operations, allowing me to aggregate the list of categories and images, given that I know the category index:</p><p><pre class="brush: csharp">
public class DataEngine
{    
    async public Task&lt;List&lt;Category&gt;&gt; GetCategoryList()    
    {    
        IMobileServiceTable&lt;Category&gt; table = App.MobileService.GetTable&lt;Category&gt;();    
        List&lt;Category&gt; data = await table.ToListAsync();
        
        return data;
    }
    
    async public Task&lt;List&lt;Image&gt;&gt; GetImagesByCategoryId(int categoryId)
    {    
        IMobileServiceTable&lt;Image&gt; table = App.MobileService.GetTable&lt;Image&gt;();    
        List&lt;Image&gt; data = await table.Where(x =&gt; x.CategoryID == categoryId).ToListAsync();
        
        return data;
    }
}
</pre></p><p>When the main page loads, I use the local <strong>DataEngine</strong> instance to call <strong>GetCategoryList</strong> and obtain a List&lt;Category&gt; collection that is subsequently transformed into an <strong>ObservableCollection</strong> through one of the default constructors:</p><p><pre class="brush: csharp">
async void MainPage_Loaded(object sender, RoutedEventArgs e)
{    
    CentralBindingPoint.Instance.Categories = new ObservableCollection&lt;Category&gt;(await dataEngine.GetCategoryList());    
}
</pre></p><p>When a category is selected in the web sets list, I assign the selected item as the current category and navigate to the <strong>ImageSetPage.xaml</strong> page that will display the associated images:</p><p><pre class="brush: csharp">
async void ListBox_SelectionChanged_1(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{    
    var box = (ListBox)sender;
    
    if (box.SelectedItem != null)    
    {    
        Category selectedCategory = (Category)box.SelectedItem;    
        selectedCategory.Images = new ObservableCollection&lt;Coding4Fun.Lockscreen.Core.Models.Image&gt;
        (await dataEngine.GetImagesByCategoryId((int)selectedCategory.id));
        
        CentralBindingPoint.Instance.CurrentCategory = selectedCategory;
        NavigationService.Navigate(new Uri(&quot;/ImageSetPage.xaml&quot;, UriKind.Relative));
    }
}
</pre></p><p>Notice that the images are not loaded at the same time as the categories; rather, they’re loaded only when a category has been selected, hence the <strong>GetImagesByCategoryId</strong> call on selection.</p><p>For a custom set, the procedure is pretty much the same, the only difference being the fact that image references are already present since those were deserialized from the local storage:</p><p><pre class="brush: csharp">
private void lstCustomSets_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
{    
    var box = (ListBox)sender;
    
    if (box.SelectedItem != null)    
    {    
        Category selectedCategory = (Category)box.SelectedItem;    
        CentralBindingPoint.Instance.CurrentCategory = selectedCategory;
        NavigationService.Navigate(new Uri(&quot;/ImageSetPage.xaml&quot;, UriKind.Relative));
    }
}
</pre></p><p>In <strong>ImageSetPage.xaml</strong> I use a <strong>ListBox</strong> with a <strong>WrapPanel</strong> in the <a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.itemspaneltemplate.aspx">ItemsPanelTemplate</a>, which ensures that I can have only two images in a row and any additions will be wrapped, with a fixed row length. You can get that control from the <a href="http://phone.codeplex.com/">WPToolkit</a> (formerly known as Silverlight Toolkit for Windows Phone, <a href="https://nuget.org/packages/WPtoolkit">available on NuGet</a>).</p><p><img src="http://www.codeplex.com/Download?ProjectName=lockscreen&amp;DownloadId=631916" alt="" width="288" height="480"></p><p>Here is the basic XAML layout:</p><p><pre class="brush: xml">
&lt;ListBox 
    SelectionMode=&quot;Single&quot;
    Margin=&quot;24&quot;
    x:Name=&quot;lstImages&quot; SelectionChanged=&quot;lstImages_SelectionChanged_1&quot;
    ItemsSource=&quot;{Binding Path=Instance.CurrentCategory.Images,
    Source={StaticResource CentralBindingPoint}}&quot;
    ItemTemplate=&quot;{StaticResource ListItemTemplate}&quot;&gt;
    &lt;ListBox.ItemsPanel&gt;
        &lt;ItemsPanelTemplate&gt;
            &lt;toolkit:WrapPanel ItemWidth=&quot;216&quot; ItemHeight=&quot;260&quot;/&gt;
        &lt;/ItemsPanelTemplate&gt;
    &lt;/ListBox.ItemsPanel&gt;
&lt;/ListBox&gt;
</pre></p><p>Now that we have a basic skeleton for the incoming data, let’s see how it can be transformed into a live lockscreen, on which wallpapers can be cycled. In the <strong>ImageSetPage.xaml</strong> page I have a button in the application bar that allows me to set the current category as the source for the switching wallpapers.</p><p>Currently, each <strong>Image</strong> instance carries an image URL and the images can be located anywhere outside the application. This can cause problems with the wallpaper setting process, however, since the API only allows local images to be set as background. This means that I need to download each image to the local application folder:</p><p><pre class="brush: csharp">
private async void btnSetStack_Click_1(object sender, EventArgs e)
{    
    var isProvider = Windows.Phone.System.UserProfile.LockScreenManager.IsProvidedByCurrentApplication;
    
    if (!isProvider)    
    {    
        var op = await Windows.Phone.System.UserProfile.LockScreenManager.RequestAccessAsync();    
        isProvider = op == Windows.Phone.System.UserProfile.LockScreenRequestResult.Granted;
    }
    
    if (isProvider)
    {    
        downloadableItems = new List&lt;string&gt;();    
        fileItems = new List&lt;string&gt;();

        foreach (var image in CentralBindingPoint.Instance.CurrentCategory.Images)        
        {    
            downloadableItems.Add(image.URL);    
            fileItems.Add(Path.GetFileName(image.URL));    
        }
        
        SerializationHelper.SerializeToFile(fileItems, &quot;imagestack.xml&quot;);
        LocalStorageHelper.ClearFolder(&quot;CurrentSet&quot;);
        DownloadImages();
        grdDownloading.Visibility = System.Windows.Visibility.Visible;
    }
}
</pre></p><p>First of all, I need to make sure that the application can set a lockscreen background and is registered in the OS as a provider. The application needs to state its intent to be able to access the wallpaper by adding this snippet to the <strong>WMAppManifest.xml</strong>, right after the <strong>Tokens</strong> node:</p><p><pre class="brush: xml">
&lt;Extensions&gt;
      &lt;Extension ExtensionName=&quot;LockScreen_Background&quot; ConsumerID=&quot;{111DFF24-AA15-4A96-8006-2BFF8122084F}&quot; TaskID=&quot;_default&quot; /&gt;
&lt;/Extensions&gt;
</pre></p><p><strong>downloadableItems</strong> is a collection that represents the download queue. <strong>fileItems</strong> contains the local file names for each image that is about to be downloaded and will be serialized and used in the background agent to iterate through the category files. Whenever the download process is started, an overlay becomes visible to notify the user that the image acquisition process is in progress.</p><p>Also, notice the fact that I am calling <strong>LocalStorageHelper.ClearFolder</strong>, passing the name of the folder as the first argument. I do not want to keep images for sets that are not active, therefore when a new set is selected, the currently stored images are deleted from the <strong>CurrentSet</strong> folder and replaced by the ones that are about to be downloaded. The implementation of the <strong>ClearFolder</strong> function looks like this:</p><p><pre class="brush: csharp">
public static void ClearFolder(string folderName
{    
    if (store.DirectoryExists(folderName))    
    {    
        foreach (string file in store.GetFileNames(folderName &#43; &quot;\\*.*&quot;))    
        {    
            store.DeleteFile(folderName &#43; &quot;\\&quot; &#43; file);    
        }
    }
}
</pre></p><p>Once the file names are stored in <strong>imagestack.xml</strong>, the image contents are downloaded via <strong>DownloadImages</strong>:</p><p><pre class="brush: csharp">
void DownloadImages()
{    
    WebClient client = new WebClient();    
    string fileName = Path.GetFileName(downloadableItems.First());
    client.OpenReadAsync(new Uri(downloadableItems.First()));
    client.OpenReadCompleted &#43;= (sender, args) =&gt;
    {    
        Debug.WriteLine(&quot;Downloaded &quot; &#43; fileName);    
        LocalStorageHelper.WriteData(&quot;CurrentSet&quot;, fileName, StreamToByteArray(args.Result));
        downloadableItems.Remove(downloadableItems.First());
        if (downloadableItems.Count != 0)
            DownloadImages();
        else
        {    
            grdDownloading.Visibility = System.Windows.Visibility.Collapsed;    
            LocalStorageHelper.CycleThroughImages();
            
            //ScheduledActionService.LaunchForTest(&quot;LockscreenChanger&quot;, TimeSpan.FromSeconds(5));
        }
    };
}
</pre></p><p>Here you can see that I am making a call to <strong>LocalStorageHelper.CycleThroughImages</strong>—a function that reads the file that contains the current set and picks the first image, assigning it to be the current wallpaper and then pushing it to the back of the list, making the succeeding image the next in line for the wallpaper:</p><p><pre class="brush: csharp">
public static void CycleThroughImages()
{    
    List&lt;string&gt; images = Coding4Fun.Phone.Storage.Serialize.Open&lt;List&lt;string&gt;&gt;(&quot;imagestack.xml&quot;);    
    if (images != null)
    {    
        string tempImage = images.First();    
        Uri currentImageUri = new Uri(&quot;ms-appdata:///Local/CurrentSet/&quot; &#43; tempImage, UriKind.Absolute);
        Windows.Phone.System.UserProfile.LockScreen.SetImageUri(currentImageUri);
        images.Remove(tempImage);
        images.Add(tempImage);
        Coding4Fun.Phone.Storage.Serialize.Save&lt;List&lt;string&gt;&gt;(&quot;imagestack.xml&quot;, images);
    }
}
</pre></p><p>You might be wondering why I’m not using <a href="http://msdn.microsoft.com/en-us/library/7977ey2c.aspx">Queue&lt;T&gt;</a> for this. After all, <strong>Enqueue</strong> and <strong>Dequeue</strong> would make things a bit easier. The problem is that a Queue instance cannot be directly serialized without being transformed to a flat list. Therefore, I am sticking to minimal resource processing by manipulating a <strong>List&lt;T&gt;</strong> instance instead.</p><p>The recursive image download method runs until the download queue is emptied, after which the overlay is hidden.</p><h1>Background Agent</h1><p>At this point, we have the images locally stored and listed in an XML file. If the user accepted the system prompt, the application has also been registered as a lockscreen background provider, but there is not yet a single piece of code that would actually set the wallpaper cycle. For that, create a new Background Agent project in your solution. I named mine <strong>Coding4Fun.Lockscreen.Agent</strong>.</p><p>The <strong>OnInvoke</strong> function in <strong>ScheduledAgent.cs</strong> is executed at 30-minute intervals. This is a time limit defined by the <a href="http://msdn.microsoft.com/en-US/library/windowsphone/develop/microsoft.phone.scheduler.periodictask%28v=vs.105%29.aspx">PeriodicTask</a> background agent type that we’ll be using here. You need to add the following snippet to it:</p><p><pre class="brush: csharp">
protected override void OnInvoke(ScheduledTask task)
{    
    var isProvider = Windows.Phone.System.UserProfile.LockScreenManager.IsProvidedByCurrentApplication;    
    if (isProvider)
    {    
        LocalStorageHelper.CycleThroughImages();    
    }
    NotifyComplete();
}
</pre></p><p>As with the download snippet, I am ensuring that before I attempt to change the wallpaper the application is a registered provider. Otherwise, an exception will be thrown and the background agent will crash. The bad thing about periodic tasks crashing is the fact that once two consecutive crashes occur, the task is removed from the task queue and the backgrounds will not be changed.</p><p>If the application is a provider, call <strong>CycleThroughImages</strong> to set the new background and push the old one to the end of the list. To make sure that a different image is selected each time, the original deserialized list is modified, where the first image now becomes last, switching the stack up, after which it is serialized back into <strong>imagestack.xml</strong>.</p><p>The background agent needs to be registered in the <strong>WMAppManifest.xml</strong>. Inside the Tasks node, add an ExtendedTask:</p><p><pre class="brush: csharp">
&lt;ExtendedTask Name=&quot;LockscreenChangerTask&quot;&gt;
    &lt;BackgroundServiceAgent Specifier=&quot;ScheduledTaskAgent&quot;
        Name=&quot;LockscreenChanger&quot;
        Source=&quot;Coding4Fun.Lockscreen.Agent&quot;
        Type=&quot;Coding4Fun.Lockscreen.Agent.ScheduledAgent&quot; /&gt;
&lt;/ExtendedTask&gt;
</pre></p><p>Also, when the application starts, you need to ensure that the task is registered, and register it if it isn’t yet. Use the Application_Launching event handler for this task:</p><p><pre class="brush: csharp">
private void Application_Launching(object sender, LaunchingEventArgs e)
{    
    string taskName = &quot;LockscreenChanger&quot;;    
    var oldTask = ScheduledActionService.Find(taskName) as PeriodicTask;

    if (oldTask != null)
    {    
        ScheduledActionService.Remove(taskName);    
    }
    
    PeriodicTask task = new PeriodicTask(taskName);
    task.Description = &quot;Change lockscreen wallpaper.&quot;;
    
    ScheduledActionService.Add(task);    
    LoadCustomCategories();    
}
</pre></p><p>Here, <strong>LoadCustomCategories</strong> will deserialize the existing custom categories, so that those can be shown in the main page after the application starts:</p><p><pre class="brush: csharp">
private async void LoadCustomCategories()
{    
    try    
    {    
        CentralBindingPoint.Instance.CustomCategories =    
        (ObservableCollection&lt;Category&gt;)await SerializationHelper.DeserializeFromFile(
        typeof(ObservableCollection&lt;Category&gt;), &quot;customcat.xml&quot;);
    }
    catch
    {    
        Debug.WriteLine(&quot;No customcat.xml - no registered custom categories.&quot;);    
    }
}
</pre></p><p>Now the backgrounds will automatically change based on the web sets that you will activate every 30 minutes.</p><h1>Working with Custom Categories</h1><p>Let’s create some custom sets. To manage user input, I leverage the <strong>CustomMessageBox</strong> control available in the <a href="http://phone.codeplex.com/">Windows Phone Toolkit</a>. It has enough flexibility to let me choose between adding a <strong>TextBox</strong> control, to have the user create the new category or use a <strong>ListPicker</strong> to show the available custom categories in a consistent UI layout.</p><p>When the user decides to create a new category, he taps the plus button in the application bar on the main page:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image022%5B5%5D.png"><img title="clip_image022" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image022_thumb%5B2%5D.png" alt="clip_image022" width="262" height="437" border="0"></a></p><p>The implementation for the call is simple:</p><p><pre class="brush: csharp">
private void btnSetStack_Click_1(object sender, EventArgs e)
{    
    TextBox textBox = new TextBox();    
    CustomMessageBox box = new CustomMessageBox()
    {    
        Caption = &quot;Add Custom Category&quot;,    
        Message = &quot;Enter a unique name for the new category.&quot;,
        LeftButtonContent = &quot;ok&quot;,
        RightButtonContent = &quot;cancel&quot;,
        Content = textBox
    };
    
    box.Dismissed &#43;= (s, boxEventArgs) =&gt;
    {    
        if (boxEventArgs.Result == CustomMessageBoxResult.LeftButton)    
        {    
                    if (!string.IsNullOrWhiteSpace(textBox.Text))    
                    {    
                        var categoryCheck = (from c in CentralBindingPoint.Instance.CustomCategories    
                        where
                        c.Name == textBox.Text
                        select c).FirstOrDefault();
                        
                        if (categoryCheck == null)
                        {    
                            Category category = new Category() { Name = textBox.Text };
                            CentralBindingPoint.Instance.CustomCategories.Add(category);
                            Coding4Fun.Toolkit.Storage.Serialize.Save&lt;ObservableCollection&lt;Category&gt;&gt;(
                            &quot;customcat.xml&quot;, CentralBindingPoint.Instance.CustomCategories);
                        }
                        else
                        {    
                            MessageBox.Show(&quot;Add Custom Category&quot;,    
                            &quot;This category name was already taken!&quot;,
                            MessageBoxButton.OK);
                        }
                    }
        }        
    };
    
    box.Show();    
}
</pre></p><p>When the message box is dismissed, I check which button is pressed to take the appropriate course of action. Let’s assume that the user decided to add the new category—we need to check and make sure that there isn’t already a category with the same name in the existing collection. If there isn’t one, a new <strong>Category</strong> instance is created, added to the collection in the main view model, and serialized to <strong>customcat.xml</strong>.</p><p>The user also needs to be able to add images from any category to another custom category. To do this, I decided to give the user the option to carry across the image name and URL when he taps on an image in the <strong>ImageSetPage.xaml</strong>.</p><p>Remember, if there are no current custom categories registered, the user should be informed that he should create some first, so the alternative route for the dialog with custom category name selection should be a message box alert:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image024%5B5%5D.png"><img title="clip_image024" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image024_thumb%5B2%5D.png" alt="clip_image024" width="264" height="440" border="0"></a></p><p>Here is the snippet that does this:</p><p><pre class="brush: csharp">
private void lstImages_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
{    
    if (CentralBindingPoint.Instance.CustomCategories.Count &gt; 0)    
    {    
        if (lstImages.SelectedItem != null)    
        {    
            ListPicker picker = new ListPicker()    
            {    
                Header = &quot;Custom category name:&quot;,    
                ItemsSource = CentralBindingPoint.Instance.CustomCategories,
                Margin = new Thickness(12, 42, 24, 18)
            };
            
            CustomMessageBox messageBox = new CustomMessageBox()
            {    
                Caption = &quot;Add To Custom Category&quot;,    
                Message = &quot;Select a registered custom category to add this image to.&quot;,
                Content = picker,
                LeftButtonContent = &quot;ok&quot;,
                RightButtonContent = &quot;cancel&quot;
            };
            
            messageBox.Dismissing &#43;= (s, boxEventArgs) =&gt;
            {    
                if (picker.ListPickerMode == ListPickerMode.Expanded)    
                {    
                    boxEventArgs.Cancel = true;    
                }
            };
            
            messageBox.Dismissed &#43;= (s2, e2) =&gt;
            {    
                switch (e2.Result)    
                {    
                    case CustomMessageBoxResult.LeftButton:    
                    {    
                        if (picker.SelectedItem != null)    
                        {    
                            Category category = (from c in CentralBindingPoint.Instance.CustomCategories    
                            where c.Name == picker.SelectedItem.ToString()
                            select c).FirstOrDefault();
                            
                            if (category != null)
                            {    
                                category.Images.Add((Coding4Fun.Lockscreen.Core.Models.Image)lstImages.SelectedItem);    
                                Coding4Fun.Toolkit.Storage.Serialize.Save&lt;ObservableCollection&lt;Category&gt;&gt;(
                                &quot;customcat.xml&quot;, CentralBindingPoint.Instance.CustomCategories);
                            }
                            
                            lstImages.SelectedItem = null;
                            lstImages.IsEnabled = true;
                        }
                        break;
                    }
            
                    case CustomMessageBoxResult.RightButton:        
                    case CustomMessageBoxResult.None:
                    {    
                        lstImages.SelectedItem = null;                    
                        break;
                    }
                }
            };
            
            messageBox.Show();
        }
    }
    else
    {    
        MessageBox.Show(&quot;Add To Custom Category&quot;,    
        &quot;Tapping on an image will prompt you to add it to a custom category&quot; &#43; Environment.NewLine &#43;
        &quot;Seems like you don't have any custom categories yet.&quot;, MessageBoxButton.OK);    
    }
}
</pre></p><p>Once the category is selected from the list, the image is added to the Images collection in the <strong>Category</strong> instance, and the category list is serialized to preserve the changes. There are no restrictions as to which categories can fetch images to other categories—we can even select images from custom categories and include them in other categories. The image can be added multiple times to the same category as well.</p><h1>Conclusion</h1><p>With Azure Mobile Services and a managed SDK available for Windows Phone, as well as an open REST API, it is fairly easy to build connected applications on multiple platforms at once without major logic and code base modifications.</p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/DennisDel/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:1d735d263cfc4453ba06a1870057ac0e">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Dynamic-Lockscreen-Changer-for-Windows-Phone-8-Built-With-ASPNET-MVC-and-Azure-Mobile-Services</comments>
      <itunes:summary>With the release of Windows Phone 8, a few new developer API endpoints were made available that allow third-party applications to change the device lockscreen image. In this article, I am establishing the infrastructure and building a mobile application that provides the ability to choose from a number of dynamic image sets, from which images can be selected and then cycled as lockscreen wallpapers. What do you needYou will need to download and install ASP.NET MVC3 to work on the web frontend and Windows Phone 8 SDK to work on the mobile applications. An Azure Mobile Services account will be necessary, and of course don’t forget to download and install the Azure Mobile Services client libraries. All three components are available at no additional charge. NOTE: Without the Azure Mobile Services SDK installed on the development machine, the compilation process will fail for the Windows Phone application. Setting up The Data StoreFirst we need to establish the general design of the application and organize the workflow. The application will provide two ways to assign the dynamic lockscreen: With the help of custom image sets that are provided by the service; With the help of self-created image sets, aggregated from images provided by the service but ultimately managed by the end-user. Let’s talk about the general data model. Every image belongs to a certain category and to keep track of each we need a table with two columns—category ID and category name. We also need another core table containing the image references themselves, with the following columns: image URL, descriptive name, and the category ID to which it belongs. The overall structure looks like this:  Now to the Windows Azure Management Portal and creating a new Mobile Service.  Once created, you need to specify database information, just like you would with a standard SQL Server database:  As the database is being created, you can easily integrate it with SQL Server Management Studio. You will need the se</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Dynamic-Lockscreen-Changer-for-Windows-Phone-8-Built-With-ASPNET-MVC-and-Azure-Mobile-Services</link>
      <pubDate>Mon, 25 Mar 2013 15:39:25 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Dynamic-Lockscreen-Changer-for-Windows-Phone-8-Built-With-ASPNET-MVC-and-Azure-Mobile-Services</guid>
      <media:thumbnail url="http://files.channel9.msdn.com/thumbnail/6e006890-17a7-490b-84ab-dc762acb6541.png" height="100" width="100"></media:thumbnail>
      <media:thumbnail url="http://files.channel9.msdn.com/thumbnail/ac86e266-3378-4993-b73b-0e3d002b3ca5.png" height="220" width="220"></media:thumbnail>
      <media:thumbnail url="http://files.channel9.msdn.com/thumbnail/f6acb002-27be-41d5-8f4d-97ca7e170e80.png" height="284" width="512"></media:thumbnail>      
      <dc:creator>Clint Rutkas, Den Delimarsky</dc:creator>
      <itunes:author>Clint Rutkas, Den Delimarsky</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Dynamic-Lockscreen-Changer-for-Windows-Phone-8-Built-With-ASPNET-MVC-and-Azure-Mobile-Services/RSS</wfw:commentRss>
      <category>Azure</category>
      <category>MVC</category>
      <category>Windows Phone</category>
      <category>Windows Azure Mobile Services</category>
    </item>
  <item>
      <title>Part 12 - Project Conclusion</title>
      <description><![CDATA[<p>In this video, Den Delimarsky summarizes his experiences building FallFury, highlighting the lessons he learned as a software developer on the Coding4Fun team at Microsoft.</p><p>Check out the article for this video at <a href="http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-12-Conclusions">http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-12-Conclusions</a></p><p>For the source code, head over to <a href="http://fallfury.codeplex.com/">http://fallfury.codeplex.com</a></p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/DennisDel/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:036f886aee27434695d7a13f01829948">]]></description>
      <comments>http://channel9.msdn.com/Series/FallFury/Part-12-Project-Conclusion</comments>
      <itunes:summary>In this video, Den Delimarsky summarizes his experiences building FallFury, highlighting the lessons he learned as a software developer on the Coding4Fun team at Microsoft. Check out the article for this video at http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-12-Conclusions For the source code, head over to http://fallfury.codeplex.com </itunes:summary>
      <itunes:duration>1133</itunes:duration>
      <link>http://channel9.msdn.com/Series/FallFury/Part-12-Project-Conclusion</link>
      <pubDate>Wed, 23 Jan 2013 23:59:14 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/Series/FallFury/Part-12-Project-Conclusion</guid>
      <media:thumbnail url="http://media.ch9.ms/ch9/f8eb/37473ed7-1ccd-4afc-834d-d99ae5b2f8eb/FallFuryPart12_100.jpg" height="56" width="100"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/f8eb/37473ed7-1ccd-4afc-834d-d99ae5b2f8eb/FallFuryPart12_220.jpg" height="124" width="220"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/f8eb/37473ed7-1ccd-4afc-834d-d99ae5b2f8eb/FallFuryPart12_512.jpg" height="289" width="512"></media:thumbnail>
      <media:group>
        <media:content url="http://media.ch9.ms/ch9/f8eb/37473ed7-1ccd-4afc-834d-d99ae5b2f8eb/FallFuryPart12.mp3" expression="full" duration="1133" fileSize="18137909" type="audio/mp3" medium="audio"></media:content>
        <media:content url="http://media.ch9.ms/ch9/f8eb/37473ed7-1ccd-4afc-834d-d99ae5b2f8eb/FallFuryPart12.mp4" expression="full" duration="1133" fileSize="76441843" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/f8eb/37473ed7-1ccd-4afc-834d-d99ae5b2f8eb/FallFuryPart12.webm" expression="full" duration="1133" fileSize="35449275" type="video/webm" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/f8eb/37473ed7-1ccd-4afc-834d-d99ae5b2f8eb/FallFuryPart12.wma" expression="full" duration="1133" fileSize="9179247" type="audio/x-ms-wma" medium="audio"></media:content>
        <media:content url="http://media.ch9.ms/ch9/f8eb/37473ed7-1ccd-4afc-834d-d99ae5b2f8eb/FallFuryPart12.wmv" expression="full" duration="1133" fileSize="38880107" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/f8eb/37473ed7-1ccd-4afc-834d-d99ae5b2f8eb/FallFuryPart12_high.mp4" expression="full" duration="1133" fileSize="242090737" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/f8eb/37473ed7-1ccd-4afc-834d-d99ae5b2f8eb/FallFuryPart12_mid.mp4" expression="full" duration="1133" fileSize="148041231" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/f8eb/37473ed7-1ccd-4afc-834d-d99ae5b2f8eb/FallFuryPart12_Source.wmv" expression="full" duration="1133" fileSize="103772286" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://smooth.ch9.ms/ch9/f8eb/37473ed7-1ccd-4afc-834d-d99ae5b2f8eb/FallFuryPart12.ism/manifest" expression="full" duration="1133" fileSize="8462" type="video/x-ms-wmv" medium="video"></media:content>
      </media:group>      
      <enclosure url="http://media.ch9.ms/ch9/f8eb/37473ed7-1ccd-4afc-834d-d99ae5b2f8eb/FallFuryPart12.wmv" length="38880107" type="video/x-ms-wmv"></enclosure>
      <dc:creator>Clint Rutkas, Den Delimarsky</dc:creator>
      <itunes:author>Clint Rutkas, Den Delimarsky</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/Series/FallFury/Part-12-Project-Conclusion/RSS</wfw:commentRss>
      <category>C#</category>
      <category>C++</category>
      <category>DirectX</category>
      <category>Windows Store App</category>
    </item>
  <item>
      <title>Part 11 - Hardware Testing</title>
      <description><![CDATA[<p>Because of the large Windows 8 user base, FallFury was tested on different hardware with different input layouts. This video covers the basic setup necessary for remote debugging and performance tuning when connected to a test device, such as the Microsoft Surface.</p><p>Check out the article for this video at <a href="http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-11-Hardware-Testing--Debugging">http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-11-Hardware-Testing--Debugging</a></p><p>For the source code, head over to <a href="http://fallfury.codeplex.com">http://fallfury.codeplex.com</a></p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/DennisDel/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:ee8b551e56084ee0bb6ca13f018281f6">]]></description>
      <comments>http://channel9.msdn.com/Series/FallFury/Part-11-Hardware-Testing</comments>
      <itunes:summary>Because of the large Windows 8 user base, FallFury was tested on different hardware with different input layouts. This video covers the basic setup necessary for remote debugging and performance tuning when connected to a test device, such as the Microsoft Surface. Check out the article for this video at http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-11-Hardware-Testing--Debugging For the source code, head over to http://fallfury.codeplex.com </itunes:summary>
      <itunes:duration>707</itunes:duration>
      <link>http://channel9.msdn.com/Series/FallFury/Part-11-Hardware-Testing</link>
      <pubDate>Wed, 23 Jan 2013 23:59:10 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/Series/FallFury/Part-11-Hardware-Testing</guid>
      <media:thumbnail url="http://media.ch9.ms/ch9/d2bf/2dea3e0d-559c-4efb-ae2d-a2c49c20d2bf/FallFuryPart11_100.jpg" height="56" width="100"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/d2bf/2dea3e0d-559c-4efb-ae2d-a2c49c20d2bf/FallFuryPart11_220.jpg" height="124" width="220"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/d2bf/2dea3e0d-559c-4efb-ae2d-a2c49c20d2bf/FallFuryPart11_512.jpg" height="289" width="512"></media:thumbnail>
      <media:group>
        <media:content url="http://media.ch9.ms/ch9/d2bf/2dea3e0d-559c-4efb-ae2d-a2c49c20d2bf/FallFuryPart11.mp3" expression="full" duration="707" fileSize="11315411" type="audio/mp3" medium="audio"></media:content>
        <media:content url="http://media.ch9.ms/ch9/d2bf/2dea3e0d-559c-4efb-ae2d-a2c49c20d2bf/FallFuryPart11.mp4" expression="full" duration="707" fileSize="54068940" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/d2bf/2dea3e0d-559c-4efb-ae2d-a2c49c20d2bf/FallFuryPart11.webm" expression="full" duration="707" fileSize="24968296" type="video/webm" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/d2bf/2dea3e0d-559c-4efb-ae2d-a2c49c20d2bf/FallFuryPart11.wma" expression="full" duration="707" fileSize="5730655" type="audio/x-ms-wma" medium="audio"></media:content>
        <media:content url="http://media.ch9.ms/ch9/d2bf/2dea3e0d-559c-4efb-ae2d-a2c49c20d2bf/FallFuryPart11.wmv" expression="full" duration="707" fileSize="25814015" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/d2bf/2dea3e0d-559c-4efb-ae2d-a2c49c20d2bf/FallFuryPart11_high.mp4" expression="full" duration="707" fileSize="160833339" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/d2bf/2dea3e0d-559c-4efb-ae2d-a2c49c20d2bf/FallFuryPart11_mid.mp4" expression="full" duration="707" fileSize="97822943" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/d2bf/2dea3e0d-559c-4efb-ae2d-a2c49c20d2bf/FallFuryPart11_Source.wmv" expression="full" duration="707" fileSize="83625730" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://smooth.ch9.ms/ch9/d2bf/2dea3e0d-559c-4efb-ae2d-a2c49c20d2bf/FallFuryPart11.ism/manifest" expression="full" duration="707" fileSize="8462" type="video/x-ms-wmv" medium="video"></media:content>
      </media:group>      
      <enclosure url="http://media.ch9.ms/ch9/d2bf/2dea3e0d-559c-4efb-ae2d-a2c49c20d2bf/FallFuryPart11.wmv" length="25814015" type="video/x-ms-wmv"></enclosure>
      <dc:creator>Clint Rutkas, Den Delimarsky</dc:creator>
      <itunes:author>Clint Rutkas, Den Delimarsky</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/Series/FallFury/Part-11-Hardware-Testing/RSS</wfw:commentRss>
      <category>C#</category>
      <category>C++</category>
      <category>DirectX</category>
      <category>Windows Store App</category>
    </item>
  <item>
      <title>Part 10 - Charms</title>
      <description><![CDATA[<p>Windows 8 offers a unified way to interact with other applications, as well as with the app's own settings, through charms. This video introduces you to the concept of Windows 8 charms and covers the implementation of a Settings and Share charm integration mechanism in FallFury.</p><p>Check out the article for this video at <a href="http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-10-Charms">http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-10-Charms</a></p><p>For the source code, head over to <a href="http://fallfury.codeplex.com/">http://fallfury.codeplex.com</a></p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/DennisDel/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:3dc6c00618ff4b8f8a29a13f01827298">]]></description>
      <comments>http://channel9.msdn.com/Series/FallFury/Part-10-Charms</comments>
      <itunes:summary>Windows 8 offers a unified way to interact with other applications, as well as with the app&#39;s own settings, through charms. This video introduces you to the concept of Windows 8 charms and covers the implementation of a Settings and Share charm integration mechanism in FallFury. Check out the article for this video at http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-10-Charms For the source code, head over to http://fallfury.codeplex.com </itunes:summary>
      <itunes:duration>984</itunes:duration>
      <link>http://channel9.msdn.com/Series/FallFury/Part-10-Charms</link>
      <pubDate>Wed, 23 Jan 2013 23:58:52 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/Series/FallFury/Part-10-Charms</guid>
      <media:thumbnail url="http://media.ch9.ms/ch9/d462/4039d0c3-2c48-4570-98d7-56de07f1d462/FallFuryPart10_100.jpg" height="56" width="100"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/d462/4039d0c3-2c48-4570-98d7-56de07f1d462/FallFuryPart10_220.jpg" height="124" width="220"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/d462/4039d0c3-2c48-4570-98d7-56de07f1d462/FallFuryPart10_512.jpg" height="289" width="512"></media:thumbnail>
      <media:group>
        <media:content url="http://media.ch9.ms/ch9/d462/4039d0c3-2c48-4570-98d7-56de07f1d462/FallFuryPart10.mp3" expression="full" duration="984" fileSize="15757889" type="audio/mp3" medium="audio"></media:content>
        <media:content url="http://media.ch9.ms/ch9/d462/4039d0c3-2c48-4570-98d7-56de07f1d462/FallFuryPart10.mp4" expression="full" duration="984" fileSize="89965283" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/d462/4039d0c3-2c48-4570-98d7-56de07f1d462/FallFuryPart10.webm" expression="full" duration="984" fileSize="36936001" type="video/webm" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/d462/4039d0c3-2c48-4570-98d7-56de07f1d462/FallFuryPart10.wma" expression="full" duration="984" fileSize="7977647" type="audio/x-ms-wma" medium="audio"></media:content>
        <media:content url="http://media.ch9.ms/ch9/d462/4039d0c3-2c48-4570-98d7-56de07f1d462/FallFuryPart10.wmv" expression="full" duration="984" fileSize="38335397" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/d462/4039d0c3-2c48-4570-98d7-56de07f1d462/FallFuryPart10_high.mp4" expression="full" duration="984" fileSize="206460652" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/d462/4039d0c3-2c48-4570-98d7-56de07f1d462/FallFuryPart10_mid.mp4" expression="full" duration="984" fileSize="142233883" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/d462/4039d0c3-2c48-4570-98d7-56de07f1d462/FallFuryPart10_Source.wmv" expression="full" duration="984" fileSize="140555392" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://smooth.ch9.ms/ch9/d462/4039d0c3-2c48-4570-98d7-56de07f1d462/FallFuryPart10.ism/manifest" expression="full" duration="984" fileSize="8462" type="video/x-ms-wmv" medium="video"></media:content>
      </media:group>      
      <enclosure url="http://media.ch9.ms/ch9/d462/4039d0c3-2c48-4570-98d7-56de07f1d462/FallFuryPart10.wmv" length="38335397" type="video/x-ms-wmv"></enclosure>
      <dc:creator>Clint Rutkas, Den Delimarsky</dc:creator>
      <itunes:author>Clint Rutkas, Den Delimarsky</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/Series/FallFury/Part-10-Charms/RSS</wfw:commentRss>
      <category>C#</category>
      <category>C++</category>
      <category>DirectX</category>
      <category>Windows Store App</category>
    </item>
  <item>
      <title>Part 9 - Particle System</title>
      <description><![CDATA[<p>This video covers the creation of a particle system that is able to generate a texture-based particle layout in different parts of the visible screen, with different geometric and displacement conditions.</p><p>Check out the article for this video at <a href="http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-9-Particle-System">http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-9-Particle-System</a></p><p>For the source code, head over to <a href="http://fallfury.codeplex.com/">http://fallfury.codeplex.com</a></p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/DennisDel/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:3ae96e77a6d04c32911da13f018260ce">]]></description>
      <comments>http://channel9.msdn.com/Series/FallFury/Part-9-Particle-System</comments>
      <itunes:summary>This video covers the creation of a particle system that is able to generate a texture-based particle layout in different parts of the visible screen, with different geometric and displacement conditions. Check out the article for this video at http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-9-Particle-System For the source code, head over to http://fallfury.codeplex.com </itunes:summary>
      <itunes:duration>1030</itunes:duration>
      <link>http://channel9.msdn.com/Series/FallFury/Part-9-Particle-System</link>
      <pubDate>Wed, 23 Jan 2013 23:58:49 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/Series/FallFury/Part-9-Particle-System</guid>
      <media:thumbnail url="http://media.ch9.ms/ch9/af7e/b408253b-7538-45b2-9b34-0685e059af7e/FallFuryPart9_100.jpg" height="56" width="100"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/af7e/b408253b-7538-45b2-9b34-0685e059af7e/FallFuryPart9_220.jpg" height="124" width="220"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/af7e/b408253b-7538-45b2-9b34-0685e059af7e/FallFuryPart9_512.jpg" height="289" width="512"></media:thumbnail>
      <media:group>
        <media:content url="http://media.ch9.ms/ch9/af7e/b408253b-7538-45b2-9b34-0685e059af7e/FallFuryPart9.mp3" expression="full" duration="1030" fileSize="16485982" type="audio/mp3" medium="audio"></media:content>
        <media:content url="http://media.ch9.ms/ch9/af7e/b408253b-7538-45b2-9b34-0685e059af7e/FallFuryPart9.mp4" expression="full" duration="1030" fileSize="74535124" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/af7e/b408253b-7538-45b2-9b34-0685e059af7e/FallFuryPart9.webm" expression="full" duration="1030" fileSize="35469767" type="video/webm" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/af7e/b408253b-7538-45b2-9b34-0685e059af7e/FallFuryPart9.wma" expression="full" duration="1030" fileSize="8347139" type="audio/x-ms-wma" medium="audio"></media:content>
        <media:content url="http://media.ch9.ms/ch9/af7e/b408253b-7538-45b2-9b34-0685e059af7e/FallFuryPart9.wmv" expression="full" duration="1030" fileSize="36459209" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/af7e/b408253b-7538-45b2-9b34-0685e059af7e/FallFuryPart9_high.mp4" expression="full" duration="1030" fileSize="239960640" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/af7e/b408253b-7538-45b2-9b34-0685e059af7e/FallFuryPart9_mid.mp4" expression="full" duration="1030" fileSize="137966226" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/af7e/b408253b-7538-45b2-9b34-0685e059af7e/FallFuryPart9_Source.wmv" expression="full" duration="1030" fileSize="121307668" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://smooth.ch9.ms/ch9/af7e/b408253b-7538-45b2-9b34-0685e059af7e/FallFuryPart9.ism/manifest" expression="full" duration="1030" fileSize="8446" type="video/x-ms-wmv" medium="video"></media:content>
      </media:group>      
      <enclosure url="http://media.ch9.ms/ch9/af7e/b408253b-7538-45b2-9b34-0685e059af7e/FallFuryPart9.wmv" length="36459209" type="video/x-ms-wmv"></enclosure>
      <dc:creator>Clint Rutkas, Den Delimarsky</dc:creator>
      <itunes:author>Clint Rutkas, Den Delimarsky</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/Series/FallFury/Part-9-Particle-System/RSS</wfw:commentRss>
      <category>C#</category>
      <category>C++</category>
      <category>DirectX</category>
      <category>Windows Store App</category>
    </item>
  <item>
      <title>Part 8 - Element Interaction</title>
      <description><![CDATA[<p>In FallFury, elements such as obstacle, buttons, and characters collide and react to each other's actions depending on specific game conditions. This video describes the basics of collision detection and object interaction in the game.</p><p>Check out the article for this video at <a href="http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-8-Element-Interaction">http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-8-Element-Interaction</a></p><p>For the source code, head over to <a href="http://fallfury.codeplex.com/">http://fallfury.codeplex.com</a></p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/DennisDel/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:7b77f68e4c52401cab16a13f01814ff1">]]></description>
      <comments>http://channel9.msdn.com/Series/FallFury/Part-8-Element-Interaction</comments>
      <itunes:summary>In FallFury, elements such as obstacle, buttons, and characters collide and react to each other&#39;s actions depending on specific game conditions. This video describes the basics of collision detection and object interaction in the game. Check out the article for this video at http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-8-Element-Interaction For the source code, head over to http://fallfury.codeplex.com </itunes:summary>
      <itunes:duration>1114</itunes:duration>
      <link>http://channel9.msdn.com/Series/FallFury/Part-8-Element-Interaction</link>
      <pubDate>Wed, 23 Jan 2013 23:58:45 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/Series/FallFury/Part-8-Element-Interaction</guid>
      <media:thumbnail url="http://media.ch9.ms/ch9/3d85/e97b9237-10bd-414e-b825-986d050e3d85/FallFuryPart8_100.jpg" height="56" width="100"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/3d85/e97b9237-10bd-414e-b825-986d050e3d85/FallFuryPart8_220.jpg" height="124" width="220"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/3d85/e97b9237-10bd-414e-b825-986d050e3d85/FallFuryPart8_512.jpg" height="289" width="512"></media:thumbnail>
      <media:group>
        <media:content url="http://media.ch9.ms/ch9/3d85/e97b9237-10bd-414e-b825-986d050e3d85/FallFuryPart8.mp3" expression="full" duration="1114" fileSize="17825963" type="audio/mp3" medium="audio"></media:content>
        <media:content url="http://media.ch9.ms/ch9/3d85/e97b9237-10bd-414e-b825-986d050e3d85/FallFuryPart8.mp4" expression="full" duration="1114" fileSize="82202538" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/3d85/e97b9237-10bd-414e-b825-986d050e3d85/FallFuryPart8.webm" expression="full" duration="1114" fileSize="38496918" type="video/webm" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/3d85/e97b9237-10bd-414e-b825-986d050e3d85/FallFuryPart8.wma" expression="full" duration="1114" fileSize="9020035" type="audio/x-ms-wma" medium="audio"></media:content>
        <media:content url="http://media.ch9.ms/ch9/3d85/e97b9237-10bd-414e-b825-986d050e3d85/FallFuryPart8.wmv" expression="full" duration="1114" fileSize="39854075" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/3d85/e97b9237-10bd-414e-b825-986d050e3d85/FallFuryPart8_high.mp4" expression="full" duration="1114" fileSize="234154759" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/3d85/e97b9237-10bd-414e-b825-986d050e3d85/FallFuryPart8_mid.mp4" expression="full" duration="1114" fileSize="150556867" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/3d85/e97b9237-10bd-414e-b825-986d050e3d85/FallFuryPart8_Source.wmv" expression="full" duration="1114" fileSize="135964166" type="video/x-ms-wmv" medium="video"></media:content>
      </media:group>      
      <enclosure url="http://media.ch9.ms/ch9/3d85/e97b9237-10bd-414e-b825-986d050e3d85/FallFuryPart8.wmv" length="39854075" type="video/x-ms-wmv"></enclosure>
      <dc:creator>Clint Rutkas, Den Delimarsky</dc:creator>
      <itunes:author>Clint Rutkas, Den Delimarsky</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/Series/FallFury/Part-8-Element-Interaction/RSS</wfw:commentRss>
      <category>C#</category>
      <category>C++</category>
      <category>DirectX</category>
      <category>Windows Store App</category>
    </item>
  <item>
      <title>Part 7 - Animations</title>
      <description><![CDATA[<p>This video covers the creation of basic animations in FallFury with the help of the core game update loop and additional timers capable of switching object states.</p><p>Check out the article for this video at <a href="http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-7-Animations">http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-7-Animations</a></p><p>For the source code, head over to <a href="http://fallfury.codeplex.com/">http://fallfury.codeplex.com</a></p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/DennisDel/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:ed4e9837e67b44dfa086a13f018139c5">]]></description>
      <comments>http://channel9.msdn.com/Series/FallFury/Part-7-Animations</comments>
      <itunes:summary>This video covers the creation of basic animations in FallFury with the help of the core game update loop and additional timers capable of switching object states. Check out the article for this video at http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-7-Animations For the source code, head over to http://fallfury.codeplex.com </itunes:summary>
      <itunes:duration>1964</itunes:duration>
      <link>http://channel9.msdn.com/Series/FallFury/Part-7-Animations</link>
      <pubDate>Wed, 23 Jan 2013 23:58:40 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/Series/FallFury/Part-7-Animations</guid>
      <media:thumbnail url="http://media.ch9.ms/ch9/5a90/d869aabf-608a-42a9-b8b5-3512c3e65a90/FallFuryPart7_100.jpg" height="56" width="100"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/5a90/d869aabf-608a-42a9-b8b5-3512c3e65a90/FallFuryPart7_220.jpg" height="124" width="220"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/5a90/d869aabf-608a-42a9-b8b5-3512c3e65a90/FallFuryPart7_512.jpg" height="289" width="512"></media:thumbnail>
      <media:group>
        <media:content url="http://media.ch9.ms/ch9/5a90/d869aabf-608a-42a9-b8b5-3512c3e65a90/FallFuryPart7.mp3" expression="full" duration="1964" fileSize="31438884" type="audio/mp3" medium="audio"></media:content>
        <media:content url="http://media.ch9.ms/ch9/5a90/d869aabf-608a-42a9-b8b5-3512c3e65a90/FallFuryPart7.mp4" expression="full" duration="1964" fileSize="173074091" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/5a90/d869aabf-608a-42a9-b8b5-3512c3e65a90/FallFuryPart7.webm" expression="full" duration="1964" fileSize="68874981" type="video/webm" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/5a90/d869aabf-608a-42a9-b8b5-3512c3e65a90/FallFuryPart7.wma" expression="full" duration="1964" fileSize="15902199" type="audio/x-ms-wma" medium="audio"></media:content>
        <media:content url="http://media.ch9.ms/ch9/5a90/d869aabf-608a-42a9-b8b5-3512c3e65a90/FallFuryPart7.wmv" expression="full" duration="1964" fileSize="75918365" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/5a90/d869aabf-608a-42a9-b8b5-3512c3e65a90/FallFuryPart7_high.mp4" expression="full" duration="1964" fileSize="406073930" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/5a90/d869aabf-608a-42a9-b8b5-3512c3e65a90/FallFuryPart7_mid.mp4" expression="full" duration="1964" fileSize="280558876" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/5a90/d869aabf-608a-42a9-b8b5-3512c3e65a90/FallFuryPart7_Source.wmv" expression="full" duration="1964" fileSize="273569272" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://smooth.ch9.ms/ch9/5a90/d869aabf-608a-42a9-b8b5-3512c3e65a90/FallFuryPart7.ism/manifest" expression="full" duration="1964" fileSize="8446" type="video/x-ms-wmv" medium="video"></media:content>
      </media:group>      
      <enclosure url="http://media.ch9.ms/ch9/5a90/d869aabf-608a-42a9-b8b5-3512c3e65a90/FallFuryPart7.wmv" length="75918365" type="video/x-ms-wmv"></enclosure>
      <dc:creator>Clint Rutkas, Den Delimarsky</dc:creator>
      <itunes:author>Clint Rutkas, Den Delimarsky</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/Series/FallFury/Part-7-Animations/RSS</wfw:commentRss>
      <category>C#</category>
      <category>C++</category>
      <category>DirectX</category>
      <category>Windows Store App</category>
    </item>
  <item>
      <title>Part 6 - Rendering Level Elements</title>
      <description><![CDATA[<p>Levels rely on multiple elements aggregated directly from the associated XML file. In this video, Den explains how such elements are processed and rendered internally.</p><p>Check out the article for this video at <a href="http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-6-Rendering-Level-Elements">http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-6-Rendering-Level-Elements</a></p><p>For the source code, head over to <a href="http://fallfury.codeplex.com/">http://fallfury.codeplex.com</a></p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/DennisDel/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:fe1e30f7d2394306b861a13f018115d7">]]></description>
      <comments>http://channel9.msdn.com/Series/FallFury/Part-6-Rendering-Level-Elements</comments>
      <itunes:summary>Levels rely on multiple elements aggregated directly from the associated XML file. In this video, Den explains how such elements are processed and rendered internally. Check out the article for this video at http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-6-Rendering-Level-Elements For the source code, head over to http://fallfury.codeplex.com </itunes:summary>
      <itunes:duration>873</itunes:duration>
      <link>http://channel9.msdn.com/Series/FallFury/Part-6-Rendering-Level-Elements</link>
      <pubDate>Wed, 23 Jan 2013 23:58:37 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/Series/FallFury/Part-6-Rendering-Level-Elements</guid>
      <media:thumbnail url="http://media.ch9.ms/ch9/7ae7/6a8080f8-5fdb-4614-9540-da3c77cc7ae7/FallFuryPart6_100.jpg" height="56" width="100"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/7ae7/6a8080f8-5fdb-4614-9540-da3c77cc7ae7/FallFuryPart6_220.jpg" height="124" width="220"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/7ae7/6a8080f8-5fdb-4614-9540-da3c77cc7ae7/FallFuryPart6_512.jpg" height="289" width="512"></media:thumbnail>
      <media:group>
        <media:content url="http://media.ch9.ms/ch9/7ae7/6a8080f8-5fdb-4614-9540-da3c77cc7ae7/FallFuryPart6.mp3" expression="full" duration="873" fileSize="13984260" type="audio/mp3" medium="audio"></media:content>
        <media:content url="http://media.ch9.ms/ch9/7ae7/6a8080f8-5fdb-4614-9540-da3c77cc7ae7/FallFuryPart6.mp4" expression="full" duration="873" fileSize="66154814" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/7ae7/6a8080f8-5fdb-4614-9540-da3c77cc7ae7/FallFuryPart6.webm" expression="full" duration="873" fileSize="31056101" type="video/webm" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/7ae7/6a8080f8-5fdb-4614-9540-da3c77cc7ae7/FallFuryPart6.wma" expression="full" duration="873" fileSize="7079451" type="audio/x-ms-wma" medium="audio"></media:content>
        <media:content url="http://media.ch9.ms/ch9/7ae7/6a8080f8-5fdb-4614-9540-da3c77cc7ae7/FallFuryPart6.wmv" expression="full" duration="873" fileSize="31761131" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/7ae7/6a8080f8-5fdb-4614-9540-da3c77cc7ae7/FallFuryPart6_high.mp4" expression="full" duration="873" fileSize="187261821" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/7ae7/6a8080f8-5fdb-4614-9540-da3c77cc7ae7/FallFuryPart6_mid.mp4" expression="full" duration="873" fileSize="121925346" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/7ae7/6a8080f8-5fdb-4614-9540-da3c77cc7ae7/FallFuryPart6_Source.wmv" expression="full" duration="873" fileSize="127674726" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://smooth.ch9.ms/ch9/7ae7/6a8080f8-5fdb-4614-9540-da3c77cc7ae7/FallFuryPart6.ism/manifest" expression="full" duration="873" fileSize="8446" type="video/x-ms-wmv" medium="video"></media:content>
      </media:group>      
      <enclosure url="http://media.ch9.ms/ch9/7ae7/6a8080f8-5fdb-4614-9540-da3c77cc7ae7/FallFuryPart6.wmv" length="31761131" type="video/x-ms-wmv"></enclosure>
      <dc:creator>Clint Rutkas, Den Delimarsky</dc:creator>
      <itunes:author>Clint Rutkas, Den Delimarsky</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/Series/FallFury/Part-6-Rendering-Level-Elements/RSS</wfw:commentRss>
      <category>C#</category>
      <category>C++</category>
      <category>DirectX</category>
      <category>Windows Store App</category>
    </item>
  <item>
      <title>Part 5 - Creating Levels</title>
      <description><![CDATA[<p>FallFury supports dynamic level creation and rendering and is not tied to the level content that is shipped with the default build. This video covers the level XML building process and in-game testing.</p><p>Check out the article for this video at <a href="http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-5-Creating-Levels">http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-5-Creating-Levels</a></p><p>For the source code, head over to <a href="http://fallfury.codeplex.com/">http://fallfury.codeplex.com</a></p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/DennisDel/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:2d230ac00fcf4370b13aa13f0180f46f">]]></description>
      <comments>http://channel9.msdn.com/Series/FallFury/Part-5-Creating-Levels</comments>
      <itunes:summary>FallFury supports dynamic level creation and rendering and is not tied to the level content that is shipped with the default build. This video covers the level XML building process and in-game testing. Check out the article for this video at http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-5-Creating-Levels For the source code, head over to http://fallfury.codeplex.com </itunes:summary>
      <itunes:duration>1693</itunes:duration>
      <link>http://channel9.msdn.com/Series/FallFury/Part-5-Creating-Levels</link>
      <pubDate>Wed, 23 Jan 2013 23:58:33 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/Series/FallFury/Part-5-Creating-Levels</guid>
      <media:thumbnail url="http://media.ch9.ms/ch9/b079/411aa110-67a6-4cda-9606-e3473f1bb079/FallFuryPart5_100.jpg" height="56" width="100"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/b079/411aa110-67a6-4cda-9606-e3473f1bb079/FallFuryPart5_220.jpg" height="124" width="220"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/b079/411aa110-67a6-4cda-9606-e3473f1bb079/FallFuryPart5_512.jpg" height="289" width="512"></media:thumbnail>
      <media:group>
        <media:content url="http://media.ch9.ms/ch9/b079/411aa110-67a6-4cda-9606-e3473f1bb079/FallFuryPart5.mp3" expression="full" duration="1693" fileSize="27103399" type="audio/mp3" medium="audio"></media:content>
        <media:content url="http://media.ch9.ms/ch9/b079/411aa110-67a6-4cda-9606-e3473f1bb079/FallFuryPart5.mp4" expression="full" duration="1693" fileSize="157603835" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/b079/411aa110-67a6-4cda-9606-e3473f1bb079/FallFuryPart5.webm" expression="full" duration="1693" fileSize="61751368" type="video/webm" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/b079/411aa110-67a6-4cda-9606-e3473f1bb079/FallFuryPart5.wma" expression="full" duration="1693" fileSize="13712283" type="audio/x-ms-wma" medium="audio"></media:content>
        <media:content url="http://media.ch9.ms/ch9/b079/411aa110-67a6-4cda-9606-e3473f1bb079/FallFuryPart5.wmv" expression="full" duration="1693" fileSize="64185851" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/b079/411aa110-67a6-4cda-9606-e3473f1bb079/FallFuryPart5_high.mp4" expression="full" duration="1693" fileSize="351067777" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/b079/411aa110-67a6-4cda-9606-e3473f1bb079/FallFuryPart5_mid.mp4" expression="full" duration="1693" fileSize="253154672" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/b079/411aa110-67a6-4cda-9606-e3473f1bb079/FallFuryPart5_Source.wmv" expression="full" duration="1693" fileSize="226911646" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://smooth.ch9.ms/ch9/b079/411aa110-67a6-4cda-9606-e3473f1bb079/FallFuryPart5.ism/manifest" expression="full" duration="1693" fileSize="8446" type="video/x-ms-wmv" medium="video"></media:content>
      </media:group>      
      <enclosure url="http://media.ch9.ms/ch9/b079/411aa110-67a6-4cda-9606-e3473f1bb079/FallFuryPart5.wmv" length="64185851" type="video/x-ms-wmv"></enclosure>
      <dc:creator>Clint Rutkas, Den Delimarsky</dc:creator>
      <itunes:author>Clint Rutkas, Den Delimarsky</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/Series/FallFury/Part-5-Creating-Levels/RSS</wfw:commentRss>
      <category>C#</category>
      <category>C++</category>
      <category>DirectX</category>
      <category>Windows Store App</category>
    </item>
  <item>
      <title>Part 4 - XAML Interop</title>
      <description><![CDATA[<p>In this video, Den Delimarsky shows how the DirectX and XAML hybrid applications available in Visual Studio 2012 were implemented in FallFury and discusses what should be considered when working on an app that leverages these capabilities.</p><p>Check out the article for this video at <a href="http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-4-XAML-Interop">http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-4-XAML-Interop</a></p><p>For the source code, head over to <a href="http://fallfury.codeplex.com/">http://fallfury.codeplex.com</a></p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/DennisDel/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:484c9e8941544956a986a13f017d7190">]]></description>
      <comments>http://channel9.msdn.com/Series/FallFury/Part-4-XAML-Interop</comments>
      <itunes:summary>In this video, Den Delimarsky shows how the DirectX and XAML hybrid applications available in Visual Studio 2012 were implemented in FallFury and discusses what should be considered when working on an app that leverages these capabilities. Check out the article for this video at http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-4-XAML-Interop For the source code, head over to http://fallfury.codeplex.com </itunes:summary>
      <itunes:duration>1034</itunes:duration>
      <link>http://channel9.msdn.com/Series/FallFury/Part-4-XAML-Interop</link>
      <pubDate>Wed, 23 Jan 2013 23:58:29 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/Series/FallFury/Part-4-XAML-Interop</guid>
      <media:thumbnail url="http://media.ch9.ms/ch9/04e6/01086880-1f2d-4b77-8261-a7ccc0c804e6/FallFuryPart4_100.jpg" height="56" width="100"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/04e6/01086880-1f2d-4b77-8261-a7ccc0c804e6/FallFuryPart4_220.jpg" height="124" width="220"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/04e6/01086880-1f2d-4b77-8261-a7ccc0c804e6/FallFuryPart4_512.jpg" height="289" width="512"></media:thumbnail>
      <media:group>
        <media:content url="http://media.ch9.ms/ch9/04e6/01086880-1f2d-4b77-8261-a7ccc0c804e6/FallFuryPart4.mp3" expression="full" duration="1034" fileSize="16551598" type="audio/mp3" medium="audio"></media:content>
        <media:content url="http://media.ch9.ms/ch9/04e6/01086880-1f2d-4b77-8261-a7ccc0c804e6/FallFuryPart4.mp4" expression="full" duration="1034" fileSize="92209073" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/04e6/01086880-1f2d-4b77-8261-a7ccc0c804e6/FallFuryPart4.webm" expression="full" duration="1034" fileSize="37150672" type="video/webm" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/04e6/01086880-1f2d-4b77-8261-a7ccc0c804e6/FallFuryPart4.wma" expression="full" duration="1034" fileSize="8374175" type="audio/x-ms-wma" medium="audio"></media:content>
        <media:content url="http://media.ch9.ms/ch9/04e6/01086880-1f2d-4b77-8261-a7ccc0c804e6/FallFuryPart4.wmv" expression="full" duration="1034" fileSize="38192273" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/04e6/01086880-1f2d-4b77-8261-a7ccc0c804e6/FallFuryPart4_high.mp4" expression="full" duration="1034" fileSize="221254547" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/04e6/01086880-1f2d-4b77-8261-a7ccc0c804e6/FallFuryPart4_mid.mp4" expression="full" duration="1034" fileSize="159353109" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/04e6/01086880-1f2d-4b77-8261-a7ccc0c804e6/FallFuryPart4_Source.wmv" expression="full" duration="1034" fileSize="282571692" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://smooth.ch9.ms/ch9/04e6/01086880-1f2d-4b77-8261-a7ccc0c804e6/FallFuryPart4.ism/manifest" expression="full" duration="1034" fileSize="8446" type="video/x-ms-wmv" medium="video"></media:content>
      </media:group>      
      <enclosure url="http://media.ch9.ms/ch9/04e6/01086880-1f2d-4b77-8261-a7ccc0c804e6/FallFuryPart4.wmv" length="38192273" type="video/x-ms-wmv"></enclosure>
      <dc:creator>Clint Rutkas, Den Delimarsky</dc:creator>
      <itunes:author>Clint Rutkas, Den Delimarsky</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/Series/FallFury/Part-4-XAML-Interop/RSS</wfw:commentRss>
      <category>C#</category>
      <category>C++</category>
      <category>DirectX</category>
      <category>Windows Store App</category>
    </item>
  <item>
      <title>Part 3 - Basic Rendering and Movement </title>
      <description><![CDATA[<p>This video covers the basics of character movement through a variety of controls, such as the accelerometer, keyboard, and mouse. The fundamentals of object rendering through a DirectX implementation of SpriteBatch are also covered.</p><p>Check out the article for this video at <a href="http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-3-Basic-Rendering-and-Movement">http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-3-Basic-Rendering-and-Movement</a></p><p>For the source code, head over to <a href="http://fallfury.codeplex.com/">http://fallfury.codeplex.com</a></p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/DennisDel/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:459cd33f3ba0435bb7aca13f017f02a5">]]></description>
      <comments>http://channel9.msdn.com/Series/FallFury/Part-3-Basic-Rendering-and-Movement</comments>
      <itunes:summary>This video covers the basics of character movement through a variety of controls, such as the accelerometer, keyboard, and mouse. The fundamentals of object rendering through a DirectX implementation of SpriteBatch are also covered. Check out the article for this video at http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-3-Basic-Rendering-and-Movement For the source code, head over to http://fallfury.codeplex.com </itunes:summary>
      <itunes:duration>1510</itunes:duration>
      <link>http://channel9.msdn.com/Series/FallFury/Part-3-Basic-Rendering-and-Movement</link>
      <pubDate>Wed, 23 Jan 2013 23:58:26 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/Series/FallFury/Part-3-Basic-Rendering-and-Movement</guid>
      <media:thumbnail url="http://media.ch9.ms/ch9/f2a1/9afdc0cb-6045-4e66-97d6-89d9297bf2a1/FallFuryPart3_100.jpg" height="56" width="100"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/f2a1/9afdc0cb-6045-4e66-97d6-89d9297bf2a1/FallFuryPart3_220.jpg" height="124" width="220"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/f2a1/9afdc0cb-6045-4e66-97d6-89d9297bf2a1/FallFuryPart3_512.jpg" height="289" width="512"></media:thumbnail>
      <media:group>
        <media:content url="http://media.ch9.ms/ch9/f2a1/9afdc0cb-6045-4e66-97d6-89d9297bf2a1/FallFuryPart3.mp3" expression="full" duration="1510" fileSize="24165578" type="audio/mp3" medium="audio"></media:content>
        <media:content url="http://media.ch9.ms/ch9/f2a1/9afdc0cb-6045-4e66-97d6-89d9297bf2a1/FallFuryPart3.mp4" expression="full" duration="1510" fileSize="122322646" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/f2a1/9afdc0cb-6045-4e66-97d6-89d9297bf2a1/FallFuryPart3.webm" expression="full" duration="1510" fileSize="53095080" type="video/webm" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/f2a1/9afdc0cb-6045-4e66-97d6-89d9297bf2a1/FallFuryPart3.wma" expression="full" duration="1510" fileSize="12225303" type="audio/x-ms-wma" medium="audio"></media:content>
        <media:content url="http://media.ch9.ms/ch9/f2a1/9afdc0cb-6045-4e66-97d6-89d9297bf2a1/FallFuryPart3.wmv" expression="full" duration="1510" fileSize="55214777" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/f2a1/9afdc0cb-6045-4e66-97d6-89d9297bf2a1/FallFuryPart3_high.mp4" expression="full" duration="1510" fileSize="320068921" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/f2a1/9afdc0cb-6045-4e66-97d6-89d9297bf2a1/FallFuryPart3_mid.mp4" expression="full" duration="1510" fileSize="222847275" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/f2a1/9afdc0cb-6045-4e66-97d6-89d9297bf2a1/FallFuryPart3_Source.wmv" expression="full" duration="1510" fileSize="203982548" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://smooth.ch9.ms/ch9/f2a1/9afdc0cb-6045-4e66-97d6-89d9297bf2a1/FallFuryPart3.ism/manifest" expression="full" duration="1510" fileSize="8446" type="video/x-ms-wmv" medium="video"></media:content>
      </media:group>      
      <enclosure url="http://media.ch9.ms/ch9/f2a1/9afdc0cb-6045-4e66-97d6-89d9297bf2a1/FallFuryPart3.wmv" length="55214777" type="video/x-ms-wmv"></enclosure>
      <dc:creator>Clint Rutkas, Den Delimarsky</dc:creator>
      <itunes:author>Clint Rutkas, Den Delimarsky</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/Series/FallFury/Part-3-Basic-Rendering-and-Movement/RSS</wfw:commentRss>
      <category>C#</category>
      <category>C++</category>
      <category>DirectX</category>
      <category>Windows Store App</category>
    </item>
  <item>
      <title>Part 2 - Shaders</title>
      <description><![CDATA[<p>Shaders are the core part of many modern video games. This video covers the fundamentals of the High Level Shader Language as well as its application in creating vertex and pixel shaders for a Windows Store DirectX &amp; XAML hybrid project.</p><p>Check out the article for this video at <a href="http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-2-Shaders">http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-2-Shaders</a></p><p>For the source code, head over to <a href="http://fallfury.codeplex.com/">http://fallfury.codeplex.com</a></p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/DennisDel/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:9ebb176e64b64148a84fa13f017d8cb4">]]></description>
      <comments>http://channel9.msdn.com/Series/FallFury/Part-2-Shaders</comments>
      <itunes:summary>Shaders are the core part of many modern video games. This video covers the fundamentals of the High Level Shader Language as well as its application in creating vertex and pixel shaders for a Windows Store DirectX &amp;amp; XAML hybrid project. Check out the article for this video at http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-2-Shaders For the source code, head over to http://fallfury.codeplex.com </itunes:summary>
      <itunes:duration>1437</itunes:duration>
      <link>http://channel9.msdn.com/Series/FallFury/Part-2-Shaders</link>
      <pubDate>Wed, 23 Jan 2013 23:58:23 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/Series/FallFury/Part-2-Shaders</guid>
      <media:thumbnail url="http://media.ch9.ms/ch9/0419/408466c0-5dee-4616-b76d-3c5e824a0419/FallFuryPart2_100.jpg" height="56" width="100"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/0419/408466c0-5dee-4616-b76d-3c5e824a0419/FallFuryPart2_220.jpg" height="124" width="220"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/0419/408466c0-5dee-4616-b76d-3c5e824a0419/FallFuryPart2_512.jpg" height="289" width="512"></media:thumbnail>
      <media:group>
        <media:content url="http://media.ch9.ms/ch9/0419/408466c0-5dee-4616-b76d-3c5e824a0419/FallFuryPart2.mp3" expression="full" duration="1437" fileSize="22997360" type="audio/mp3" medium="audio"></media:content>
        <media:content url="http://media.ch9.ms/ch9/0419/408466c0-5dee-4616-b76d-3c5e824a0419/FallFuryPart2.mp4" expression="full" duration="1437" fileSize="101812905" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/0419/408466c0-5dee-4616-b76d-3c5e824a0419/FallFuryPart2.webm" expression="full" duration="1437" fileSize="47741682" type="video/webm" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/0419/408466c0-5dee-4616-b76d-3c5e824a0419/FallFuryPart2.wma" expression="full" duration="1437" fileSize="11633515" type="audio/x-ms-wma" medium="audio"></media:content>
        <media:content url="http://media.ch9.ms/ch9/0419/408466c0-5dee-4616-b76d-3c5e824a0419/FallFuryPart2.wmv" expression="full" duration="1437" fileSize="50821979" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/0419/408466c0-5dee-4616-b76d-3c5e824a0419/FallFuryPart2_high.mp4" expression="full" duration="1437" fileSize="319500869" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/0419/408466c0-5dee-4616-b76d-3c5e824a0419/FallFuryPart2_mid.mp4" expression="full" duration="1437" fileSize="187767219" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/0419/408466c0-5dee-4616-b76d-3c5e824a0419/FallFuryPart2_Source.wmv" expression="full" duration="1437" fileSize="154526110" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://smooth.ch9.ms/ch9/0419/408466c0-5dee-4616-b76d-3c5e824a0419/FallFuryPart2.ism/manifest" expression="full" duration="1437" fileSize="8446" type="video/x-ms-wmv" medium="video"></media:content>
      </media:group>      
      <enclosure url="http://media.ch9.ms/ch9/0419/408466c0-5dee-4616-b76d-3c5e824a0419/FallFuryPart2.wmv" length="50821979" type="video/x-ms-wmv"></enclosure>
      <dc:creator>Clint Rutkas, Den Delimarsky</dc:creator>
      <itunes:author>Clint Rutkas, Den Delimarsky</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/Series/FallFury/Part-2-Shaders/RSS</wfw:commentRss>
      <category>C#</category>
      <category>C++</category>
      <category>DirectX</category>
      <category>Windows Store App</category>
    </item>
  <item>
      <title>Part 1 - Introduction</title>
      <description><![CDATA[<p>In this video, Den Delimarsky introduces the FallFury project, describing the basic core and organization as well as the technologies used to create the game.</p><p>Check out the article for this video at <a href="http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-1-Introduction">http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-1-Introduction</a></p><p>For the source code, head over to <a href="http://fallfury.codeplex.com/">http://fallfury.codeplex.com</a></p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/DennisDel/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:8ccb87d7121f45e093b5a14a01336fc9">]]></description>
      <comments>http://channel9.msdn.com/Series/FallFury/Part-1-Introduction</comments>
      <itunes:summary>In this video, Den Delimarsky introduces the FallFury project, describing the basic core and organization as well as the technologies used to create the game. Check out the article for this video at http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-1-Introduction For the source code, head over to http://fallfury.codeplex.com </itunes:summary>
      <itunes:duration>1128</itunes:duration>
      <link>http://channel9.msdn.com/Series/FallFury/Part-1-Introduction</link>
      <pubDate>Wed, 23 Jan 2013 23:58:20 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/Series/FallFury/Part-1-Introduction</guid>
      <media:thumbnail url="http://media.ch9.ms/ch9/46d7/a0462890-d8c4-4c41-9cf5-ec53e9e946d7/FallFuryPart1_100.jpg" height="56" width="100"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/46d7/a0462890-d8c4-4c41-9cf5-ec53e9e946d7/FallFuryPart1_220.jpg" height="124" width="220"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/46d7/a0462890-d8c4-4c41-9cf5-ec53e9e946d7/FallFuryPart1_512.jpg" height="289" width="512"></media:thumbnail>
      <media:group>
        <media:content url="http://media.ch9.ms/ch9/46d7/a0462890-d8c4-4c41-9cf5-ec53e9e946d7/FallFuryPart1.mp3" expression="full" duration="1128" fileSize="18051654" type="audio/mp3" medium="audio"></media:content>
        <media:content url="http://media.ch9.ms/ch9/46d7/a0462890-d8c4-4c41-9cf5-ec53e9e946d7/FallFuryPart1.mp4" expression="full" duration="1128" fileSize="110659455" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/46d7/a0462890-d8c4-4c41-9cf5-ec53e9e946d7/FallFuryPart1.webm" expression="full" duration="1128" fileSize="37583295" type="video/webm" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/46d7/a0462890-d8c4-4c41-9cf5-ec53e9e946d7/FallFuryPart1.wma" expression="full" duration="1128" fileSize="9131183" type="audio/x-ms-wma" medium="audio"></media:content>
        <media:content url="http://media.ch9.ms/ch9/46d7/a0462890-d8c4-4c41-9cf5-ec53e9e946d7/FallFuryPart1.wmv" expression="full" duration="1128" fileSize="45597095" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/46d7/a0462890-d8c4-4c41-9cf5-ec53e9e946d7/FallFuryPart1_high.mp4" expression="full" duration="1128" fileSize="245887608" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/46d7/a0462890-d8c4-4c41-9cf5-ec53e9e946d7/FallFuryPart1_mid.mp4" expression="full" duration="1128" fileSize="172098106" type="video/mp4" medium="video"></media:content>
        <media:content url="http://media.ch9.ms/ch9/46d7/a0462890-d8c4-4c41-9cf5-ec53e9e946d7/FallFuryPart1_Source.wmv" expression="full" duration="1128" fileSize="227481511" type="video/x-ms-wmv" medium="video"></media:content>
        <media:content url="http://smooth.ch9.ms/ch9/46d7/a0462890-d8c4-4c41-9cf5-ec53e9e946d7/FallFuryPart1.ism/manifest" expression="full" duration="1128" fileSize="8446" type="video/x-ms-wmv" medium="video"></media:content>
      </media:group>      
      <enclosure url="http://media.ch9.ms/ch9/46d7/a0462890-d8c4-4c41-9cf5-ec53e9e946d7/FallFuryPart1.wmv" length="45597095" type="video/x-ms-wmv"></enclosure>
      <dc:creator>Clint Rutkas, Den Delimarsky</dc:creator>
      <itunes:author>Clint Rutkas, Den Delimarsky</itunes:author>
      <slash:comments>3</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/Series/FallFury/Part-1-Introduction/RSS</wfw:commentRss>
      <category>C#</category>
      <category>C++</category>
      <category>DirectX</category>
      <category>Windows Store App</category>
    </item>
  <item>
      <title>Fall Fury: Part 12 - Conclusions</title>
      <description><![CDATA[<h3>Project Conclusions</h3><p>Developing FallFury was a fun and educational activity. Besides the fact that I got to work with an amazing team of people who were willing to assist me with the testing and development, I learned some important points about the development process as a whole and have outlined them in this article.&nbsp; Check out the video for this article at <a href="http://channel9.msdn.com/Series/FallFury/Part-12-Project-Conclusion">http://channel9.msdn.com/Series/FallFury/Part-12-Project-Conclusion</a>.&nbsp; For a complete, offline version of this series, you may <a href="http://media.ch9.ms/coding4fun/fallfury/FallFury.pdf">download a nicely formatted PDF of all the articles</a>.</p><h4>Go Outside Your Comfort Zone</h4><p>This past summer, I decided to tackle a new challenge—game development. Never before had I built a game from the ground up. Moreover, as I could already find my way around C# code, I decided that I wanted to make C&#43;&#43; the language of choice, and so worked with DirectX instead of XNA. Additionally, the project needed to be constructed with Windows 8 as the target platform and I’d have to rely on the WinRT stack.</p><p>The concepts were new to me, but I figured that learning about a new platform and a new language would be more interesting than sticking to my comfort zone. Through FallFury I extended my knowledge about pointers, trigonometry, how DirectX handles a lot of the graphics legwork, and how to write HLSL shaders.</p><p>It was a challenging but very rewarding experience.</p><h4>Communicate</h4><p>The most important part of any project is communication. There are always people who know more than you in one field or another, so don't hesitate to reach out to other developers and ask questions. Your code is not perfect, so talk about best practices used in production and how you can improve on what you already have—communication should not be limited to your team, floor, or even building.</p><p>One bonus of my experience at Microsoft was discovering that a lot of developers, when not in a meeting or in the middle of an important assignment, are more than happy to help a fellow employee with a piece of advice or some code review.</p><h4>Plan the Small Details</h4><p>Before you even touch the keyboard to write your first line of code, outline the components of your application and have a general idea of how you’ll implement those components as well as how they’ll interact with each other. It is tempting to start coding and then add or modify features, but doing so will create more problems than it will solve.</p><h4>Build Small Prototypes</h4><p>FallFury is a complex project composed out of blocks such as:</p><ul><li>XML level/metadata reader and writer </li><li>The Share and Settings charm components </li><li>SpriteBatch sub-system </li><li>Level renderer </li><li>Screen sub-system </li><li>Menu interaction sub-system </li></ul><p>Each block is responsible for its own set of tasks and each can be individually tested with either mocked data or a loose connection to the existing codebase. The necessity for small prototypes comes from individual requirements tied to the platform and possible integration scenarios. For example, when I began development, I created a non-hybrid DirectX project, which meant that if I needed to introduce XAML integration, I had to rewrite small parts of my swap chain preparation stack as well as work with a lot of XAML content in the code-behind. The Settings charm integration heavily relied on XAML, and I would have had to write the popup and control-related code in C#.</p><p>Obviously, that was not an option, so I created a hybrid project instead and ported most of my code into the new solution. Lesson learned here: prototype—and prototype early—in order to make sure that what you plan to implement will be implemented in an efficient manner.</p><h4>Test Often, Test with Other People</h4><p>When working on an application, it is important to understand the needs and expectations of your target audience, and a big part of this is making sure that the application provides a way for the user to easily learn about an action without a helper booklet. The menu system is a good example of this in FallFury. As I was designing the buttons on my screens, I tried to implement the approach used in games such as Dance Central—the user simply slides the button-panel and it takes him to the screen that was linked to that specific button. However, as I was testing the application with the local development crowd, I noticed a pattern—people were attempting to simply tap the button instead of sliding it. To avoid this confusion, I added a pulsating arrow on the right side of the button in order to highlight the fact that the button should be displaced in order to be activated.</p><p>The XML level loading system is another example of how secondary testing improved FallFury. Initial element positioning relied on a given level length, as well as on a ration-based placement. For example, if I wanted to put a button in the middle of the screen, I could position it with a value, such as .5. The level loader would then translate this value relative to the screen size. Rick Barraza was creating some test levels when he notified me about a big flaw—as the level extended, some elements were mis-positioned by a large margin compared to the original intended location. This was because when a level length was reset, the ratio was applied on a larger/smaller value, and some elements would therefore overlap. Ultimately, I rewrote the level structure to rely on pixel values, and designed the level-length to calculate automatically based on the included elements and their size.</p><h4>Test on Different Hardware</h4><p>FallFury started with portable hardware in mind. Its original design targeted Windows 8 tablet devices, though it was later decided that the project should support desktop machines as well. That automatically added thousands of possible hardware combinations on which the game might potentially run. Here are just some of the test machines we got to use:</p><ul><li>Samsung Series 7 Slate </li><li>ARM Developer Tablet (Microsoft Surface) </li><li><a href="http://www.asus.com/Eee/Eee_Pad/Eee_Slate_EP121/">ASUS EP121 Slate</a> </li></ul><p>Each of these machines came with its own specific conditions that had to be accommodated. While Samsung Series 7 Slate featured an accelerometer, at the time of development the ASUS EP121 tablet did not have Windows 8 drivers for its sensor. When I sideloaded the game, I noticed that I could no longer control the character the way I wanted to. Also, though FallFury has keyboard controls, I had to develop controls for machines without keyboards. This is why I came up with the concept of touch-based, on-screen controls.</p><p>Moving on to the ARM device, first and foremost I noticed that my shader configurations were not compatible with the platform capabilities. All my testing was done on a machine that supported DirectX Feature Level 10, which was not the case for a low-power ARM machine that supports DirectX Feature Level 9.1. I had to work with some MSDN samples to find a way to properly modify the required shaders so they would work on Windows RT. ARM devices are built with battery life in mind. Therefore, their capabilities are reduced compared to those of a full-sized Windows tablet. This had an impact on the general game performance—some parts of the game, such as particle rendering, were working fine on a desktop machine, but were quite laggy on the ARM tablet. Knowing the possible source of the problem, I had to optimize the particle storage and rendering stack to ensure they didn’t affect the user experience on Windows RT hardware.</p><h4>There Is Never Enough Time - Learn To Cut</h4><p>When I started planning FallFury, I worked up a huge list of features. As the deadline approached, however, I noticed that I somewhat underestimated the allocated project time—a lot of time was spent on testing and eliminating bugs in existing features. That was the point at which I had to cut my feature set.</p><p>When designing the feature list for your app, make sure that you have a clear vision of which features get the priority and which can be cut if necessary. For example, FallFury was originally planned to be a multiplayer game. Although it was tempting to start working on it as such from the very beginning, I knew that it wasn’t a core feature and that it wouldn’t necessarily affect the general play experience on release day. Ultimately, multiplayer capability was dropped from initial development along with a number of other not-immediately-integral features.</p><h4>Expect the Unexpected</h4><p>When allocating time for the project, anticipate situations that might derail the process and cause a delay in the planned delivery date. It is easy to estimate that creating an accelerometer-based motion system will take you a day or two, but you also need to allow for the potential possibility of your code not working as expected, hardware accidents, natural disasters, etc. Doing so will help you focus on the right features at the right time while diminishing the risk of missing the deadline.</p><h4>Platform Samples Are the Best Documentation - Learn to Read Others’ Code</h4><p>While building the core of FallFury, I leveraged multiple features that hadn’t yet become mainstream among Windows developers. Therefore, the documentation was scarce and in some instances the only help I could get was internal. Luckily, Microsoft bundled hundreds of samples that demonstrate what the new platform can do. A lot of the development approaches gained during my internship were learned from looking at the official, publicly released sample code. The lesson here: if it's not on MSDN or blogs, check the official developer samples. For example, I used the <a href="http://code.msdn.microsoft.com/windowsapps/Direct3D-sprite-sample-97ae6262">DirectX sprite drawing sample</a> to see how to build a proper sprite rendering mechanism with behavior similar to the one available in XNA.</p><h4>Atomic Commits</h4><p>When I started, source control wasn’t new to me, but there were proper usage practices that I didn’t apply before the internship. One of them is atomic commits, which I learned from <a href="https://twitter.com/ClintRutkas">Clint Rutkas</a>.</p><p>With every new addition to the application, chances are something might go wrong. It could be a faulty third-party assembly, a misplaced class, or a broken reference that brings down the entire solution. If the commits include longer time intervals, for example, you will ultimately have to roll back to a build without a lot of the new functionality. Using atomic commits, however, you’ll be able to avoid unnecessary, redundant work in the case that something goes wrong during development.</p><h4>A Non-standard Approach Is Not Necessarily a Bad Approach</h4><p>For loading high scores, I needed the UI layout to display the registered items. To do so, I had could either use data binding or write a simple routine that would generate XAML items on the fly in the code-behind. Data binding is a pretty common practice among XAML developers, so my initial thought was to use that, but I would have had to create a C&#43;&#43; binding harness in addition to the existing data retrieval code. The second approach was much cleaner because it didn’t require me to rewrite or add much code. The lesson here: pick the best approach for the job and don’t blindly follow programming trends.</p><h4>Focus on the User Experience</h4><p>At the end of the day, the user doesn’t care whether you wrote the application in native DirectX or XNA, whether you applied the MVVM pattern, or whether you have easily readable code. The user cares about having a great time while playing the game, regardless of its backbone. It’s your goal as a developer to deliver that user experience and ensure that the user feels comfortable with the product. This means that the development cycle goes beyond simply writing code. In FallFury, levels are dynamic, which means the source code doesn’t necessarily need to be modified in order to create a different playable experience. But that experience matters in any case, and level design is a huge part of FallFury’s final product. Users need to be immersed in the game world, so levels must be planned in such as way that the user returns to the game and doesn’t abandon it after a couple of lost rounds.</p><h4>Conclusion</h4><p>FallFury was my first major project that I wrote almost entirely in C&#43;&#43;, targeting the newly released Windows 8 operating system. Although the development process was challenging, it was proven to be a great educational experience that taught me about the approaches and practices that are used internally at Microsoft.</p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/DennisDel/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:cf5ded925e574af79c1fa14d01624d0b">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-12-Conclusions</comments>
      <itunes:summary>Project ConclusionsDeveloping FallFury was a fun and educational activity. Besides the fact that I got to work with an amazing team of people who were willing to assist me with the testing and development, I learned some important points about the development process as a whole and have outlined them in this article.&amp;nbsp; Check out the video for this article at http://channel9.msdn.com/Series/FallFury/Part-12-Project-Conclusion.&amp;nbsp; For a complete, offline version of this series, you may download a nicely formatted PDF of all the articles. Go Outside Your Comfort ZoneThis past summer, I decided to tackle a new challenge—game development. Never before had I built a game from the ground up. Moreover, as I could already find my way around C# code, I decided that I wanted to make C&amp;#43;&amp;#43; the language of choice, and so worked with DirectX instead of XNA. Additionally, the project needed to be constructed with Windows 8 as the target platform and I’d have to rely on the WinRT stack. The concepts were new to me, but I figured that learning about a new platform and a new language would be more interesting than sticking to my comfort zone. Through FallFury I extended my knowledge about pointers, trigonometry, how DirectX handles a lot of the graphics legwork, and how to write HLSL shaders. It was a challenging but very rewarding experience. CommunicateThe most important part of any project is communication. There are always people who know more than you in one field or another, so don&#39;t hesitate to reach out to other developers and ask questions. Your code is not perfect, so talk about best practices used in production and how you can improve on what you already have—communication should not be limited to your team, floor, or even building. One bonus of my experience at Microsoft was discovering that a lot of developers, when not in a meeting or in the middle of an important assignment, are more than happy to help a fellow employee with a piece of advice or some code </itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-12-Conclusions</link>
      <pubDate>Wed, 23 Jan 2013 23:57:48 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-12-Conclusions</guid>
      <media:thumbnail url="http://media.ch9.ms/ch9/f8eb/37473ed7-1ccd-4afc-834d-d99ae5b2f8eb/FallFuryPart12_100.jpg" height="56" width="100"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/f8eb/37473ed7-1ccd-4afc-834d-d99ae5b2f8eb/FallFuryPart12_220.jpg" height="124" width="220"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/f8eb/37473ed7-1ccd-4afc-834d-d99ae5b2f8eb/FallFuryPart12_512.jpg" height="289" width="512"></media:thumbnail>      
      <dc:creator>Brian Peek, Clint Rutkas, Dan Fernandez, Den Delimarsky, Rick Barraza</dc:creator>
      <itunes:author>Brian Peek, Clint Rutkas, Dan Fernandez, Den Delimarsky, Rick Barraza</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-12-Conclusions/RSS</wfw:commentRss>
      <category>C#</category>
      <category>C++</category>
      <category>Windows Store App</category>
    </item>
  <item>
      <title>Fall Fury: Part 11 - Hardware Testing &amp; Debugging</title>
      <description><![CDATA[<h3>Hardware Testing &amp; Debugging</h3><p>As previously mentioned, FallFury runs on multiple types of hardware as long as that hardware supports Windows 8. This article describes the project’s general testing and debugging process, including setting the debug configurations and remote debugging.</p><p>Check out the video for this article at <a href="http://channel9.msdn.com/Series/FallFury/Part-11-Hardware-Testing">http://channel9.msdn.com/Series/FallFury/Part-11-Hardware-Testing</a>.&nbsp; For a complete, offline version of this series, you may <a href="http://media.ch9.ms/coding4fun/fallfury/FallFury.pdf">download a nicely formatted PDF of all the articles</a>.</p><h4>Remote Debug</h4><p>When working on an application that targets different machines, it’s probably out of the question to install Visual Studio on each instance and move the solution from one source to another in order to run it and diagnose potential problems. Here is where <a href="http://www.microsoft.com/en-us/download/details.aspx?id=30674">Remote Tools for Visual Studio 2012</a> come into play. Microsoft offers you three separate builds—tools for x86 systems, x64 systems, and ARM systems—also known as Surface RT.</p><p>Once the tools are running on the machine you want to debug, you have two choices. You can either install the remote debugger as a service, allowing it to constantly run in the background, or you can use the debugger on a per-launch basis. From a developer perspective, the choice doesn’t affect how your application is executed on the remote machine. From a security perspective, however, you need to be sure that you properly configure it so that no unwanted apps are remotely deployed.</p><p>Now you can start the Remote Debugger Configuration Wizard:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image002%5B3%5D-8.jpg"><img title="clip_image002" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image002_thumb-9.jpg" alt="clip_image002" width="372" height="312" border="0"></a> <a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image004%5B3%5D-6.jpg"><img title="clip_image004" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image004_thumb-7.jpg" alt="clip_image004" width="333" height="312" border="0"></a></p><p>This works on both the initial start-up and also any subsequent launch as a way to easily and quickly set the necessary remote debugger settings. Specifically, it is useful to configure the machine’s network settings, allowing cross-domain communications for debugging purposes.</p><p>Once the wizard is completed, launch the Remote Debugger Monitor. Notice that it lists your machine name and the port on which it’s running. This is necessary for configuring the project to send the package to a remote machine instead of the local one:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image006%5B3%5D-4.jpg"><img title="clip_image006" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image006_thumb-5.jpg" alt="clip_image006" width="501" height="167" border="0"></a></p><p>The configuration depends on the network settings on both the local machine and the subnet as a whole. For example, in some cases, and especially on domain-joined machines, remote debugging is better done with the authentication disabled. Windows Authentication is used by default.</p><p>Since FallFury is a C&#43;&#43; project, the configuration for a remote session is different than, say, that of a C# Windows Store application. To configure the session, right click on the project in <strong>Solution Explorer</strong> and open the <strong>Debugging</strong> section. Make sure that Remote Machine is selected as the type of debugger to launch:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image008%5B3%5D-5.jpg"><img title="clip_image008" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image008_thumb-6.jpg" alt="clip_image008" width="640" height="142" border="0"></a></p><p>Next, specify the machine name as well as whether the current session will require authentication:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image010%5B3%5D-3.jpg"><img title="clip_image010" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image010_thumb-4.jpg" alt="clip_image010" width="640" height="196" border="0"></a></p><p>If you cannot specify the machine name, use the direct IPv4 address of that computer, minus the port <a>(unless you’ve explicitly set it to a port other than 4016, which is the assumed default).</a> Once the source machine connects to the remote one, you will see Visual Studio performing the deployment:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image012%5B3%5D-5.jpg"><img title="clip_image012" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image012_thumb-5.jpg" alt="clip_image012" width="640" height="108" border="0"></a></p><h4>Configurations</h4><p>As a matter of convenience, it is always good to have different debug configurations that will define how your projects are built, especially if the project targets multiple platforms (such as ARM and x86). Visual Studio provides a <a href="http://msdn.microsoft.com/en-us/library/kwybya3w%28v=vs.80%29.aspx">Configuration Manager</a> that can be accessed from the debug target dropdown:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image013%5B3%5D.png"><img title="clip_image013" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image013_thumb.png" alt="clip_image013" width="300" height="199" border="0"></a></p><p>FallFury includes two separate projects—the game core, and the C#-based XML reader. Both need to be explicitly associated with separate target platforms in order to be correctly debugged. For that, profiles were created for both local and remote sessions:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image014%5B3%5D.png"><img title="clip_image014" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image014_thumb.png" alt="clip_image014" width="640" height="186" border="0"></a></p><p>As with standard Debug/Release configurations, the ones shown above determine whether the project will carry debug symbols and support debugging commands. It is important to mention that as you switch configurations, you must be careful how you configure the graphic shaders. For each shader in the container folder, explicitly set the HLSL shader type and model. Otherwise the application deployment will fail:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image016%5B3%5D-3.jpg"><img title="clip_image016" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image016_thumb-4.jpg" alt="clip_image016" width="640" height="144" border="0"></a></p><h4>Remote Profiling</h4><p>Last but not least, when working with different hardware configurations it might be useful to perform application profiling or performance review. Fortunately, Visual Studio also provides this capability through the <a href="http://msdn.microsoft.com/en-us/library/hh977161.aspx"><strong>vsperf</strong></a> tool, which is already integrated in the IDE if you are using Visual Studio 2012 Professional or above.</p><p>To initiate a profiling session on a remote device, the Remote Debugger Monitor must be active. Make sure that the <strong>Remote Machine</strong> debug target is selected, and go to <strong>Analyze &gt; Start Performance Analysis</strong>:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image017%5B3%5D.png"><img title="clip_image017" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image017_thumb.png" alt="clip_image017" width="404" height="83" border="0"></a></p><p>On the remote machine, allow the <strong>vsperf</strong> process to run with administrative privileges. Once the profiling session completes and the data is analyzed, you can review the same performance indicators as you would when having a standard application run the profiler on the local machine:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image019%5B3%5D.jpg"><img title="clip_image019" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image019_thumb.jpg" alt="clip_image019" width="640" height="312" border="0"></a></p><h4>Conclusion</h4><p>Testing hardware outside the boundaries of a desktop machine is often a necessity, especially if the application relies on specific sensors, such as NFC, touch, or accelerometer. The remote debugging process is fairly streamlined and intuitive, with developing a proper network configuration allowing communication between machines requiring the most significant amount of effort. If you have problems getting the debugger to work, <a href="http://msdn.microsoft.com/en-us/library/bt727f1t.aspx">consult this article on MSDN</a>.</p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/DennisDel/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:4e4e6ed2c2cc4a98946aa14d0161797b">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-11-Hardware-Testing--Debugging</comments>
      <itunes:summary>Hardware Testing &amp;amp; DebuggingAs previously mentioned, FallFury runs on multiple types of hardware as long as that hardware supports Windows 8. This article describes the project’s general testing and debugging process, including setting the debug configurations and remote debugging. Check out the video for this article at http://channel9.msdn.com/Series/FallFury/Part-11-Hardware-Testing.&amp;nbsp; For a complete, offline version of this series, you may download a nicely formatted PDF of all the articles. Remote DebugWhen working on an application that targets different machines, it’s probably out of the question to install Visual Studio on each instance and move the solution from one source to another in order to run it and diagnose potential problems. Here is where Remote Tools for Visual Studio 2012 come into play. Microsoft offers you three separate builds—tools for x86 systems, x64 systems, and ARM systems—also known as Surface RT. Once the tools are running on the machine you want to debug, you have two choices. You can either install the remote debugger as a service, allowing it to constantly run in the background, or you can use the debugger on a per-launch basis. From a developer perspective, the choice doesn’t affect how your application is executed on the remote machine. From a security perspective, however, you need to be sure that you properly configure it so that no unwanted apps are remotely deployed. Now you can start the Remote Debugger Configuration Wizard:   This works on both the initial start-up and also any subsequent launch as a way to easily and quickly set the necessary remote debugger settings. Specifically, it is useful to configure the machine’s network settings, allowing cross-domain communications for debugging purposes. Once the wizard is completed, launch the Remote Debugger Monitor. Notice that it lists your machine name and the port on which it’s running. This is necessary for configuring the project to send the package to a remote ma</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-11-Hardware-Testing--Debugging</link>
      <pubDate>Wed, 23 Jan 2013 23:57:44 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-11-Hardware-Testing--Debugging</guid>
      <media:thumbnail url="http://media.ch9.ms/ch9/d2bf/2dea3e0d-559c-4efb-ae2d-a2c49c20d2bf/FallFuryPart11_100.jpg" height="56" width="100"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/d2bf/2dea3e0d-559c-4efb-ae2d-a2c49c20d2bf/FallFuryPart11_220.jpg" height="124" width="220"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/d2bf/2dea3e0d-559c-4efb-ae2d-a2c49c20d2bf/FallFuryPart11_512.jpg" height="289" width="512"></media:thumbnail>      
      <dc:creator>Brian Peek, Clint Rutkas, Dan Fernandez, Den Delimarsky, Rick Barraza</dc:creator>
      <itunes:author>Brian Peek, Clint Rutkas, Dan Fernandez, Den Delimarsky, Rick Barraza</itunes:author>
      <slash:comments>3</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-11-Hardware-Testing--Debugging/RSS</wfw:commentRss>
      <category>C#</category>
      <category>C++</category>
      <category>DirectX</category>
      <category>Windows Store App</category>
    </item>
  <item>
      <title>Fall Fury: Part 10 - Charms</title>
      <description><![CDATA[<h3>Charms</h3><p>With the release of the Windows 8 operating system, applications are now able to easily integrate with each other and have a unified way to control their workflow through unique <a href="http://msdn.microsoft.com/en-us/library/windows/apps/hh464906.aspx">system-wide contracts</a> called <a href="http://blogs.msdn.com/b/going_metro/archive/2012/04/22/integrating-with-windows-8-charms-amp-contracts.aspx">Charms</a>. Out of the multitude of available options, FallFury leverages two charms—Share contract and Settings. This article describes how the integration is implemented.</p><p>Check out the video for this article at <a href="http://channel9.msdn.com/Series/FallFury/Part-10-Charms">http://channel9.msdn.com/Series/FallFury/Part-10-Charms</a>&nbsp;.&nbsp; For a complete, offline version of this series, you may <a href="http://media.ch9.ms/coding4fun/fallfury/FallFury.pdf">download a nicely formatted PDF of all the articles</a>.</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image002%5B3%5D-7.jpg"><img title="clip_image002" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image002_thumb-8.jpg" alt="clip_image002" width="640" height="362" border="0"></a></p><h4>The Share Contract</h4><p>When a user achieves a specific score in the game, he might decide to share it with his social circle. In Charms, that’s the purpose of the Share contract, which integrates directly with the OS.</p><p>Windows Store applications have the capability to expose their sharing capabilities and register as <a href="http://code.msdn.microsoft.com/windowsapps/Sharing-Content-Target-App-e2689782">a share target</a>. For example, if there is a Twitter client out, it can register itself as an app through which content can be shared. FallFury, on the other hand, acts as a consumer that aggregates existing share targets and lets the user pick the one through which he wants to let the message out:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image004%5B3%5D-5.jpg"><img title="clip_image004" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image004_thumb-6.jpg" alt="clip_image004" width="640" height="192" border="0"></a></p><p>Let’s take a look at how this process is built in the code-behind. The core is located in <strong>DirectXPage.xaml.cpp</strong>—the class responsible for XAML content manipulation in FallFury. First and foremost, you need to get the current instance of the <a href="http://msdn.microsoft.com/en-us/library/windows/apps/windows.applicationmodel.datatransfer.datatransfermanager">DataTransferManager</a> class:</p><p><pre class="brush: cpp">
auto dataTransferManager = Windows::ApplicationModel::DataTransfer::DataTransferManager::GetForCurrentView();
</pre></p><p>Consider this a proxy that allows you to pass content between your app and other Windows Store apps that are executed in the context of the same sandbox. As the instance is obtained, hook it to the <strong>DataRequested</strong> event handler that will handle the scenario where the user invoked the sharing capability:</p><p><pre class="brush: cpp">
dataTransferManager-&gt;DataRequested &#43;= ref new 
    TypedEventHandler&lt;Windows::ApplicationModel::DataTransfer::DataTransferManager^,
    Windows::ApplicationModel::DataTransfer::DataRequestedEventArgs^&gt;(this, &amp;DirectXPage::OnShareDataRequested);
</pre></p><p>&nbsp;</p><p>In the <strong>OnShareDataRequested</strong>, specify the information that goes into the sharing popup:</p><p><pre class="brush: cpp">
void DirectXPage::OnShareDataRequested(Windows::ApplicationModel::DataTransfer::DataTransferManager^ manager,Windows::ApplicationModel::DataTransfer::DataRequestedEventArgs^ params)
{
    auto request = params-&gt;Request;
    request-&gt;Data-&gt;Properties-&gt;Title = &quot;Share Score&quot;;
    request-&gt;Data-&gt;Properties-&gt;Description = &quot;Tell your friends how much you scored in [DEN'S PROJECT]!&quot;;
    request-&gt;Data-&gt;SetText(&quot;I just scored &quot; &#43; StaticDataHelper::Score.ToString() &#43; &quot; in [DEN'S PROJECT]! Beat me! http://dennisdel.com&quot;);
}
</pre></p><p>&nbsp;</p><p>From that point, the control is in the user’s hand. The application cannot force the share, so unless you implement a direct API hook to a social service, the Share charm will only expose the endpoints available for sharing and will let you set the shareable content. You also don’t have to worry about the way the content will be shared—that will be handled by the target application:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image006%5B3%5D-3.jpg"><img title="clip_image006" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image006_thumb-4.jpg" alt="clip_image006" width="571" height="411" border="0"></a></p><p>You can show the popup triggered by the Share charm from your application without having the user open the Charms Bar. To do this, call the <a href="http://msdn.microsoft.com/en-us/library/windows/apps/windows.applicationmodel.datatransfer.datatransfermanager.showshareui">ShowShareUI</a> method:</p><p><pre class="brush: cpp">
void DirectXPage::ShareTopScore_Selected(MenuItem^ sender, Platform::String^ params)
{
    Windows::ApplicationModel::DataTransfer::DataTransferManager::ShowShareUI();
}
</pre></p><p>&nbsp;</p><p>This is exactly what the Share button does in the screenshot above. You should make this behavior predictable.</p><h4>The Settings Charm</h4><p>As you just saw, integrating basic sharing capabilities in FallFury is not too complicated. Working with settings is also a fairly easy task, though it involves some XAML work. While with sharing capabilities the work focused mostly on OS-based endpoints and application-specific popups, settings allow for full control over how they’re displayed.</p><p>For all Windows Store applications, settings should be handled via the Settings charm and not through dedicated application screens. Consider which settings that directly affect the user experience might be changed in FallFury:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image008%5B3%5D-4.jpg"><img title="clip_image008" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image008_thumb-5.jpg" alt="clip_image008" width="506" height="230" border="0"></a></p><ul><li><strong>Music and SFX</strong> – the user can enable or disable music and sound effects, as well as control their volume. </li><li><strong>Accelerometer</strong> – depending on personal preferences, the user might decide to disable the accelerometer (it is enabled by default). The accelerometer can also be inverted—if the device is tilted to the right, the character will move to the left and vice-versa. Last but not least, even with dynamic screen rotation enabled on the device, the user can disable that rotation on the application level and lock the screen to one orientation, such as portrait or landscape. </li><li><strong>Character Movement</strong> – the character can be easily controlled via touch (swipe) or mouse. This behavior is enabled by default, but if the user decides to only use the mouse to direct shells, he can easily disable this feature here. </li></ul><p>As seen in the image above, the operating system provides the basic shell used to list the possible settings. Once one option is selected, however, further UI displays are delegated to the developer.</p><p>As with the share UI, the settings UI can be shown to the user from the application and not from the Charms Bar. Here is how to do this:</p><p><pre class="brush: cpp">
void DirectXPage::Settings_Selected(MenuItem^ sender, Platform::String^ params)
{
    SettingsPane::GetForCurrentView()-&gt;Show();
}
</pre></p><p>&nbsp;</p><p><a href="http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.applicationsettings.settingspane">SettingsPane</a> is the core class that handles the settings display. It does not control how settings are stored or activated. When the main page loads, you need to make sure that you hook the current <strong>SettingsPane</strong> to a <strong>CommandRequested</strong> event handler. It will be triggered when the Settings capability is invoked:</p><p><pre class="brush: cpp">
SettingsPane::GetForCurrentView()-&gt;CommandsRequested &#43;= ref new TypedEventHandler&lt;SettingsPane^, SettingsPaneCommandsRequestedEventArgs^&gt;(this, &amp;DirectXPage::OnSettingsRequested);
</pre></p><p><strong>OnSettingsRequested</strong> is the function where the core setting selections are defined and hooked to their own event handlers:</p><p><pre class="brush: cpp">
void DirectXPage::OnSettingsRequested(Windows::UI::ApplicationSettings::SettingsPane^ settingsPane, Windows::UI::ApplicationSettings::SettingsPaneCommandsRequestedEventArgs^ eventArgs)
{
    if (m_renderer-&gt;CurrentGameState == GameState::GS_PLAYING)
            StaticDataHelper::IsPaused = true;
    
    UICommandInvokedHandler^ handler = ref new UICommandInvokedHandler(this, &amp;DirectXPage::OnSettingsSelected);
    
        SettingsCommand^ generalCommand = ref new SettingsCommand(&quot;musicSfx&quot;, &quot;Music &amp; SFX&quot;, handler);
        eventArgs-&gt;Request-&gt;ApplicationCommands-&gt;Append(generalCommand);
    
    SettingsCommand^ accelerometerCommand = ref new SettingsCommand(&quot;accelerometer&quot;, &quot;Accelerometer&quot;, handler);
    eventArgs-&gt;Request-&gt;ApplicationCommands-&gt;Append(accelerometerCommand);
    
    SettingsCommand^ charMovementCommand = ref new SettingsCommand(&quot;charMovement&quot;, &quot;Character Movement&quot;, handler);
    eventArgs-&gt;Request-&gt;ApplicationCommands-&gt;Append(charMovementCommand);
}
</pre></p><p>Each <a href="http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.applicationsettings.settingscommand">SettingsCommand</a> is an item in the list displayed in the settings pane. When one is selected, <strong>OnSettingsSelected</strong> is called:</p><p><pre class="brush: cpp">
void DirectXPage::OnSettingsSelected(Windows::UI::Popups::IUICommand^ command)
{
    if (command-&gt;Id-&gt;ToString() == &quot;musicSfx&quot;)
    {
        stkMusicSfx-&gt;Width = 346.0f;
        grdSubMusicSfx-&gt;Height = m_renderer-&gt;m_renderTargetSize.Height;
        stkMusicSfx-&gt;IsOpen = true;
    }
    else if (command-&gt;Id-&gt;ToString() == &quot;accelerometer&quot;)
    {
        stkAccelerometerSettings-&gt;Width = 346.0f;
        grdAccelerometerSettings-&gt;Height = m_renderer-&gt;m_renderTargetSize.Height;
        stkAccelerometerSettings-&gt;IsOpen = true;
    }
    else if (command-&gt;Id-&gt;ToString() == &quot;charMovement&quot;)
    {
        stkCharacterMovement-&gt;Width = 346.0f;
        grdCharacterMovement-&gt;Height = m_renderer-&gt;m_renderTargetSize.Height;
        stkCharacterMovement-&gt;IsOpen = true;
    }

    WindowActivationToken = Window::Current-&gt;Activated &#43;= ref new WindowActivatedEventHandler(this, &amp;DirectXPage::OnWindowActivated);
}
</pre></p><p>Looking back at <strong>OnSettingsRequested</strong>, each command has a string identifier. When a command is invoked, that string identifier is returned through the <a href="http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.popups.iuicommand">IUICommand</a> instance in the <a href="http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.popups.iuicommand.id">Id</a> property. Based on that, I decided which popups to open. Since each has a similar structure, I am going to cover the implementation of just one—<strong>Music &amp; SFX</strong>.</p><p>Here is what the end result looks like:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image010%5B3%5D-2.jpg"><img title="clip_image010" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image010_thumb-3.jpg" alt="clip_image010" width="640" height="461" border="0"></a></p><p>The panel on the left is a <a href="http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.controls.primitives.popup">Popup</a>, with two <a href="http://msdn.microsoft.com/en-us/library/windows/apps/xaml/windows.ui.xaml.controls.primitives.togglebutton">ToggleButton</a> controls used to enable or disable generic music and sound effects. There are also two <a href="http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.controls.slider">Slider</a> controls that are used to adjust the volume. The XAML for the above layout looks like this:</p><p><pre class="brush: xml">
&lt;Popup HorizontalAlignment=&quot;Right&quot; IsLightDismissEnabled=&quot;True&quot; x:Name=&quot;stkMusicSfx&quot; &gt;
    &lt;Grid Background=&quot;Black&quot; x:Name=&quot;grdSubMusicSfx&quot;  Width=&quot;346&quot;&gt;
        &lt;Grid.Transitions&gt;
            &lt;TransitionCollection&gt;
                &lt;RepositionThemeTransition /&gt;
            &lt;/TransitionCollection&gt;
        &lt;/Grid.Transitions&gt;

        &lt;Grid.RowDefinitions&gt;
            &lt;RowDefinition Height=&quot;120&quot;&gt;&lt;/RowDefinition&gt;
            &lt;RowDefinition Height=&quot;*&quot;&gt;&lt;/RowDefinition&gt;
        &lt;/Grid.RowDefinitions&gt;

        &lt;StackPanel Grid.Row=&quot;0&quot; Orientation=&quot;Horizontal&quot; Margin=&quot;24,12,0,0&quot; &gt;
            &lt;Button Margin=&quot;0&quot; VerticalAlignment=&quot;Center&quot; x:Name=&quot;dismissAudioSettings&quot; Click=&quot;dismissAudioSettings_Click&quot; Style=&quot;{StaticResource BackButtonStyle}&quot;&gt;&lt;/Button&gt;
            &lt;TextBlock Margin=&quot;12,0,0,12&quot; Height=&quot;Auto&quot; VerticalAlignment=&quot;Center&quot; Text=&quot;Music &amp;amp; SFX&quot; Style=&quot;{StaticResource SubheaderTextStyle}&quot;&gt;&lt;/TextBlock&gt;
        &lt;/StackPanel&gt;

        &lt;StackPanel Grid.Row=&quot;1&quot; Margin=&quot;24,24,0,0&quot;&gt;
            &lt;StackPanel&gt;
                &lt;TextBlock Text=&quot;Music&quot; Style=&quot;{StaticResource BodyTextStyle}&quot;&gt;&lt;/TextBlock&gt;
                &lt;TextBlock  Width=&quot;346&quot; Text=&quot;This includes the theme track and level background music.&quot; Style=&quot;{StaticResource CaptionTextStyle}&quot; TextWrapping=&quot;Wrap&quot; Margin=&quot;0,12,12,12&quot; &gt;&lt;/TextBlock&gt;
                &lt;ToggleSwitch x:Name=&quot;tglMusic&quot; Toggled=&quot;tglMusic_Toggled&quot; IsOn=&quot;{Binding ElementName=XAMLPage,Path=MusicEnabled}&quot; Margin=&quot;-6,0,0,0&quot;&gt;&lt;/ToggleSwitch&gt;
            &lt;/StackPanel&gt;

            &lt;StackPanel Margin=&quot;0,24,0,0&quot;&gt;
                &lt;TextBlock Text=&quot;Music Volume&quot; Style=&quot;{StaticResource BodyTextStyle}&quot;&gt;&lt;/TextBlock&gt;
                &lt;Slider x:Name=&quot;sldMusicVolume&quot; ValueChanged=&quot;sldMusicVolume_ValueChanged&quot; Value=&quot;{Binding ElementName=XAMLPage,Path=MusicVolume, Mode=TwoWay}&quot; Minimum=&quot;0&quot; Maximum=&quot;100&quot; Margin=&quot;0,0,12,0&quot;&gt;&lt;/Slider&gt;
            &lt;/StackPanel&gt;

            &lt;StackPanel Margin=&quot;0,24,0,0&quot;&gt;
                &lt;TextBlock Text=&quot;Sound Effects&quot; Style=&quot;{StaticResource BodyTextStyle}&quot;&gt;&lt;/TextBlock&gt;
                &lt;TextBlock Width=&quot;346&quot; Text=&quot;Includes sounds played during the game (e.g. explosions).&quot; Style=&quot;{StaticResource CaptionTextStyle}&quot; TextWrapping=&quot;Wrap&quot; Margin=&quot;0,12,12,12&quot; &gt;&lt;/TextBlock&gt;
                &lt;ToggleSwitch x:Name=&quot;tglSFX&quot; Toggled=&quot;tglSFX_Toggled&quot; IsOn=&quot;{Binding ElementName=XAMLPage,Path=SFXEnabled}&quot; Margin=&quot;-6,0,0,0&quot;&gt;&lt;/ToggleSwitch&gt;
            &lt;/StackPanel&gt;

            &lt;StackPanel Margin=&quot;0,24,0,0&quot;&gt;
                &lt;TextBlock Text=&quot;SFX Volume&quot; Style=&quot;{StaticResource BodyTextStyle}&quot;&gt;&lt;/TextBlock&gt;
                &lt;Slider x:Name=&quot;sldSFXVolume&quot; ValueChanged=&quot;sldSFXVolume_ValueChanged&quot; Value=&quot;{Binding ElementName=XAMLPage,Path=SFXVolume, Mode=TwoWay}&quot; Minimum=&quot;0&quot; Maximum=&quot;100&quot; Margin=&quot;0,0,12,0&quot;&gt;&lt;/Slider&gt;
            &lt;/StackPanel&gt;

        &lt;/StackPanel&gt;

    &lt;/Grid&gt;
&lt;/Popup&gt;
</pre></p><p>For every Popup instance used for settings, make sure that <strong>IsLightDismissEnabled</strong> is set to true. This allows the user to dismiss the panel with a touch outside its boundaries, just like the stock system panels. Other than that, you are working with the standard XAML control set and can include virtually anything in your settings.</p><p>Notice, that the switches and sliders are bound to internal properties, such as <strong>SFXEnabled</strong> and <strong>MusicEnabled</strong>, that perform the binding <a href="http://msdn.microsoft.com/en-us/library/windows/apps/hh700353.aspx">via dependency property references</a>:</p><p><pre class="brush: cpp">
DependencyProperty^ DirectXPage::_musicEnabled = DependencyProperty::Register(&quot;MusicEnabled&quot;, 
bool::typeid, DirectXPage::typeid, nullptr);
DependencyProperty^ DirectXPage::_sfxEnabled = DependencyProperty::Register(&quot;SFXEnabled&quot;, 
bool::typeid, DirectXPage::typeid, nullptr);
</pre></p><p>&nbsp;</p><p>The properties themselves are declared in the <strong>DirectXPage</strong> header file:</p><p><pre class="brush: csharp">
static property DependencyProperty^ SFXVolumeProperty
{
    DependencyProperty^ get() { return _sfxVolume; }
}
property int SFXVolume
{
    int get() { return (int)GetValue(SFXVolumeProperty); }
    void set(int value) 
    { 
        SetValue(SFXVolumeProperty, value);
    }
}

static property DependencyProperty^ MusicVolumeProperty
{
    DependencyProperty^ get() { return _musicVolume; }
}
property int MusicVolume
{
    int get() { return (int)GetValue(MusicVolumeProperty); }
    void set(int value) 
    { 
        SetValue(MusicVolumeProperty, value);
    }
}
</pre></p><p>Let’s take a quick look at how settings are stored. I have a class called <strong>SettingsHelper</strong> that allows me to save, read, and check if specific settings exist. Here is the implementation:</p><p><pre class="brush: cpp">
#include &quot;pch.h&quot;
#include &quot;SettingsHelper.h&quot;

using namespace Windows::Storage;
using namespace Coding4Fun::FallFury::Helpers;

SettingsHelper::SettingsHelper(void)
{
}

void SettingsHelper::Save(Platform::String^ key, Platform::Object^ value)
{
    ApplicationDataContainer^ localSettings = ApplicationData::Current-&gt;LocalSettings;
    auto values = localSettings-&gt;Values;

    values-&gt;Insert(key, value);
}

Platform::Object^ SettingsHelper::Read(Platform::String^ key)
{
    ApplicationDataContainer^ localSettings = ApplicationData::Current-&gt;LocalSettings;
    auto values = localSettings-&gt;Values;

    return values-&gt;Lookup(key);
}

bool SettingsHelper::Exists(Platform::String^ key)
{
    ApplicationDataContainer^ localSettings = ApplicationData::Current-&gt;LocalSettings;
    auto values = localSettings-&gt;Values;

    return values-&gt;HasKey(key);
}
</pre></p><p>&nbsp;</p><p>It is clear that storage and retrieval heavily relies on the <a href="http://msdn.microsoft.com/en-us/library/windows/apps/windows.storage.applicationdatacontainer.aspx">ApplicationDataContainer</a> class, the container class for local settings that eliminates the need for the developer to create his own setting files, instead delegating this task to the OS and utilizing a centralized storage for all Windows Store applications.</p><p>A typical scenario that utilizes the class above is executed when the toggle that manages the sound effects is switched:</p><p><pre class="brush: cpp">
void DirectXPage::tglSFX_Toggled(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
    SettingsHelper::Save(&quot;sfxEnabled&quot;, tglSFX-&gt;IsOn);
    SFXEnabled = tglSFX-&gt;IsOn;
    AudioManager::IsSFXStarted = SFXEnabled;

    if (SFXEnabled)
    {
        AudioManager::AudioEngineInstance.StartSFX();
    }
    else
    {
        AudioManager::AudioEngineInstance.SuspendSFX();
    }
}
</pre></p><p>&nbsp;</p><p>The Boolean value above will be automatically serialized and stored. The files will be located at <strong>C:\Users\YOUR_USER_NAME\AppData\Local\Packages\PACKAGE_ID\Settings\settings.dat:</strong></p><p>&nbsp;</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image012%5B3%5D-4.jpg"><img title="clip_image012" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image012_thumb-4.jpg" alt="clip_image012" width="640" height="192" border="0"></a></p><h4>Conclusion</h4><p>Implementing sharing through the OS channel in Windows 8 is extremely easy seeing as the developer does not necessarily have to worry about connecting the app to third-party API endpoints. Instead, the user controls the sharing, allowing flexibility of choice without requiring a major addition to the existing code base. It’s hard to predict which services might appear, and modifying the app to support each one of them would be next to impossible otherwise.</p><p>You can read more about settings in Windows Store applications <a href="http://msdn.microsoft.com/en-us/library/windows/apps/hh770544.aspx">here</a>.</p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/DennisDel/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:41450e373f904b80834ba14d01612a58">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-10-Charms</comments>
      <itunes:summary>CharmsWith the release of the Windows 8 operating system, applications are now able to easily integrate with each other and have a unified way to control their workflow through unique system-wide contracts called Charms. Out of the multitude of available options, FallFury leverages two charms—Share contract and Settings. This article describes how the integration is implemented. Check out the video for this article at http://channel9.msdn.com/Series/FallFury/Part-10-Charms&amp;nbsp;.&amp;nbsp; For a complete, offline version of this series, you may download a nicely formatted PDF of all the articles.  The Share ContractWhen a user achieves a specific score in the game, he might decide to share it with his social circle. In Charms, that’s the purpose of the Share contract, which integrates directly with the OS. Windows Store applications have the capability to expose their sharing capabilities and register as a share target. For example, if there is a Twitter client out, it can register itself as an app through which content can be shared. FallFury, on the other hand, acts as a consumer that aggregates existing share targets and lets the user pick the one through which he wants to let the message out:  Let’s take a look at how this process is built in the code-behind. The core is located in DirectXPage.xaml.cpp—the class responsible for XAML content manipulation in FallFury. First and foremost, you need to get the current instance of the DataTransferManager class: 
auto dataTransferManager = Windows::ApplicationModel::DataTransfer::DataTransferManager::GetForCurrentView();
 Consider this a proxy that allows you to pass content between your app and other Windows Store apps that are executed in the context of the same sandbox. As the instance is obtained, hook it to the DataRequested event handler that will handle the scenario where the user invoked the sharing capability: 
dataTransferManager-&amp;gt;DataRequested &amp;#43;= ref new 
    TypedEventHandler&amp;lt;Windows::ApplicationM</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-10-Charms</link>
      <pubDate>Wed, 23 Jan 2013 23:57:40 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-10-Charms</guid>
      <media:thumbnail url="http://media.ch9.ms/ch9/d462/4039d0c3-2c48-4570-98d7-56de07f1d462/FallFuryPart10_100.jpg" height="56" width="100"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/d462/4039d0c3-2c48-4570-98d7-56de07f1d462/FallFuryPart10_220.jpg" height="124" width="220"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/d462/4039d0c3-2c48-4570-98d7-56de07f1d462/FallFuryPart10_512.jpg" height="289" width="512"></media:thumbnail>      
      <dc:creator>Brian Peek, Clint Rutkas, Dan Fernandez, Den Delimarsky, Rick Barraza</dc:creator>
      <itunes:author>Brian Peek, Clint Rutkas, Dan Fernandez, Den Delimarsky, Rick Barraza</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-10-Charms/RSS</wfw:commentRss>
      <category>C#</category>
      <category>C++</category>
      <category>DirectX</category>
      <category>Windows Store App</category>
    </item>
  <item>
      <title>Fall Fury: Part 9 - Particle System</title>
      <description><![CDATA[<h3>Particle System</h3><p>During gameplay there are scenarios during which users need to be visually notified that something has happened, such as a collision with an obstacle or an enemy shell. One way to do this is by having explosion or item breaking simulation, which brings us to the next large component in FallFury—the sprite-based particle system. It doesn’t offer as much power as a full-fledged particle system would, but it allows for effects that fit well within the overall theme and layout of the game.</p><p>Check out the video for this article at <a href="http://channel9.msdn.com/Series/FallFury/Part-9-Particle-System">http://channel9.msdn.com/Series/FallFury/Part-9-Particle-System</a>&nbsp;.&nbsp; For a complete, offline version of this series, you may <a href="http://media.ch9.ms/coding4fun/fallfury/FallFury.pdf">download a nicely formatted PDF of all the articles</a>.</p><h4>The Core</h4><p><strong>ParticleSystem</strong> is the dedicated folder in the project that contains everything needed to render multiple textures at once and displace them to create the desired effect:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image001%5B3%5D.png"><img title="clip_image001" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image001_thumb.png" alt="clip_image001" width="353" height="343" border="0"></a></p><p>A single particle carries information regarding its size, position, velocity, color shading, rotation, circular velocity, and scale. As with any other rendered entity, it has a bounding box that can be used to detect its intersection with other elements on the screen. In FallFury, this functionality is not used.</p><p>Its structure is as follows:</p><p><pre class="brush: cpp">
#pragma once
#include &quot;pch.h&quot;
struct Particle
{
    Particle(float2 size);
    Particle(float2 size, float4 shading);
    float2 Size;
    float2 Position;
    float2 Velocity;
    float4 Shading;
    float Rotation;
    float RotationVelocity;
    float Scale;
    bool IsWithinScreenBoundaries(float x, float y, Windows::Foundation::Rect screenBounds);
    Windows::Foundation::Rect GetBoundingBox();
};
</pre></p><p>The <strong>Particle</strong> class also happens to have two constructors—one that sets the particle to have the default shading, effectively removing the effect, and one where shading is dynamic. Note that a particle on its own doesn’t do much—it neither carries the associated texture nor has an internal loop that can be used in any given application part to display it.</p><p>The next core class is <strong>ParticleSet</strong>. It is used as a container for all the particles associated with a specific effect. For example, if I want to create flying stuffing when the bear hits an obstacle, I create a new ParticleSet instance and define the necessary particle properties:</p><ul><li><strong>Lifespan</strong> – a particle set does not constantly animate. It displays the particles for a limited amount of time, and displaces them by the given velocity values, and then self-destructs. </li><li><strong>Texture</strong> – all particles in a <strong>ParticleSet</strong> have the same texture. Going back to the stuffing example, there is a single PNG file used to render multiple variable-sized particles on collision. </li><li><strong>IsAlive </strong>– this is the flag that shows whether the particle set should be rendered in the first place. If it is set to <strong>false</strong> then, regardless of the conditions, this <strong>ParticleSet</strong> instance is ignored. </li><li><strong>ShouldScale </strong>– this flag determines whether particles will automatically increase their scale as they are being displaced, creating the effect of a particle approaching the screen. This effect is applied to each particle in the set. </li></ul><p>The container class is used to update the particles through the Update function:</p><p><pre class="brush: cpp">
void ParticleSet::Update(float timeDelta)
{
    float quat = _lifespan / 0.016f;
    float decrement = 1.0f / quat;
    
    if (_totalTime &lt;= _lifespan &amp;&amp; _isAlive)
    {
        _totalTime &#43;= timeDelta;
        
        for (auto particle = _particles.begin(); particle != _particles.end(); particle&#43;&#43;)
        {
            if (_shouldScale)
                particle-&gt;Scale &#43;= 0.2f;
            
            particle-&gt;Shading.a -= decrement;
            particle-&gt;Position = float2(particle-&gt;Position.x &#43; particle-&gt;Velocity.x,
                            particle-&gt;Position.y &#43; particle-&gt;Velocity.y);
            
            if (!_shouldScale)
                particle-&gt;Rotation &#43;= particle-&gt;RotationVelocity;
        }
    }
    else
    {
        _totalTime = 0.0f;
        _isAlive = false;
    }
}
</pre></p><p>As it relies on the <strong>_isAlive</strong> flag, the <strong>Update</strong> loop is only used when the particle displacement is activated via the <strong>Activate</strong> function:</p><p><pre class="brush: cpp">
void ParticleSet::Activate(float2 position, float2 velocity, bool randomize, bool scale)
{
    for (auto particle = _particles.begin(); particle != _particles.end(); particle&#43;&#43;)
    {
        particle-&gt;Position = position;

        if (randomize)
            particle-&gt;Velocity = float2(RandFloat(-5.0f,5.0f), RandFloat(-5.0f, 5.0f));
        else
            particle-&gt;Velocity = float2(velocity.x &#43; RandFloat(-0.6f, 0.6f), velocity.y &#43; RandFloat(-0.6f, 0.6f));;
    }

    _shouldScale = scale;
    _isAlive = true;
}
</pre></p><p>When a set is activated, several user-defined parameters come into play. The position is set no matter what and is used to create the source point from which the particles start appearing. The velocity, on the other hand, can be randomized between the values of <em>-5</em> and <em>5</em> pixels per update loop, on both the X-axis and the Y-axis. If randomized, large amount of particles will create an explosion that starts from the center point and expands towards all quadrants. When the velocity is not randomized, it creates a triangular expansion grid on which particles deviate from the center point in one of the given directions:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image003%5B3%5D-1.png"><img title="clip_image003" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image003_thumb-1.png" alt="clip_image003" width="640" height="235" border="0"></a></p><p>When it’s time to render the particles, the sprite batch associated with the current game screen is used to pass a texture for each particle registered in the set:</p><p><pre class="brush: cpp">
void ParticleSet::Render(SpriteBatch ^spriteBatch)
{
    for (auto particle = _particles.begin(); particle != _particles.end(); particle&#43;&#43;)
        {
        if (GamePlayScreen::Manager-&gt;IsWithinScreenBoundaries(particle-&gt;Position))
                    spriteBatch-&gt;Draw(_texture.Get(), particle-&gt;Position, PositionUnits::DIPs,
                    particle-&gt;Size * particle-&gt;Scale, SizeUnits::Pixels, particle-&gt;Shading, particle-&gt;Rotation);
        }
}
</pre></p><p>Although there is no flag check inside the Render method that would make sure that the set is alive, this can be done outside of it by calling <strong>IsAlive</strong>, which will return the flag value:</p><p><pre class="brush: cpp">
bool ParticleSet::IsAlive()
{
    return _isAlive;
}
</pre></p><p>&nbsp;</p><p>Let’s now take a look at the class that managed the particle flow—<strong>ParticleCore</strong>.</p><h4>The Particle Manager</h4><p><strong>ParticleCore</strong> is the class that manages internal particle sets, and is also the proxy for set activation, update, and rendering. Here is its structure:</p><p><pre class="brush: cpp">
#pragma once
#include &quot;pch.h&quot;
#include &quot;ParticleSet.h&quot;
#include &lt;list&gt;
#include &lt;map&gt;

class ParticleCore
{
    public:
    ParticleCore();
    ParticleCore(Coding4Fun::FallFury::Screens::GameScreenBase^);
    virtual ~ParticleCore();
    
    void CreatePreCachedParticleSets();
    void ActivateSet(Platform::String^, float2);
    void ActivateSet(Platform::String^, float2, float2);
    void ActivateSet(Platform::String^, float2, bool);
    void ActivateSet(Platform::String^, float2, float2, bool);
    void ActivateSet(Platform::String^, float2, float2, bool, bool scale);
    void Update(float);
    void Render();
    
    private:
        std::list&lt;ParticleSet&gt;                                                    _renderParticleSets;
        std::map&lt;Platform::String^, ParticleSet*&gt;                                _particleSetCache;
        std::map&lt;Platform::String^, Microsoft::WRL::ComPtr&lt;ID3D11Texture2D&gt;&gt;    _textureCache;
        Coding4Fun::FallFury::Screens::GameScreenBase^                            _screenBase;
};
</pre></p><p>As previously mentioned, set activation can be done with some omitted parameters inferred by the system, such as randomization of velocity or particle scaling, which is the reason why you see multiple overloads for <strong>ActivateSet</strong>.</p><p><strong>ParticleCore</strong> is also the container for pre-defined sets that have specific textures and properties that are dumped in the particle set cache (internal <strong>_particleSetCache</strong>). The cache is reusable and even though sets can be activated and destroyed, the cache remains intact for the duration of the game unless explicitly reset or modified. The texture cache is an addition to the particle set cache and is used as a helper container to temporarily store the textures used for individual particles.</p><p>Taking a look under the hood at the <strong>CreatePreCachedParticleSets</strong> function, you can see multiple sets that can be used in the game, each with different properties. Here is a snippet that shows how the bear stuffing explosion set is created:</p><p><pre class="brush: cpp">
auto smallExplosionSet = new ParticleSet(_textureCache[&quot;Stuffing&quot;], LIFESPAN);
for (int i = 0; i &lt; 20; i&#43;&#43;)
{
    float size = RandFloat(50.0f, 100.0f);
    Particle particle(float2(size, size));
    smallExplosionSet-&gt;AddParticle(particle);
}
</pre></p><p>&nbsp;</p><p>Once all the particles are in place for that specific set, it is added to the global particle set cache:</p><p><pre class="brush: cpp">
_particleSetCache[&quot;SmallExplosion&quot;] = smallExplosionSet;
</pre></p><p>The particle set cache is not explicitly used to render anything on the screen. Rather, that task is delegated to the rendering cache. When a set is activated, the cache is inspected for the given key, its Activate function is called, marking it as alive, and the set itself is pushed on the rendering stack:</p><p><pre class="brush: cpp">
void ParticleCore::ActivateSet(Platform::String^ name, float2 position, float2 velocity, bool randomize, bool scale)
{
    ParticleSet set = ParticleSet(*_particleSetCache[name]);
    set.Activate(position, velocity, randomize, scale);
    _renderParticleSets.push_back(set);
}
</pre></p><p>&nbsp;</p><p>The Render loop takes care of invoking the proper <strong>SpriteBatch</strong> drawing functions for each set that is in that stack:</p><p><pre class="brush: cpp">
void ParticleCore::Render()
{
    for (auto set = _renderParticleSets.begin(); set != _renderParticleSets.end(); &#43;&#43;set)
    {
        if ((*set).IsAlive())
        {
            (*set).Render(_screenBase-&gt;CurrentSpriteBatch);
        }
    }
}
</pre></p><p>&nbsp;</p><p>Notice that, as previously mentioned, the set does not perform the life check on itself when rendering. Instead, the manager class performs this action. The same applies to the <strong>Update</strong> loop:</p><p><pre class="brush: cpp">
void ParticleCore::Update(float timeDelta)
{
    for (auto set = _renderParticleSets.begin(); set != _renderParticleSets.end();)
    {
        if ((*set).IsAlive())
        {
            (*set).Update(timeDelta);
            &#43;&#43;set;
        }
        else
        {
            set = _renderParticleSets.erase(set);
        }
    }
}
</pre></p><p>&nbsp;</p><p>The textures for each set are individually loaded in the <strong>CreatePreCachedParticleSets</strong>. Each instance is internally pushed into the cache and also added to the sprite batch associated with the current game screen, where <strong>ParticleCore</strong> is used:</p><p><pre class="brush: cpp">
Loader-&gt;LoadTexture(&quot;DDS\\stuffing.dds&quot;, &amp;_textureCache[&quot;Stuffing&quot;], nullptr);
_screenBase-&gt;CurrentSpriteBatch-&gt;AddTexture(_textureCache[&quot;Stuffing&quot;].Get());
</pre></p><p>&nbsp;</p><p>Once everything is loaded, the <strong>ParticleCore</strong> is ready to go and you can use as many particles as necessary in any part of the application. In <strong>GamePlayScreen</strong>, particle sets are activated in many cases. For example, if the bear dies:</p><p><pre class="brush: cpp">
void GamePlayScreen::CheckBearHealth()
{
    if (GameBear-&gt;CurrentHealth &lt;= 0)
    {
        m_particleSystem.ActivateSet(&quot;Buttons&quot;,GameBear-&gt;Position, true);
        GameBear-&gt;Kill();
        StopBackground();
    }
}
</pre></p><p>&nbsp;</p><h4>Conclusion</h4><p>Implementing a sprite-based particle system is not complicated, but it requires depending on a number of assumptions. For example, when a particle set is created, you might consider the fact that some hardware can handle drawing only a given number of sprites at the same time. If a particle set is rendered on a desktop machine, there is no guarantee that the same set will successfully render on an ARM device. Therefore, plan accordingly. For each particle set, create a lifespan that fits the scenario without wasting resources on rendering unnecessary particles. As an additional failsafe, you might want to disable specific particle set types when a Direct3D feature level below 10.0 is detected.</p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/DennisDel/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:d7f02957c420452a8791a14d01580aad">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-9-Particle-System</comments>
      <itunes:summary>Particle SystemDuring gameplay there are scenarios during which users need to be visually notified that something has happened, such as a collision with an obstacle or an enemy shell. One way to do this is by having explosion or item breaking simulation, which brings us to the next large component in FallFury—the sprite-based particle system. It doesn’t offer as much power as a full-fledged particle system would, but it allows for effects that fit well within the overall theme and layout of the game. Check out the video for this article at http://channel9.msdn.com/Series/FallFury/Part-9-Particle-System&amp;nbsp;.&amp;nbsp; For a complete, offline version of this series, you may download a nicely formatted PDF of all the articles. The CoreParticleSystem is the dedicated folder in the project that contains everything needed to render multiple textures at once and displace them to create the desired effect:  A single particle carries information regarding its size, position, velocity, color shading, rotation, circular velocity, and scale. As with any other rendered entity, it has a bounding box that can be used to detect its intersection with other elements on the screen. In FallFury, this functionality is not used. Its structure is as follows: 
#pragma once
#include &amp;quot;pch.h&amp;quot;
struct Particle
{
    Particle(float2 size);
    Particle(float2 size, float4 shading);
    float2 Size;
    float2 Position;
    float2 Velocity;
    float4 Shading;
    float Rotation;
    float RotationVelocity;
    float Scale;
    bool IsWithinScreenBoundaries(float x, float y, Windows::Foundation::Rect screenBounds);
    Windows::Foundation::Rect GetBoundingBox();
};
 The Particle class also happens to have two constructors—one that sets the particle to have the default shading, effectively removing the effect, and one where shading is dynamic. Note that a particle on its own doesn’t do much—it neither carries the associated texture nor has an internal loop that can be used</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-9-Particle-System</link>
      <pubDate>Wed, 23 Jan 2013 23:57:36 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-9-Particle-System</guid>
      <media:thumbnail url="http://media.ch9.ms/ch9/af7e/b408253b-7538-45b2-9b34-0685e059af7e/FallFuryPart9_100.jpg" height="56" width="100"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/af7e/b408253b-7538-45b2-9b34-0685e059af7e/FallFuryPart9_220.jpg" height="124" width="220"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/af7e/b408253b-7538-45b2-9b34-0685e059af7e/FallFuryPart9_512.jpg" height="289" width="512"></media:thumbnail>      
      <dc:creator>Brian Peek, Clint Rutkas, Dan Fernandez, Den Delimarsky, Rick Barraza</dc:creator>
      <itunes:author>Brian Peek, Clint Rutkas, Dan Fernandez, Den Delimarsky, Rick Barraza</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-9-Particle-System/RSS</wfw:commentRss>
      <category>C#</category>
      <category>C++</category>
      <category>DirectX</category>
      <category>Windows Store App</category>
    </item>
  <item>
      <title>Fall Fury: Part 8 - Element Interaction</title>
      <description><![CDATA[<h3>Element Interaction</h3><p>During the gameplay multiple entities interact with each other to make the gaming experience what it is. The bear collides with obstacles and collects buttons, monsters shoot shells that can fly off-screen or hit the bear—all this is possible with the help of the basic collision detection techniques that are implemented in FallFury.</p><p>Check out the video for this article at <a href="http://channel9.msdn.com/Series/FallFury/Part-8-Element-Interaction">http://channel9.msdn.com/Series/FallFury/Part-8-Element-Interaction</a>&nbsp;. For a complete, offline version of this series, you may <a href="http://media.ch9.ms/coding4fun/fallfury/FallFury.pdf">download a nicely formatted PDF of all the articles</a>.</p><h4>Buttons</h4><p>Buttons are bonus-boosters that can be placed by the level designer anywhere on the screen in game mode. These are relatively small entities, which are displaced vertically with each cycle of the <strong>Update</strong> loop and move in the opposite direction, but with the same velocity, as the main character.</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B2%5D-8.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb-9.png" alt="image" width="624" height="351" border="0"></a></p><p>Looking at the Update function in the GamePlayScreen class, you will notice this call:</p><p><pre class="brush: cpp">
UpdateButtons();
</pre></p><p><strong>UpdateButtons</strong> can be considered the button manager function responsible for removing the collected buttons from the rendering stack, counting them, and checking for a button collision when the bear is in close proximity. The implementation looks like this:</p><p><pre class="brush: cpp">
void GamePlayScreen::UpdateButtons()
{
    Windows::Foundation::Rect livingEntityBoundingBox = GameBear-&gt;GetBoundingBox();
    for (auto button = m_buttons.begin(); button != m_buttons.end();)
    {
        (*button)-&gt;Position.x = (*button)-&gt;PixelDiff &#43; LoBoundX;
        (*button)-&gt;Position.y -= GameBear-&gt;Velocity.y;
        if (Geometry::IsInProximity(GameBear-&gt;Position,(*button)-&gt;Position, 100))
        {
            Windows::Foundation::Rect obstacleRect = (*button)-&gt;GetBoundingBox();
            if (livingEntityBoundingBox.IntersectsWith(obstacleRect))
            {
                AudioManager::AudioEngineInstance.StopSoundEffect(Coin);
                AudioManager::AudioEngineInstance.PlaySoundEffect(Coin);
                m_particleSystem.ActivateSet(&quot;Sparkle&quot;, (*button)-&gt;Position,float2(RandFloat(-6.0f,6.0f),RandFloat(-10.0f, -5.0f)));
                StaticDataHelper::ButtonsCollected&#43;&#43;;
                button = m_buttons.erase(button);
            }
            else
            &#43;&#43;button;
        }
        else
        {
            &#43;&#43;button;
        }
    }
}
</pre></p><p>For performance reasons, FallFury supports composite bounding box creation as well as simple box creation. As mentioned earlier in the series, the main character is not composed of a single texture, but rather multiple sprites that are cross-positioned to create a single visual entity. To give you a better idea of what composite vs. simple boxing looks like, take a look at the images below:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B5%5D-10.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B1%5D-7.png" alt="image" width="266" height="225" border="0"></a><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B8%5D-4.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B2%5D-8.png" alt="image" width="226" height="222" border="0"></a></p><p>The image on the left shows how each part of the bear has its own bounding box, and each will be used for collision checking. In the image on the right, the bear has a single bounding box, creating minor potential gaps, but gaining performance.</p><p>Going back to <strong>UpdateButtons</strong>, once the bounding box is obtained, I iterate through the button collection and make sure that each item is located in the proper space:</p><p><pre class="brush: cpp">
(*button)-&gt;Position.x = (*button)-&gt;PixelDiff &#43; LoBoundX;
(*button)-&gt;Position.y -= GameBear-&gt;Velocity.y;
</pre></p><p>&nbsp;</p><p>The constant position checks are necessary because FallFury supports dynamic orientation changes. When the user switches from portrait to landscape mode and vice-versa, rendered elements on the screen are not automatically repositioned. Setting the X position is easy as long as there is a fixed button margin (from the left side of the screen: <strong>LoBoundX</strong>) and adding it to the current <strong>LoBoundX</strong> value results in a proper X location. There is no need to do the same check on the Y-axis because the level length remains the same regardless of the current screen orientation. The adjustment made relative the Y position is bound to the bear velocity. If the bear moves slower, buttons will also scroll slower.</p><p>Given that all buttons are properly positioned, a proximity check is performed on each button passed through the loop. If the bear position is at least 100 pixels away from the current button, the corresponding bounding box is obtained and an intersect check is performed. In simple boxing mode, this is done via <strong>Windows::Foundation::Rect::IntersectsWith</strong>:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B11%5D-4.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B3%5D-9.png" alt="image" width="562" height="61" border="0"></a></p><p>If a collision occurs, the appropriate sound effect is played and a particle set is activated to create a visual notification of the action. After the button counter is incremented, the button is removed from the local collection, effectively being removed from the rendering stack.</p><h4>Power-ups</h4><p>As the bear flies towards the end of the level, it might encounter bonuses to improve its ability to fight incoming enemies or protect from damage caused by enemy ammo or obstacles. The process behind displaying power-ups on the screen and determining whether there was a collision with the main character is similar to <strong>UpdateButtons</strong>.</p><p>The core function for this task is <strong>UpdatePowerups</strong>:</p><p><pre class="brush: cpp">
void GamePlayScreen::UpdatePowerups(float timeDelta)
{
    if (m_powerups.size() &gt; 0)
    {
        for (auto powerup = m_powerups.begin(); powerup != m_powerups.end(); powerup&#43;&#43;)
        {
            (*powerup)-&gt;Update(timeDelta);
            (*powerup)-&gt;Position.x = (*powerup)-&gt;PixelDiff &#43; LoBoundX;
            (*powerup)-&gt;Position.y -= GameBear-&gt;Velocity.y;
        }
    }
    CheckForCollisionWithPowerups();
}
</pre></p><p>&nbsp;</p><p>One difference you probably noticed in the snippet above is the fact that the collision check is now done through a separate function—<strong>CheckForCollisionWithPowerups</strong>:</p><p><pre class="brush: cpp">
void GamePlayScreen::CheckForCollisionWithPowerups()
{
    Powerup^ currentPowerup;
    Windows::Foundation::Rect livingEntityBoundingBox = GameBear-&gt;GetBoundingBox();
    for (auto powerup = m_powerups.begin(); powerup != m_powerups.end();)
    {
        currentPowerup = (*powerup);
        if (Geometry::IsInProximity(GameBear-&gt;Position,currentPowerup-&gt;Position, 100))
        {
            Windows::Foundation::Rect obstacleRect = currentPowerup-&gt;GetBoundingBox();
            if (livingEntityBoundingBox.IntersectsWith(obstacleRect))
            {
                AudioManager::AudioEngineInstance.PlaySoundEffect(GenericPowerup);
                GameBear-&gt;PickupPowerup(currentPowerup, &amp;m_particleSystem);
                powerup = m_powerups.erase(powerup);
            }
            else
            &#43;&#43;powerup;
        }
        else
        {
            &#43;&#43;powerup;
        }
    }
}
</pre></p><p>If an intersection is detected between the boxed bear and the power-up texture, the current power-up is passed to the <strong>Bear</strong> instance and the appropriate type of action is selected:</p><p><pre class="brush: cpp">
void Bear::PickupPowerup(Powerup^ powerup, ParticleCore* ParticleSystem)
{
    switch (powerup-&gt;Type)
    {
        case PowerupType::PARACHUTE:
        {
            m_previousVelocity = Velocity.y;
            SetParachute(powerup-&gt;Lifespan);
            Velocity.y -= powerup-&gt;Effect;
            ParticleSystem-&gt;ActivateSet(&quot;ScalableParachute&quot;, Position, 0.0f, false, true);
            break;
        }
        case PowerupType::HEALTH:
        {
            CurrentHealth = MaxHealth;
            ParticleSystem-&gt;ActivateSet(&quot;ScalableHeart&quot;, Position, 0.0f, false, true);
            break;
        }
        case PowerupType::BUBBLE:
        {
            if (IsHelmetEnabled)
            {
                IsHelmetEnabled = false;
                DamageDivider = 1.0f;
            }
            else
            {
                DamageDivider = powerup-&gt;Effect;
            }
            IsBubbleEnabled = true;
            m_maxBubbleCounter = powerup-&gt;Lifespan;
            ParticleSystem-&gt;ActivateSet(&quot;ScalableBubble&quot;, Position, 0.0f, false, true);
            break;
        }
        // [...]
        case PowerupType::BOOMERANG:
        {
            m_weaponType = powerup-&gt;Type;
            m_weaponTexture = m_boomerangTexture;
            CurrentDamage = powerup-&gt;Effect;
            m_weaponSize = float2(225.0f, 205.0f) * 0.5f;
            ParticleSystem-&gt;ActivateSet(&quot;ScalableBoomerang&quot;, Position, 0.0f, false, true);
            break;
        }
    }
}
</pre></p><p>Depending on the power-up, textures are added to the bear model and later passed to the rendering stack (if the power-up type is <strong>PARACHUTE</strong>), some textures and capabilities are replaced (<strong>BOOMERANG</strong>), or the bear capabilities are temporarily modified (<strong>BUBBLE</strong>):</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B14%5D-4.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B4%5D-3.png" alt="image" width="359" height="358" border="0"></a></p><p>If one of the temporary power-ups is enabled n the <strong>Update</strong> loop, dedicated timers ensure that ability enhancement does not last longer than necessary. As an example, here is the snippet that controls the bubble:</p><p><pre class="brush: cpp">
if (IsBubbleEnabled)
{
    m_currentBubbleCounter &#43;= timeDelta;
    if (m_currentBubbleCounter &gt; m_maxBubbleCounter)
    {
        IsBubbleEnabled = false;
        DamageDivider = 1.0f;
        m_currentBubbleCounter = 0.0f;
    }
}
</pre></p><p>&nbsp;</p><h4>Ammo Collisions</h4><p>There are also objects that direct ammo at either the enemy or the bear. After release, each shell follows a linear path towards the target, and while the user directs the shells that originate from the bear, those released by enemy entities automatically target the bear. In this case, the ammo needs to collide with an object to either damage or kill it. When a shell is released, it is added to the general ammo collection that is later updated internally:</p><p><pre class="brush: cpp">
void GamePlayScreen::UpdateAmmo(float timeDelta)
{
    for (auto shell = m_ammoCollection.begin(); shell != m_ammoCollection.end(); shell&#43;&#43;)
    {
        (*shell)-&gt;Update(timeDelta, &amp;m_particleSystem);
    }
}
</pre></p><p>&nbsp;</p><p>At this point, the rendering system does not differentiate between friendly and enemy ammo—all it knows is that each item in the collection must have a new position when a new frame is rendered. The <strong>CheckForCollisionsWithAmmo</strong> function checks for ammo collisions:</p><p><pre class="brush: cpp">
void GamePlayScreen::CheckForCollisionWithAmmo(LivingEntity^ entity)
{
    if (entity != nullptr)
    {
        Windows::Foundation::Rect livingEntityBoundingBox = entity-&gt;GetBoundingBox();
        if (entity-&gt;IsFriendly)
        {
            for (auto ammo = m_ammoCollection.begin(); ammo != m_ammoCollection.end();)
            {
                if (!(*ammo)-&gt;IsFriendly)
                {
                    Windows::Foundation::Rect ammoBoundingBox = (*ammo)-&gt;GetBoundingBox();
                    if (livingEntityBoundingBox.IntersectsWith(ammoBoundingBox))
                    {
                        m_particleSystem.ActivateSet(&quot;SmallExplosion&quot;,entity-&gt;Position, true);
                        entity-&gt;InflictDamage((*ammo)-&gt;HealthDamage);
                        GameBear-&gt;RedShade();
                        AudioManager::AudioEngineInstance.PlaySoundEffect(OuchA);
                        AudioManager::AudioEngineInstance.PlaySoundEffect(HardSoftCollision);
                        CheckBearHealth();
                        ammo = m_ammoCollection.erase(ammo);
                    }
                    else
                    {
                        &#43;&#43;ammo;
                    }
                }
                else
                {
                    &#43;&#43;ammo;
                }
            }
        }
        else
        {
            for (auto ammo = m_ammoCollection.begin(); ammo != m_ammoCollection.end();)
            {
                if ((*ammo)-&gt;IsFriendly)
                {
                    Windows::Foundation::Rect ammoBoundingBox = (*ammo)-&gt;GetBoundingBox();
                    if (livingEntityBoundingBox.IntersectsWith(ammoBoundingBox))
                    { 
                        Monster^ monster = ((Monster^)entity);
                        if (!monster-&gt;IsDead &amp;&amp; monster-&gt;IsActive)
                        {
                            m_particleSystem.ActivateSet(&quot;SmallExplosion&quot;, entity-&gt;Position, true);
                            entity-&gt;InflictDamage((*ammo)-&gt;HealthDamage);
                            monster-&gt;RedShade();
                            monster-&gt;CheckIfAlive();
                            AudioManager::AudioEngineInstance.PlaySoundEffect(SharpSoftCollision);
                        }
                        ammo = m_ammoCollection.erase(ammo);
                    }
                    else
                    {
                        &#43;&#43;ammo;
                    }
                }
                else
                {
                    &#43;&#43;ammo;
                }
            }
        }
    }
}
</pre></p><p>When the function is called, it is usually run against an entity that is present on the screen, such as the main character. Regardless of whether the enemy or the friendly character fired the shot, the shot cannot inflict damage to its source, and that’s why the function implements the ammo-to-entity crosscheck. If the ammo collides with any shells intersecting the entity bounding box, a collision is counted and health verification is performed to ensure that the character is still alive and that the game should continue. The bear’s health is checked via <strong>CheckBarHealth</strong>:</p><p><pre class="brush: cpp">
void GamePlayScreen::CheckBearHealth()
{
    if (GameBear-&gt;CurrentHealth &lt;= 0)
    {
        m_particleSystem.ActivateSet(&quot;Buttons&quot;,GameBear-&gt;Position, true);
        GameBear-&gt;Kill();
        StopBackground();
    }
}
</pre></p><p>That said, not all ammo will collide with entities on the screen. Some of it will go out-of-bounds, and without an explicit cleanup process in place out-of-bounds ammo is constantly re-rendered even though the end user has no way of seeing it. To avoid this, there is a helper function—<strong>CheckForOutOfBoundsAmmo</strong>:</p><p><pre class="brush: cpp">
void GamePlayScreen::CheckForOutOfBoundsAmmo()
{
    for (auto l_Iter = m_ammoCollection.begin(); l_Iter != m_ammoCollection.end(); /* nothing here */ )
    {
        if (!GamePlayScreen::Manager-&gt;IsWithinScreenBoundaries((*l_Iter)-&gt;Position))
        {
            l_Iter = m_ammoCollection.erase(l_Iter);
        }
        else
        {
            &#43;&#43;l_Iter;
        }
    }
}
</pre></p><p>If any shell flies outside the screen bounding box, its instance is erased from the collection and the renderer no longer worries about allocating memory for an irrelevant item. To give you an idea of how that happens, here is a snippet that shows how the <strong>RenderScreen</strong> function handles the current ammo set:</p><p><pre class="brush: cpp">
if (!m_ammoCollection.empty())
{
    for (auto shell = m_ammoCollection.begin(); shell != m_ammoCollection.end(); shell&#43;&#43;)
    {
        if (!(*shell)-&gt;IsFriendly)
        {
            (*shell)-&gt;Render();
        }
        else
        {
            GameBear-&gt;RenderShell((*shell)-&gt;Position, (*shell)-&gt;Rotation);
        }
    }
}
</pre></p><p>&nbsp;</p><h4>Conclusion</h4><p>Element interaction is a core part of the FallFury experience. Separate handlers are implemented for each of them to ensure maximum flexibility when it comes to adding or removing components without breaking major parts of the code-base. Handling is mainly accomplished in the Update loop by iterating through registered entity sets, such as ammo, and verifying whether an action should be taken. Be cautious when implementing this kind of scenario with large entities and data sets—having multiple loops running simultaneously might tax machine performance, especially on low-power configurations such as ARM.</p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/DennisDel/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:79ffea1b09074fc7bfd9a14d01549989">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-8-Element-Interaction</comments>
      <itunes:summary>Element InteractionDuring the gameplay multiple entities interact with each other to make the gaming experience what it is. The bear collides with obstacles and collects buttons, monsters shoot shells that can fly off-screen or hit the bear—all this is possible with the help of the basic collision detection techniques that are implemented in FallFury. Check out the video for this article at http://channel9.msdn.com/Series/FallFury/Part-8-Element-Interaction&amp;nbsp;. For a complete, offline version of this series, you may download a nicely formatted PDF of all the articles. ButtonsButtons are bonus-boosters that can be placed by the level designer anywhere on the screen in game mode. These are relatively small entities, which are displaced vertically with each cycle of the Update loop and move in the opposite direction, but with the same velocity, as the main character.  Looking at the Update function in the GamePlayScreen class, you will notice this call: 
UpdateButtons();
 UpdateButtons can be considered the button manager function responsible for removing the collected buttons from the rendering stack, counting them, and checking for a button collision when the bear is in close proximity. The implementation looks like this: 
void GamePlayScreen::UpdateButtons()
{
    Windows::Foundation::Rect livingEntityBoundingBox = GameBear-&amp;gt;GetBoundingBox();
    for (auto button = m_buttons.begin(); button != m_buttons.end();)
    {
        (*button)-&amp;gt;Position.x = (*button)-&amp;gt;PixelDiff &amp;#43; LoBoundX;
        (*button)-&amp;gt;Position.y -= GameBear-&amp;gt;Velocity.y;
        if (Geometry::IsInProximity(GameBear-&amp;gt;Position,(*button)-&amp;gt;Position, 100))
        {
            Windows::Foundation::Rect obstacleRect = (*button)-&amp;gt;GetBoundingBox();
            if (livingEntityBoundingBox.IntersectsWith(obstacleRect))
            {
                AudioManager::AudioEngineInstance.StopSoundEffect(Coin);
                AudioManager::AudioEngineInstance.PlaySoundEf</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-8-Element-Interaction</link>
      <pubDate>Wed, 23 Jan 2013 23:57:25 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-8-Element-Interaction</guid>
      <media:thumbnail url="http://media.ch9.ms/ch9/3d85/e97b9237-10bd-414e-b825-986d050e3d85/FallFuryPart8_100.jpg" height="56" width="100"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/3d85/e97b9237-10bd-414e-b825-986d050e3d85/FallFuryPart8_220.jpg" height="124" width="220"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/3d85/e97b9237-10bd-414e-b825-986d050e3d85/FallFuryPart8_512.jpg" height="289" width="512"></media:thumbnail>      
      <dc:creator>Brian Peek, Clint Rutkas, Dan Fernandez, Den Delimarsky, Rick Barraza</dc:creator>
      <itunes:author>Brian Peek, Clint Rutkas, Dan Fernandez, Den Delimarsky, Rick Barraza</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-8-Element-Interaction/RSS</wfw:commentRss>
      <category>C#</category>
      <category>C++</category>
      <category>DirectX</category>
      <category>Windows Store App</category>
    </item>
  <item>
      <title>Fall Fury: Part 7 - Animations</title>
      <description><![CDATA[<h3>Animations &amp; Item Transitions</h3><p>FallFury relies on a lot of dynamic content. As you already aware of how <strong>SpriteBatch</strong> is invoked inside the FallFury rendering stack, this article focuses on how dynamic activities are handled on existing textures and entities. If you need a quick look at what was already covered, refer to Part 3 of the series.</p><p>Check out the video for this article at <a href="http://channel9.msdn.com/Series/FallFury/Part-7-Animations">http://channel9.msdn.com/Series/FallFury/Part-7-Animations</a>&nbsp;. For a complete, offline version of this series, you may <a href="http://media.ch9.ms/coding4fun/fallfury/FallFury.pdf">download a nicely formatted PDF of all the articles</a>.</p><h3>Menu Screen</h3><p>The first animated element shown in the menu screen is the bear, which is positioned in the top half of the viewport. Notice that the bear moves its paws as well as moving across the screen:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B2%5D-7.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb-8.png" alt="image" width="624" height="351" border="0"></a></p><p>The bear is implemented in the <strong>GameBear</strong> class and is the normal playable entity that is invincible when animated outside the scope of the gameplay screen. Its full body image is composed of four textures:</p><p><pre class="brush: cpp">
Microsoft::WRL::ComPtr&lt;ID3D11Texture2D&gt;        m_head;
Microsoft::WRL::ComPtr&lt;ID3D11Texture2D&gt;        m_leftPaw;
Microsoft::WRL::ComPtr&lt;ID3D11Texture2D&gt;        m_rightPaw;

Microsoft::WRL::ComPtr&lt;ID3D11Texture2D&gt;        m_body // Exposed through LivingEntity;
</pre></p><p>Each of these textures is internally dependent on the coupled float rotation and position values passed to the sprite batch in the host container (the parent screen):</p><p><pre class="brush: cpp">
HostContainer-&gt;CurrentSpriteBatch-&gt;Draw(
    m_rightPaw.Get(),
    m_rightPawPosition,
    PositionUnits::DIPs,
    float2(522.0f, 141.0f) * Scale,
    SizeUnits::Pixels,
    m_shading,
    m_rightPawRotation - 0.5f);

HostContainer-&gt;CurrentSpriteBatch-&gt;Draw(
    m_body.Get(),
    Position,
    PositionUnits::DIPs,
    float2(400.0f, 400.0f) * Scale,
    SizeUnits::Pixels,
    m_shading,
    Rotation);

HostContainer-&gt;CurrentSpriteBatch-&gt;Draw(
    m_leftPaw.Get(),
    m_leftPawPosition,
    PositionUnits::DIPs,
    float2(522.0f, 141.0f) * Scale,
    SizeUnits::Pixels,
    m_shading,
    m_leftPawRotation &#43; 0.5f);
</pre></p><p>Let’s take a look at how the position and rotation values are modified. All item animations are performed with the help of timers set to brief intervals in which the values are cycled through two value exchange operations. Here is a snippet taken from inside the Update method in the <strong>GameBear</strong> class that is responsible for bear arm movement:</p><p><pre class="brush: cpp">
if (m_armRotationTimer &lt; 0.6f)
{
    m_rightPawRotation -= 0.005f;
    m_leftPawRotation &#43;= 0.005f;
}
else if (m_armRotationTimer &gt; 0.6f &amp;&amp; m_armRotationTimer &lt; 1.2f)
{
    m_rightPawRotation &#43;= 0.005f;
    m_leftPawRotation -= 0.005f;
}
else
{
    m_rightPawRotation = 0.0f;
    m_leftPawRotation = 0.0f;
    m_armRotationTimer = 0.0f;
}
</pre></p><p><strong>m_armRotationTimer</strong> is a float value that is initially set to <strong>0.0f</strong>. In the <strong>Update</strong> loop and increments each iteration by the value of <strong>timeDelta</strong>, which represents the time difference between two loop cycles. As this value is less than 600 milliseconds (0.6 seconds), the right paw rotation is incremented and the left paw rotation decremented. The difference in the value adjustment direction is caused by the fact that one paw is rotated clockwise and the other is rotated counterclockwise. Once the timer tracks a value above 600 milliseconds but below than 1200 milliseconds, the process reverses and the paws rotate in the opposite direction. After 1.2 seconds, the timer resets, as does the rotation.</p><p>Since this rotation is automated, <strong>GameBear-&gt;Update</strong> is called in the menu screen:</p><p><pre class="brush: cpp">
m_showBear-&gt;Update(timeTotal, timeDelta, float2(Manager-&gt;m_windowBounds.Width / 2, Manager-&gt;m_windowBounds.Height / 2));
</pre></p><p>Outside the context of the bear update cycle, there is a similar timed mechanism used to randomly move the bear across the screen:</p><p><pre class="brush: cpp">
if (m_positionYAdj == 0.0f)
{
    m_positionYAdj = RandFloat(0.1f, 1.2f);
    m_positionXAdj = RandFloat(-1.0f, 1.0f);
}

if (m_positionTimer &lt; 4.0f)
{
    m_showBear-&gt;Position.x &#43;= m_positionXAdj;
    m_showBear-&gt;Position.y &#43;= m_positionYAdj;
    m_showBear-&gt;Rotation &#43;= 0.001f;
    m_showBear-&gt;Scale &#43;= 0.0008f;
    
    m_showMonster-&gt;Scale &#43;= 0.002f;
}
else if (m_positionTimer &gt; 4.0f &amp;&amp; m_positionTimer &lt; 8.0f)
{
    m_showBear-&gt;Position.x -= m_positionXAdj;
    m_showBear-&gt;Position.y -= m_positionYAdj;
    m_showBear-&gt;Rotation -= 0.001f;
    m_showBear-&gt;Scale -= 0.0008f;
}
else
{
    m_positionYAdj = 0.0f;
    m_positionTimer = 0.0f;
}
</pre></p><p>The X and Y adjustments are randomly generated and for the duration of a single timer cycle (in this case, 4 seconds) the bear’s horizontal and vertical positions are adjusted using those values. The rotation and scale are minimally adjusted to create a 3D motion effect. Because the displacement is minimal, the bear is always visible and does not move much outside the viewport.</p><p>There is also a flying monster animation in the main menu screen. Monster creation happens on top of the same instance that is replaced when an initial monster flies out of bounds:</p><p><pre class="brush: cpp">
m_showMonster-&gt;Position.y -= m_showMonster-&gt;Velocity.y;
if (m_showMonster-&gt;Position.y &lt; -m_showMonster-&gt;Size.y)
{
    CreateNewMonster();
}
</pre></p><p>&nbsp;</p><p>When a new monster is created, a random monster type is selected and its position on the X axis is randomized. The Y position is set to be right under the bottom screen boundary:</p><p><pre class="brush: cpp">
void MenuScreen::CreateNewMonster()
{
    m_showMonster = ref new Monster(this, (MonsterType)(rand() % (int)MonsterType::MT_CANDYLAND_E), true);
    m_showMonster-&gt;Scale = 0.3f;
    m_showMonster-&gt;Velocity.y = 1.0f;
    m_showMonster-&gt;Load();
    m_showMonster-&gt;Position = float2(RandFloat(LoBoundX, HiBoundX), Manager-&gt;m_windowBounds.Height &#43; m_showMonster-&gt;Size.y * m_showMonster-&gt;Scale);
}
</pre></p><p>Monster scaling is done on the same timed loop as the bear. The results look like this:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B5%5D-9.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B1%5D-6.png" alt="image" width="640" height="362" border="0"></a></p><h3>Gameplay Screen</h3><h4>Bear</h4><p>The gameplay screen carries the most animations in FallFury, including animations related to ammo displacement, monster movement paths, power-up animations, and secondary game character animations that are triggered in special cases such as character death.</p><p>Let’s start with character entrance. When the game begins, the teddy bear falls into the screen and stops at a specific point close to the top boundary of the gameplay screen. Once that transition is complete, the bear is no longer vertically displaced:</p><p><pre class="brush: cpp">
if ((GameBear-&gt;Position.y / HiBoundY) &lt; 0.19f)
{
    GameBear-&gt;Position.y &#43;= GameBear-&gt;Velocity.y * (3.2f);
}
</pre></p><p>&nbsp;</p><p>If the limit is not hit, the original bear velocity is multiplied by a fixed value, after which the condition is ignored for the rest of the gameplay.</p><p>Let’s now take a look at what happens when an enemy shell kills the bear. Generally, when the main character is killed, there is not much sense in maintaining other in-game activities. In FallFury, a killed bear results in a time freeze—the fall stops and the monsters are no longer shooting or moving. Not only that, but the bear is also flipped on its back:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B11%5D-3.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B3%5D-8.png" alt="image" width="386" height="387" border="0"></a></p><p>In the <strong>Update</strong> loop, the position for the paws and the head are adjusted for the new body texture layout:</p><p><pre class="brush: cpp">
if (IsDead)
{
    if (m_armRotationTimer &lt; 1.0f)
    {
        m_rightPawRotation &#43;= 0.001f;
        m_leftPawRotation -= 0.001f;
    }
    else if (m_armRotationTimer &gt; 1.0f &amp;&amp; m_armRotationTimer &lt; 2.0f)
    {
        m_rightPawRotation -= 0.001f;
        m_leftPawRotation &#43;= 0.001f;
    }
    else
    {
        m_rightPawRotation = 0.0f;
        m_leftPawRotation = 0.0f;
        m_armRotationTimer = 0.0f;
    }

    m_rightPawPosition = Position &#43; float2(40.0f, -50.0f) * Scale;
    m_leftPawPosition = Position &#43; float2(10.0f, 150.0f) * Scale;
    m_headPosition = (Position - float2(-160.0f, 0.0f) * Scale);
}
</pre></p><p>The proper textures are assigned via the <strong>Kill</strong> method:</p><p><pre class="brush: cpp">
void Bear::Kill()
{
    IsDead = true;
    Rotation = -1.0f;
    m_head = m_deadHead;
    m_body = m_deadBody;
    m_leftPaw = m_deadLeftArm;
    m_rightPaw = m_deadRightArm;
}
</pre></p><p>The bear will continue falling as long as <strong>StopBackground</strong> in <strong>GamePlayScreen</strong> is called:</p><p><pre class="brush: cpp">
void GamePlayScreen::StopBackground()
{
    m_isBackgroundMoving = false;
}
</pre></p><p>This will cause the internal state check to fail in the <strong>Update</strong> loop, sending the bear off screen limits. Once the bear completes the fall, the state is set to <strong>GS_GAME_OVER</strong>:</p><p><pre class="brush: cpp">
if (!m_isBackgroundMoving)
{
    if (GameBear-&gt;Position.y &gt; m_screenSize.y)
    {
        Manager-&gt;CurrentGameState = GameState::GS_GAME_OVER;
    }
    else
    {
        GameBear-&gt;Position.y &#43;= GameBear-&gt;Velocity.y * 1.5f;
    }
}
</pre></p><h4>Monsters</h4><p>Monsters, on the other hand, are being constantly moved during the duration of the game. Their basic displacement is performed by MoveMonsters:</p><p><pre class="brush: cpp">
void GamePlayScreen::MoveMonsters(float timeTotal ,float timeDelta)
{
    for (auto monster = m_monsters.begin(); monster != m_monsters.end();)
    {
        Monster^ currentMonster = (*monster);
        if ((currentMonster-&gt;Position.y - GameBear-&gt;Position.y) &lt; -Manager-&gt;m_renderTargetSize.Height / 2)
        {
            monster = m_monsters.erase(monster);
        }
        else
        {
            currentMonster-&gt;Velocity.y = GameBear-&gt;Velocity.y;
            currentMonster-&gt;Update(timeTotal, timeDelta, GameBear-&gt;Position, GetScreenBounds());
            CheckForCollisionWithAmmo(currentMonster);
            &#43;&#43;monster;
        }
    }
}
</pre></p><p>This method adjusts the monster position relative to the bear:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B14%5D-3.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B4%5D-2.png" alt="image" width="622" height="349" border="0"></a></p><p>The zig-zag like motion is defined in the <strong>Monster</strong> class in the <strong>Update</strong> method:</p><p><pre class="brush: cpp">
float adjustment = 0.0f;
adjustment = m_goingRight ? Position.x &#43; Velocity.x : Position.x - Velocity.x;
if (adjustment &gt;= (HostContainer-&gt;LoBoundX &#43; (Size.x * Scale) / 2.0f) 
&amp;&amp; adjustment &lt;= (HostContainer-&gt;HiBoundX - (Size.x * Scale) / 2.0f))
{
    Position.x = adjustment;
}
else
{
    m_goingRight = !m_goingRight;
}
</pre></p><p>&nbsp;</p><p>The snippet above determines the direction in which the enemy has to move depending on which screen boundary is hit first. While the monster is active and is visible, its vertical adjustment is performed in a timed loop, like this:</p><p><pre class="brush: cpp">
m_jumpingTimer &#43;= timeDelta;
if (m_jumpingTimer &gt; 0.0f &amp;&amp; m_jumpingTimer &lt; 1.0f)
{
    Position.y -= 1.0f;
}
else if (m_jumpingTimer &gt;= 1.0f &amp;&amp; m_jumpingTimer &lt; 2.0f)
{
    Position.y &#43;= 1.0f;
}
else
{
    m_jumpingTimer = 0.0f;
}
</pre></p><p>Here you can either use the Y velocity or introduce a static value. The only condition has to be a number low enough that the monster does not leave the screen, which would prevent the bear from being able to kill it. When the monster is killed, it flies out by following an arch-like path:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B17%5D-1.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B5%5D-1.png" alt="image" width="487" height="480" border="0"></a></p><p>The “death arc” is implemented via another timer:</p><p><pre class="brush: cpp">
Position.x &#43;= Velocity.y * 1.3f;
if (m_deathArcTimer &gt; 0.4f)
{
    Position.y &#43;= Velocity.y;
    if (Scale &gt; 0.1f)
    Scale -= 0.01f;
}
else
{
    Position.y -= Velocity.y;
    Scale &#43;= 0.01f;
    m_deathArcTimer &#43;= timeDelta;
}
</pre></p><p>&nbsp;</p><p>Regardless of the monster position, the horizontal displacement is positive and the entity moves to the right. For 400 milliseconds its vertical position is decreased, moving the texture up, and the scale is also adjusted to create the proximity effect. After this time interval, the monster drops out of the screen boundaries.</p><p>As previously mentioned, each monster is composed of three cycled textures, which are loaded and stored in three ID3D11Texture2D containers:</p><p><pre class="brush: cpp">
Microsoft::WRL::ComPtr&lt;ID3D11Texture2D&gt; m_spriteA;
Microsoft::WRL::ComPtr&lt;ID3D11Texture2D&gt; m_spriteB;
Microsoft::WRL::ComPtr&lt;ID3D11Texture2D&gt; m_spriteC;
</pre></p><p>&nbsp;</p><p>Each of these is assigned to the main body texture container every 300 milliseconds, replacing the previously assigned asset:</p><p><pre class="brush: cpp">
m_stateChangeTimer &#43;= timeDelta;
if (m_stateChangeTimer &lt; 0.3f)
{
    m_body = m_spriteA;
}
else if (m_stateChangeTimer &gt; 0.3f &amp;&amp; m_stateChangeTimer &lt; 0.6f)
{
    m_body = m_spriteB;
}
else if (m_stateChangeTimer &gt; 0.6f &amp;&amp; m_stateChangeTimer &lt; 0.9f)
{
    m_body = m_spriteC;
}
else if (m_stateChangeTimer &gt; 0.9f)
{
    m_stateChangeTimer = 0.0f;
}
</pre></p><p>&nbsp;</p><p>This cycle can be disabled when the monster is not active.</p><h4>Ammo</h4><p>There are different types of ammo used in the game, and each behaves in its own way. The stock ammo type is a plasma ball.</p><p>The default shooting behavior releases a shell when the user taps anywhere on the screen (other than the pause button area). Given the texture of the shell, when it is released the tail must be oriented towards the bear at an angle equal to the one created by the bear and the target position. To get a better idea, take a look at the images below:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B20%5D-4.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B6%5D-5.png" alt="image" width="339" height="340" border="0"></a><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B23%5D-1.png">&nbsp;<img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B7%5D-3.png" alt="image" width="340" height="340" border="0"></a></p><p>In the image on the left, the player tapped at the bottom of the screen. In the one on the right, the player tapped at the right edge of the screen. The shell accordingly rotates depending on the tapped position. To get a better understanding of how the rotation is performed, imagine the XY coordinate grid with the bear located at the intersection of the axes:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B26%5D-2.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B8%5D-7.png" alt="image" width="622" height="279" border="0"></a></p><p>Thinking back to trigonometry, notice the triangle formed by the shell and the bear origin point:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B29%5D-3.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B9%5D-2.png" alt="image" width="288" height="182" border="0"></a></p><p>Remember also the trig concept of quadrants:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B32%5D-1.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B10%5D-5.png" alt="image" width="623" height="278" border="0"></a></p><p>The quadrant in which the shell is located determines how the angle is calculated and the tail rotated. If the shell is in quadrant 2 or 3, calculate the rotation radians by following this algorithm:</p><p>1. Find the hypotenuse from the X and Y components of the velocity, which can be calculated by finding the difference between the bear and the position of the tap. To do this, us the well-known Pythagorean theorem:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B35%5D-1.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B11%5D-2.png" alt="image" width="100" height="20" border="0"></a></p><p>The hypotenuse formula can be deduced from the formula above and is the square root of the sum of the velocity component squares:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B38%5D-1.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B12%5D-5.png" alt="image" width="114" height="21" border="0"></a></p><p>2. Once calculated, it is necessary to find the sine of the target angle. The value can be obtained by dividing the Y component of the velocity by the hypotenuse.</p><p>3. Find the angle by calculating the arcsine from the resultant sine value. This will return the final angle in radians.</p><p>That said, for shells launched in quadrants 1 or 4, there is one extra step that needs to be performed. In addition to the rotation value obtained from the steps listed above, the rotation should be incremented by the radian value of a 180-degree angle minus twice the rotation value previously obtained. This ensures that the tail is correctly flipped relative to the axis origin.</p><p>In C&#43;&#43;, the implementation is done inside the <strong>AmmoItem</strong> class. For flexibility purposes, it triggers inside the <strong>Update</strong> loop—that way, it is possible to modify the trajectory of the shell and not worry about turning it again manually after launch:</p><p><pre class="brush: cpp">
if ((Velocity.x &gt; 0 &amp;&amp; Velocity.y &gt; 0) || (Velocity.x &gt; 0 &amp;&amp; Velocity.y &lt;0))
{
    Rotation = CalculateRadians(Velocity);
    Rotation &#43;= CalculateRadiansFromAngle(180) - 2 * Rotation;
}
else
{
    Rotation = CalculateRadians(Velocity);
}
</pre></p><p><strong>CalculateRadians</strong> is the method that transforms the velocity components in a rotation value. It is located in the <strong>BasicMath.h </strong>helper:</p><p><pre class="brush: cpp">
inline float CalculateRadians(float2 velocity)
{
    float hypothenuse = sqrt(velocity.x * velocity.x &#43; velocity.y * velocity.y);
    float sine = velocity.y / hypothenuse;
    float angle = asin(sine);
    return angle;
};
</pre></p><p>&nbsp;</p><p>There is a potential problem with the implementation above. As the user taps on different parts of the screen, the X and Y components are different, each resulting in a different hypotenuse. As the target is set, the shell flies faster the further away from the bear the user taps. To avoid this, the triangle legs should be normalized to a near-constant value:</p><p>Take a look at the <strong>ShootAtTarget</strong> function in the Bear class:</p><p><pre class="brush: cpp">
void Bear::ShootAtTarget(float2 lastTargetTrace)
{
    OnPulledTrigger(Position.x, Position.y, 
    GetVelocityLegs(lastTargetTrace).x, GetVelocityLegs(lastTargetTrace).y, 
    CurrentDamage, IsFriendly, false, HostContainer-&gt;CurrentSpriteBatch);
}
</pre></p><p>&nbsp;</p><p>Notice that the triangle legs are not passed as a raw value, but are proxied through <strong>GetVelocityLegs</strong>, which forces the resulting vector to be produced from a constant triangle with the velocity constant at 10 pixels per iteration:</p><p><pre class="brush: cpp">
float2 LivingEntity::GetVelocityLegs(float2 lastTargetTrace)
{
    float bottomLeg = 0.0f;
    float sideLeg = (Position.y - lastTargetTrace.y) / 100.0f;
    bottomLeg = (Position.x - lastTargetTrace.x) / 100.0f;
    float requiredVelocity = 10.0f;
    float hypothenuse = sqrt(bottomLeg * bottomLeg &#43; sideLeg * sideLeg);
    float proportionalX = 0.0f;
    float proportionalY = 0.0f;
    proportionalX = (requiredVelocity * bottomLeg) / hypothenuse;
    proportionalY = (sideLeg &lt; 0.0f ? -1 : 1) * sqrt(requiredVelocity * requiredVelocity - proportionalX * proportionalX);
    return float2(proportionalX,proportionalY);
}
</pre></p><p>&nbsp;</p><p>For ammo that does not have a visual rotation dependency, such as the plasma ball, simply increment the rotation to make the thrown item continuously spin:</p><p><pre class="brush: cpp">
if (Type == PowerupType::PLASMA_BALL)
{
    if ((Velocity.x &gt; 0 &amp;&amp; Velocity.y &gt; 0) || (Velocity.x &gt; 0 &amp;&amp; Velocity.y &lt;0))
    {
        Rotation = CalculateRadians(Velocity);
        Rotation &#43;= CalculateRadiansFromAngle(180) - 2 * Rotation;
    }
    else
    {
        Rotation = CalculateRadians(Velocity);
    }
}
else
{
    Rotation &#43;= 0.2f;
}
</pre></p><p>&nbsp;</p><h3>Conclusions</h3><p>FallFury mostly relies on sprite-based animations in which there are several textures cycled through in order to create the desired dynamic effect. These are not really hard to build, given that there is a possibility to integrate them in a timed loop. Be aware, however, that with slower machines the timing might be off and the time delta value between loops might be higher. In that case the sprite cycling will not be as smooth as it should be, which is why it’s important to perform animation testing on a variety of hardware with different OS loads.</p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/DennisDel/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:cf9dec8e099f4f63a437a14d0152aeab">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-7-Animations</comments>
      <itunes:summary>Animations &amp;amp; Item TransitionsFallFury relies on a lot of dynamic content. As you already aware of how SpriteBatch is invoked inside the FallFury rendering stack, this article focuses on how dynamic activities are handled on existing textures and entities. If you need a quick look at what was already covered, refer to Part 3 of the series. Check out the video for this article at http://channel9.msdn.com/Series/FallFury/Part-7-Animations&amp;nbsp;. For a complete, offline version of this series, you may download a nicely formatted PDF of all the articles. Menu ScreenThe first animated element shown in the menu screen is the bear, which is positioned in the top half of the viewport. Notice that the bear moves its paws as well as moving across the screen:  The bear is implemented in the GameBear class and is the normal playable entity that is invincible when animated outside the scope of the gameplay screen. Its full body image is composed of four textures: 
Microsoft::WRL::ComPtr&amp;lt;ID3D11Texture2D&amp;gt;        m_head;
Microsoft::WRL::ComPtr&amp;lt;ID3D11Texture2D&amp;gt;        m_leftPaw;
Microsoft::WRL::ComPtr&amp;lt;ID3D11Texture2D&amp;gt;        m_rightPaw;

Microsoft::WRL::ComPtr&amp;lt;ID3D11Texture2D&amp;gt;        m_body // Exposed through LivingEntity;
 Each of these textures is internally dependent on the coupled float rotation and position values passed to the sprite batch in the host container (the parent screen): 
HostContainer-&amp;gt;CurrentSpriteBatch-&amp;gt;Draw(
    m_rightPaw.Get(),
    m_rightPawPosition,
    PositionUnits::DIPs,
    float2(522.0f, 141.0f) * Scale,
    SizeUnits::Pixels,
    m_shading,
    m_rightPawRotation - 0.5f);

HostContainer-&amp;gt;CurrentSpriteBatch-&amp;gt;Draw(
    m_body.Get(),
    Position,
    PositionUnits::DIPs,
    float2(400.0f, 400.0f) * Scale,
    SizeUnits::Pixels,
    m_shading,
    Rotation);

HostContainer-&amp;gt;CurrentSpriteBatch-&amp;gt;Draw(
    m_leftPaw.Get(),
    m_leftPawPosition,
    PositionUnits::DIPs,
    float2(522</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-7-Animations</link>
      <pubDate>Wed, 23 Jan 2013 23:57:22 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-7-Animations</guid>
      <media:thumbnail url="http://media.ch9.ms/ch9/5a90/d869aabf-608a-42a9-b8b5-3512c3e65a90/FallFuryPart7_100.jpg" height="56" width="100"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/5a90/d869aabf-608a-42a9-b8b5-3512c3e65a90/FallFuryPart7_220.jpg" height="124" width="220"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/5a90/d869aabf-608a-42a9-b8b5-3512c3e65a90/FallFuryPart7_512.jpg" height="289" width="512"></media:thumbnail>      
      <dc:creator>Brian Peek, Clint Rutkas, Dan Fernandez, Den Delimarsky, Rick Barraza</dc:creator>
      <itunes:author>Brian Peek, Clint Rutkas, Dan Fernandez, Den Delimarsky, Rick Barraza</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-7-Animations/RSS</wfw:commentRss>
      <category>C#</category>
      <category>C++</category>
      <category>DirectX</category>
      <category>Windows Store App</category>
    </item>
  <item>
      <title>Fall Fury: Part 6 - Rendering Level Elements</title>
      <description><![CDATA[<h4>Rendering Level Elements</h4><p>In the previous article, you learned how to build level XML files in order to create playable levels. This article discusses how the internal parser works and how XML nodes become items on the game screen.&nbsp; Check out the video for this article at <a href="http://channel9.msdn.com/Series/FallFury/Part-6-Rendering-Level-Elements">http://channel9.msdn.com/Series/FallFury/Part-6-Rendering-Level-Elements</a>.&nbsp; For a complete, offline version of this series, you may <a href="http://media.ch9.ms/coding4fun/fallfury/FallFury.pdf">download a nicely formatted PDF of all the articles</a>.</p><h4>Project Interop – The C# Parser</h4><p>Thanks to classes such as <a href="http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.aspx">XmlSerializer</a> and <a href="http://msdn.microsoft.com/en-us/library/system.xml.linq.xdocument.aspx">XDocument</a>, parsing XML in .NET Framework is not a complicated task. Similarly, in the WinRT world there are alternatives such as <a href="http://msdn.microsoft.com/en-us/library/windows/apps/windows.data.xml.dom.aspx">Windows::Data::Xml::Dom</a>. That being said, using the parser skeleton in C# this project leverages the existing codebase, adapting it to the specific level reading needs.</p><p>Start by creating a new WinRT project that is the part of the existing solution. Make sure that you create a Windows Runtime Component:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image002%5B3%5D-5.jpg"><img title="clip_image002" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image002_thumb-6.jpg" alt="clip_image002" width="624" height="380" border="0"></a></p><p>There are <a href="http://www.drdobbs.com/windows/winrt-the-new-runtime-in-windows-8/232200577">major differences</a> between the .NET and WinRT stacks, especially when it comes to building code that can be invoked from any potential WinRT project type, as is the case here. Make sure that the output of the newly created project is a Windows Runtime Component (<a href="http://www.thomgerdes.com/2011/12/winrt-internals-winmd-files.html">WinMD file</a>):</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image004%5B3%5D-3.jpg"><img title="clip_image004" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image004_thumb-4.jpg" alt="clip_image004" width="640" height="195" border="0"></a></p><p>The XMLReader project reads much more than the level data—it also manages internal XML metadata such as user scores. This article, however, focuses only on level-related aspects of the engine.</p><p><strong>Reader </strong>is the one core class used here. It contains the <strong>ReadXml</strong> method, which receives the file name and the type of the XML file to be read. Regardless of the name, the XML file type determines the parsing rules, the root lookup location, and the produced output. The tier (level set) and individual level data are stored internally in the application folder, and the score metadata is outside the sandbox in the application data folder:</p><p><pre class="brush: csharp">
async Task&lt;Object&gt; ReadXml(string fileName, XmlType type)
{
        StorageFile file = null;
        StorageFolder folder = null;
    
        if (type == XmlType.LEVEL || type == XmlType.TIERS)
        {
                folder = Windows.ApplicationModel.Package.Current.InstalledLocation;
                folder = await folder.GetFolderAsync(&quot;Levels&quot;);
        }
        else if (type == XmlType.HIGHSCORE)
        {
                folder = ApplicationData.Current.LocalFolder;
                folder = await folder.GetFolderAsync(&quot;Meta&quot;);
        }
    
        file = await folder.GetFileAsync(fileName);
    
        Object returnValue = null;
        string data;
    
        using (IRandomAccessStream readStream = await file.OpenAsync(FileAccessMode.Read))
        {
                using (Stream inStream = Task.Run(() =&gt; readStream.AsStreamForRead()).Result)
                {
                        using (StreamReader reader = new StreamReader(inStream))
                        {
                                data = reader.ReadToEnd();
                        }
                }
        }
    
        if (type == XmlType.LEVEL)
        {
                returnValue = ExtractLevelData(data);
        }
        else if (type == XmlType.HIGHSCORE)
        {
                returnValue = ExtractScoreData(data);
        }
        else if (type == XmlType.TIERS)
        {
                returnValue = ExtractTierData(data);
        }
    
        return returnValue;
}
</pre></p><p>Before the level data is extracted, FallFury needs to know about the existing tiers pointing to those levels. That’s where <strong>ExtractTierData</strong>, an internal method that accepts a raw XML string and return a <strong>TierSet</strong> instance, comes in:</p><p><pre class="brush: csharp">
public sealed class TierSet
{
    public Tier[] Tiers { get; set; }
}
</pre></p><p>A <strong>Tier</strong> class has the following structure:</p><p><pre class="brush: csharp">
public sealed class Tier
{
    public string Name { get; set; }
    public string[] LevelNames { get; set; }
    public string[] LevelFiles { get; set; }
}
</pre></p><p>I am using the most fundamental types – arrays instead of generic collections, to maximize the portability of the code. The <strong>ExtractTierData </strong>method handles the XML-to-Object transformation:</p><p><pre class="brush: csharp">
TierSet ExtractTierData(string tierString)
{
        TierSet set = new TierSet();
    
        XDocument document = XDocument.Parse(tierString);
    
        set.Tiers = new Tier[document.Root.Elements().Count()];
    
        int tierCounter = 0;
    
        foreach (XElement element in document.Root.Elements())
        {
                Tier tier = new Tier();
                tier.Name = element.Attribute(&quot;name&quot;).Value;
        
                tier.LevelFiles = new string[element.Elements(&quot;level&quot;).Count()];
                tier.LevelNames = new string[element.Elements(&quot;level&quot;).Count()];
        
                
                int count = 0;
                foreach (XElement lElement in element.Elements(&quot;level&quot;))
                {
                        tier.LevelFiles[count] = lElement.Attribute(&quot;file&quot;).Value;
                        tier.LevelNames[count] = lElement.Attribute(&quot;name&quot;).Value;
                        count&#43;&#43;;
                }
        
                set.Tiers[tierCounter] = tier;
                tierCounter&#43;&#43;;
        }
    
        return set;
}
</pre></p><p>I am running a coupled array block here, utilizing one array for level names and another for file locations. This is a very basic implementation of a key-value pair that depends on code-based coupling. <strong>ExtractTierData</strong>, however, is not exposed publicly and the C&#43;&#43; layer of FallFury will not access it because <strong>TierSet</strong> is not exposed through a compatible async method. Looking back at <strong>ReadXml</strong>, might seem like the answer to this problem. But a <strong>Task&lt;Object&gt;</strong> is not an interop-compatible type, which means I use <strong>ReadXmlAsync</strong>, which proxies the call through an <a href="http://msdn.microsoft.com/en-us/library/windows/apps/br206598.aspx">IAsyncOperation</a>:</p><p><pre class="brush: csharp">
public IAsyncOperation&lt;Object&gt; ReadXmlAsync(string filename, XmlType type)
{
    return (IAsyncOperation&lt;Object&gt;)AsyncInfo.Run((CancellationToken token) =&gt; ReadXml(filename, type));
}
</pre></p><p><a href="http://msdn.microsoft.com/en-us/library/hh779740.aspx">AsyncInfo.Run</a> starts a WinRT async operation and handles the returned result, regardless of the selected file path or type.</p><p>Level-based data is extracted in a similar manner to the tier data. The difference lies in the used internal models, as well as the node reading order:</p><p><pre class="brush: csharp">
Level ExtractLevelData(string levelString)
{
        XDocument document = XDocument.Parse(levelString);
    
        Level level = new Level();
        level.LevelMeta = new Meta();
     
        level.LevelMeta.Score = Convert.ToInt32(document.Root.Element(&quot;meta&quot;).Attribute(&quot;score&quot;).Value);
        level.LevelMeta.ButtonPrice = Convert.ToInt32(document.Root.Element(&quot;meta&quot;).Attribute(&quot;buttonPrice&quot;).Value)
        level.LevelMeta.LevelType = (LevelType)Convert.ToInt32(document.Root.Attribute(&quot;type&quot;).Value);
    
        int count = document.Root.Element(&quot;obstacles&quot;).Elements().Count();
        level.Obstacles = new Obstacle[count];
    
        count = 0;
        foreach (XElement element in document.Root.Element(&quot;obstacles&quot;).Elements())
        {
                Obstacle obstacle = new Obstacle();
                obstacle.HealthDamage = Convert.ToSingle(element.Attribute(&quot;healthDamage&quot;).Value);
                obstacle.InflictsDamage = Convert.ToBoolean(element.Attribute(&quot;inflictsDamage&quot;).Value);
                obstacle.Rotation = Convert.ToSingle(element.Attribute(&quot;rotation&quot;).Value);
                obstacle.Scale = Convert.ToSingle(element.Attribute(&quot;scale&quot;).Value);
                obstacle.X = Convert.ToSingle(element.Attribute(&quot;x&quot;).Value);
                obstacle.Y = Convert.ToSingle(element.Attribute(&quot;y&quot;).Value);
                obstacle.Type = (ObstacleType)Convert.ToInt32(element.Attribute(&quot;type&quot;).Value);
                level.Obstacles[count] = obstacle;
                count&#43;&#43;;
        }
    
        count = document.Root.Element(&quot;monsters&quot;).Elements().Count();
        level.Monsters = new Monster[count];
    
        count = 0;
        foreach (XElement element in document.Root.Element(&quot;monsters&quot;).Elements())
        {
                Monster monster = new Monster();
                monster.CriticalDamage = Convert.ToSingle(element.Attribute(&quot;criticalDamage&quot;).Value);
                monster.Damage = Convert.ToSingle(element.Attribute(&quot;damage&quot;).Value);
                monster.DefaultAmmo = Convert.ToInt32(element.Attribute(&quot;defaultAmmo&quot;).Value);
                monster.MaxHealth = Convert.ToSingle(element.Attribute(&quot;maxHealth&quot;).Value);
                monster.X = Convert.ToSingle(element.Attribute(&quot;x&quot;).Value);
                monster.Y = Convert.ToSingle(element.Attribute(&quot;y&quot;).Value);
                monster.VelocityX = Convert.ToSingle(element.Attribute(&quot;velocityX&quot;).Value);
                monster.Lifetime = Convert.ToSingle(element.Attribute(&quot;lifetime&quot;).Value);
                monster.Type = (MonsterType)Convert.ToInt32(element.Attribute(&quot;type&quot;).Value);
                monster.Bonus = Convert.ToInt32(element.Attribute(&quot;bonus&quot;).Value);
                monster.Scale = Convert.ToSingle(element.Attribute(&quot;scale&quot;).Value);
        
                level.Monsters[count] = monster;
                count&#43;&#43;;
        }
    
        count = document.Root.Element(&quot;buttons&quot;).Elements().Count();
        level.Buttons = new Button[count];
    
        count = 0;
        foreach (XElement element in document.Root.Element(&quot;buttons&quot;).Elements())
        {
                Button button = new Button();
        
                button.X = Convert.ToSingle(element.Attribute(&quot;x&quot;).Value);
                button.Y = Convert.ToSingle(element.Attribute(&quot;y&quot;).Value);
        
                level.Buttons[count] = button;
                count&#43;&#43;;
        }
    
        count = document.Root.Element(&quot;powerups&quot;).Elements().Count();
        level.Powerups = new Powerup[count];
    
        count = 0;
        foreach (XElement element in document.Root.Element(&quot;powerups&quot;).Elements())
        {
                Powerup powerup = new Powerup();
        
                powerup.X = Convert.ToSingle(element.Attribute(&quot;x&quot;).Value);
                powerup.Y = Convert.ToSingle(element.Attribute(&quot;y&quot;).Value);
                powerup.Category = (PowerupCategory)Convert.ToInt32(element.Attribute(&quot;category&quot;).Value);
                powerup.Type = (PowerupType)Convert.ToInt32(element.Attribute(&quot;type&quot;).Value);
                powerup.Lifespan = Convert.ToSingle(element.Attribute(&quot;lifespan&quot;).Value);
                powerup.Effect = Convert.ToSingle(element.Attribute(&quot;effect&quot;).Value);
        
                level.Powerups[count] = powerup;
                count&#43;&#43;;
        }
    
        Bear bear = new Bear();
        XElement bearElement = document.Root.Element(&quot;bear&quot;);
        bear.CriticalDamage = Convert.ToSingle(bearElement.Attribute(&quot;criticalDamage&quot;).Value);
        bear.Damage = Convert.ToSingle(bearElement.Attribute(&quot;damage&quot;).Value);
        bear.DefaultAmmo = Convert.ToInt32(bearElement.Attribute(&quot;defaultAmmo&quot;).Value);
        bear.MaxHealth = Convert.ToSingle(bearElement.Attribute(&quot;maxHealth&quot;).Value);
        bear.StartPosition = Convert.ToSingle(bearElement.Attribute(&quot;startPosition&quot;).Value);
        bear.Velocity = Convert.ToSingle(bearElement.Attribute(&quot;velocity&quot;).Value);
    
        level.GameBear = bear;
        
        return level;
}
</pre></p><p>As a result, the <strong>Level</strong> instance has an internal counterpart in the C&#43;&#43; project:</p><p><pre class="brush: csharp">
public sealed class Level
{
    public Bear GameBear { get; set; }
    public Meta LevelMeta { get; set; }
    public Obstacle[] Obstacles { get; set; }
    public Monster[] Monsters { get; set; }
    public Button[] Buttons { get; set; }
    public Powerup[] Powerups { get; set; }
}
</pre></p><h4>From C# to C&#43;&#43; - Leveraging the WinRT Component</h4><p>At this point, the C#-based WinRT component is complete and can be integrated into the C&#43;&#43; project. This can be done in two ways: either by adding a reference to the project itself or by adding a reference to the generated WinMD file. Both methods will ultimately produce the same output, but it’s easier to debug and modify coupled projects on the go, so I went with the first option.</p><p>To add a reference to an internal Windows Runtime Component project, right click on the C&#43;&#43; project in <strong>Solution Explorer</strong> and select <strong>Properties</strong>. You will see a dialog like this:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image006%5B3%5D-1.jpg"><img title="clip_image006" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image006_thumb-2.jpg" alt="clip_image006" width="567" height="403" border="0"></a></p><p>Select the <strong>Common Properties</strong> node in the tree on the left and open the <strong>Framework and References</strong> page:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image008%5B3%5D-2.jpg"><img title="clip_image008" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image008_thumb-3.jpg" alt="clip_image008" width="569" height="404" border="0"></a></p><p>In the sample screen capture above, the <strong>FallFury.XMLReader</strong> project is already added as a reference. For a new project, simply click on <strong>Add New Reference</strong> and add any compatible project or third-party extension. As soon as the reference is added, the publicly exposed methods can be accessed.</p><p>In <strong>DirectXPage.cpp</strong> I have a method called <strong>LoadLevelData</strong> that allows me to load the list of the registered levels from <strong>core.xml</strong> as well as build the visual tree for the menu items, whichallows players to select a level:</p><p><pre class="brush: cpp">
void DirectXPage::LoadLevelData()
{
    Coding4Fun::FallFury::XMLReader::Reader^ reader = ref new Coding4Fun::FallFury::XMLReader::Reader();
    Windows::Foundation::IAsyncOperation&lt;Platform::Object^&gt;^ result = reader-&gt;ReadXmlAsync(&quot;core.xml&quot;, Coding4Fun::FallFury::XMLReader::Models::XmlType::TIERS);
    result-&gt;Completed =
        ref new AsyncOperationCompletedHandler&lt;Platform::Object^&gt;(this, &amp;DirectXPage::OnLevelLoadCompleted);
}
</pre></p><p>Following the normal asynchronous pattern, as well as the structure of the method exposed in the Reader class, I am calling <strong>ReadXmlAsync</strong> and getting the result in <strong>OnLevelLoadCompleted</strong> when the operation reaches its final stage. It is worth mentioning that the associated <a href="http://msdn.microsoft.com/en-us/library/windows/apps/br206572.aspx">AsyncOperationCompletedHandler</a> is invoked even when the reading fails; therefore, the invocation of that callback does not on its own mean that the necessary data is obtained:</p><p>Here is what happens when <strong>OnLevelLoadCompleted</strong> is called:</p><p><pre class="brush: cpp">
void DirectXPage::OnLevelLoadCompleted(IAsyncOperation&lt;Platform::Object^&gt; ^op, AsyncStatus s)
{
    if (s == AsyncStatus::Completed)
    {
        auto set = (Coding4Fun::FallFury::XMLReader::Models::TierSet^)op-&gt;GetResults();
        
        auto tiers = set-&gt;Tiers;
        
        int levelCounter = 0;
        
        for (auto tier = tiers-&gt;begin(); tier != tiers-&gt;end(); tier&#43;&#43;)
        {
            StackPanel^ panel = ref new StackPanel();
            
            TextBlock^ levelTierTitle = ref new TextBlock();
            levelTierTitle-&gt;Text = (*tier)-&gt;Name;
            levelTierTitle-&gt;Style = (Windows::UI::Xaml::Style^)Application::Current-&gt;Resources-&gt;Lookup(&quot;LevelSelectTierItemText&quot;);
            levelTierTitle-&gt;RenderTransform = ref new TranslateTransform();
            panel-&gt;Children-&gt;Append(levelTierTitle);
            
            levelNames = (*tier)-&gt;LevelNames;
            auto levelFiles = (*tier)-&gt;LevelFiles;
            
            int max = levelNames-&gt;Length;
            
            for(int i = 0; i &lt; max; i&#43;&#43;)
            {
                MenuItem^ item = ref new MenuItem();
                item-&gt;Tag = levelCounter;
                item-&gt;Label = levelNames[i];
                item-&gt;HorizontalAlignment = Windows::UI::Xaml::HorizontalAlignment::Left;
                item-&gt;OnButtonSelected &#43;= ref new MenuItem::ButtonSelected(this, &amp;DirectXPage::OnLevelButtonSelected);
                item-&gt;RenderTransform = ref new TranslateTransform();
                
                m_renderer-&gt;Levels.Insert(levelCounter,levelFiles[i]);
                
                panel-&gt;Children-&gt;Append(item);
                levelCounter&#43;&#43;;
            }
            
            stkLevelContainer-&gt;Items-&gt;Append(panel);
        }
    }
}
</pre></p><p>Here, <a href="http://msdn.microsoft.com/en-us/library/windows/apps/windows.foundation.asyncstatus">AsyncStatus</a> can also be <strong>Cancelled</strong> or <strong>Error</strong>, so checking for <strong>Complete</strong> ensures that the expected result is processed further inside the context of the callback.</p><p>As the returned <strong>TierSet</strong> exposes the <strong>Tiers</strong> array, I am simply iterating through each of the existing items to create independent tier blocks, grouped in <strong>StackPanel</strong> elements, coupled with level-specific <strong>MenuItem</strong> instances that present the user with a choice of playing a given level. The level ID is carried in the Tag property and it will be used to identify the selected button when <strong>DirectXPage::OnLevelButtonSelected</strong> is triggered:</p><h4>Reading Level-specific Data</h4><p>Level data is read in the <strong>GamePlayScreen</strong> once the selected menu button passes the name and level identifiers. The <strong>LoadLevelXml</strong> method is called as the screen begins to load, preparing all assets for the start of the game session:</p><p><pre class="brush: cpp">
void GamePlayScreen::LoadLevelXML()
{
    Coding4Fun::FallFury::XMLReader::Reader^ reader = ref new Coding4Fun::FallFury::XMLReader::Reader();
    
    Platform::String^ LevelName = Manager-&gt;Levels.Lookup(StaticDataHelper::CurrentLevelID);
    
    Windows::Foundation::IAsyncOperation&lt;Platform::Object^&gt;^ result = 
            reader-&gt;ReadXmlAsync(LevelName, Coding4Fun::FallFury::XMLReader::Models::XmlType::LEVEL);
    
        result-&gt;Completed =
            ref new AsyncOperationCompletedHandler&lt;Platform::Object^&gt;(this, &amp;GamePlayScreen::OnLevelLoadCompleted);
}
</pre></p><p>The selected ID passes from the menu screen to the game screen through <strong>CurrentLevelID</strong>, an intermediary value preserved in a <strong>StaticDataHelper</strong> class. The level file name is looked up based on the ID and then passed to <strong>ReadXmlAsync</strong> with the <strong>XmlType</strong> set to <strong>LEVEL</strong>. When the load completes, <strong>OnLevelLoadCompleted</strong> is invoked, and an additional helper class—<strong> LevelDataLoader</strong>—sets up the game components based on the received data:</p><p><pre class="brush: cpp">
void GamePlayScreen::OnLevelLoadCompleted(IAsyncOperation&lt;Platform::Object^&gt; ^op, AsyncStatus s)
{
        if (s == AsyncStatus::Completed)
        {
                InitializeSpriteBatch();    
        m_loader = ref new BasicLoader(Manager-&gt;m_d3dDevice.Get(), Manager-&gt;m_wicFactory.Get());
        CreateBear();
        
                LevelDataLoader^ loader = ref new LevelDataLoader((Coding4Fun::FallFury::XMLReader::Models::Level^)op-&gt;GetResults(), this);
        loader-&gt;SetupBear(GameBear);
        loader-&gt;SetupObstacles(m_obstacles);
        loader-&gt;SetupMonsters(m_monsters);
        loader-&gt;SetupButtons(m_buttons, m_buttonPrice);
        loader-&gt;SetupPowerups(m_powerups);
        m_currentLevelType = (LevelType) loader-&gt;CurrentLevel-&gt;LevelMeta-&gt;LevelType;
        
        StaticDataHelper::CurrentLevel = loader-&gt;CurrentLevel;
        StaticDataHelper::ButtonsTotal = loader-&gt;CurrentLevel-&gt;Buttons-&gt;Length;
        
        LoadTextures();
        
                CreateMonster();
                CreatePowerups();
        
        IsLevelLoaded = true;
        
        GameBear-&gt;TurnRight();
        m_particleSystem.CreatePreCachedParticleSets();
        LoadSounds();
        }
}
</pre></p><p>Each object is separated in its own method, such as <strong>SetupBear</strong> or <strong>SetupObstacles</strong>. <strong>SetupBear</strong>, for example, transforms the exposed managed <strong>Bear</strong> model to a native C&#43;&#43; <strong>Characters::Bear</strong> one:</p><p><pre class="brush: cpp">
void LevelDataLoader::SetupBear(Bear ^gameBear)
{
        gameBear-&gt;Position = float2(GetXPosition(CurrentLevel-&gt;GameBear-&gt;StartPosition), 0);    
    gameBear-&gt;MaxHealth = CurrentLevel-&gt;GameBear-&gt;MaxHealth;
    gameBear-&gt;CurrentHealth = CurrentLevel-&gt;GameBear-&gt;MaxHealth;
    gameBear-&gt;CurrentDamage = CurrentLevel-&gt;GameBear-&gt;Damage;
    gameBear-&gt;Velocity.y = CurrentLevel-&gt;GameBear-&gt;Velocity;
    gameBear-&gt;MaxCriticalDamage = CurrentLevel-&gt;GameBear-&gt;CriticalDamage;
    gameBear-&gt;Rotation = 0.0f;
}
</pre></p><h4>Conclusion</h4><p>Mixing C# and C&#43;&#43; components is not a complicated process. Nonetheless, it comes with specific restrictions and considerations, such as the format of the publicly exposed asynchronous calls. The above C#-based level loading engine highlights the fact that WinRT interoperability allows you to leverage the languages you know best in order to efficiently accomplish project tasks.</p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/DennisDel/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:3090c59845c94007a593a14a0135ba1f">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-6-Rendering-Level-Elements</comments>
      <itunes:summary>Rendering Level ElementsIn the previous article, you learned how to build level XML files in order to create playable levels. This article discusses how the internal parser works and how XML nodes become items on the game screen.&amp;nbsp; Check out the video for this article at http://channel9.msdn.com/Series/FallFury/Part-6-Rendering-Level-Elements.&amp;nbsp; For a complete, offline version of this series, you may download a nicely formatted PDF of all the articles. Project Interop – The C# ParserThanks to classes such as XmlSerializer and XDocument, parsing XML in .NET Framework is not a complicated task. Similarly, in the WinRT world there are alternatives such as Windows::Data::Xml::Dom. That being said, using the parser skeleton in C# this project leverages the existing codebase, adapting it to the specific level reading needs. Start by creating a new WinRT project that is the part of the existing solution. Make sure that you create a Windows Runtime Component:  There are major differences between the .NET and WinRT stacks, especially when it comes to building code that can be invoked from any potential WinRT project type, as is the case here. Make sure that the output of the newly created project is a Windows Runtime Component (WinMD file):  The XMLReader project reads much more than the level data—it also manages internal XML metadata such as user scores. This article, however, focuses only on level-related aspects of the engine. Reader is the one core class used here. It contains the ReadXml method, which receives the file name and the type of the XML file to be read. Regardless of the name, the XML file type determines the parsing rules, the root lookup location, and the produced output. The tier (level set) and individual level data are stored internally in the application folder, and the score metadata is outside the sandbox in the application data folder: 
async Task&amp;lt;Object&amp;gt; ReadXml(string fileName, XmlType type)
{
        StorageFile file = null;
   </itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-6-Rendering-Level-Elements</link>
      <pubDate>Wed, 23 Jan 2013 23:57:17 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-6-Rendering-Level-Elements</guid>
      <media:thumbnail url="http://media.ch9.ms/ch9/7ae7/6a8080f8-5fdb-4614-9540-da3c77cc7ae7/FallFuryPart6_100.jpg" height="56" width="100"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/7ae7/6a8080f8-5fdb-4614-9540-da3c77cc7ae7/FallFuryPart6_220.jpg" height="124" width="220"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/7ae7/6a8080f8-5fdb-4614-9540-da3c77cc7ae7/FallFuryPart6_512.jpg" height="289" width="512"></media:thumbnail>      
      <dc:creator>Brian Peek, Clint Rutkas, Dan Fernandez, Den Delimarsky, Rick Barraza</dc:creator>
      <itunes:author>Brian Peek, Clint Rutkas, Dan Fernandez, Den Delimarsky, Rick Barraza</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-6-Rendering-Level-Elements/RSS</wfw:commentRss>
      <category>C#</category>
      <category>C++</category>
      <category>DirectX</category>
      <category>Windows Store App</category>
    </item>
  <item>
      <title>Fall Fury: Part 5 - Creating Levels</title>
      <description><![CDATA[<h4>Creating Levels</h4><p>One of the goals set when developing FallFury was making the game extensible in regards to playable levels. Furthermore, I thought that it would make sense from the development and testing perspective to have levels as a completely separate entity that can be modified as necessary. For example, when a new power-up was introduced, I wanted to add an extra line in a level file and test it out. This was ultimately achieved by creating an XML-based level engine and in this article I will describe the level structure and design process.</p><p>Check out the video for this article at <a href="http://channel9.msdn.com/Series/FallFury/Part-5-Creating-Levels">http://channel9.msdn.com/Series/FallFury/Part-5-Creating-Levels.</a>&nbsp; For a complete, offline version of this series, you may <a href="http://media.ch9.ms/coding4fun/fallfury/FallFury.pdf">download a nicely formatted PDF of all the articles</a>.</p><h4>The First Steps</h4><p>When I started working on the level engine concept, I began designing the potential XML file structure for the level and ended up with the following requirements:</p><ul><li><strong>Level Type Identifier</strong> – As different levels have different backgrounds and sound themes, there should be a way to mark a level type. There are currently four level types: dream, nightmare, space, and magic bean. </li><li><strong>The Starting Character Descriptor</strong> – When the game starts, the teddy bear has some initial, basic properties, such as maximum health level, horizontal position, and velocity. </li><li><strong>A Collection of Obstacles </strong>– For each level, obstacles are positioned differently, and it’s important to specify that. For some obstacles it might be desirable to disable the damage infliction component, while for others it might be good to maximize the damage caused by colliding with them. Also, there are multiple textures associated with different obstacle types, so I wanted to specify the obstacles to render regardless of the selected level type. </li><li><strong>A Collection of Monsters </strong>– Obstacles are not the only component that can damage the bear during gameplay. There are also monsters that can pop up and shoot at the main character. Similar to the bear, monsters represent a living entity and have some specific properties, such as the initial health, damage, starting position, velocity, and type. </li><li><strong>Buttons – </strong>These are the bonus point boosters in FallFury. The player collects as many of those as possible, and each of them should be individually positioned to form either a trail or a shape. </li><li><strong>Power-Ups</strong> – With the basic set of abilities, the bear is able to get some bonuses such as a cape that will speed-up his descent or a bubble that will protect him from incoming shells. </li></ul><p>The first build of the level engine integrated into FallFuryused percentage-based relative values to position elements on the screen. Although this seemed like a good idea at the time, it became problematic because</p><ul><li>It required the level to be a fixed size, which restricted element addition and level extension. </li><li>It caused problems with obstacles that needed to be scaled and therefore had a non-standard size. </li><li>Small modifications were harder to make because minimal adjustments would throw off the relative position. </li></ul><p>So, I switched to a pixel-based conditioning in which each position is relative to zero. With this in place, levels can be infinitely long (within the context of the machine’s rendering and memory capabilities)and extra elements can be more seamlessly added.</p><p>Additionally, levels need to be packaged together in individual sets, normally grouped by themes, without restriction. This is achieved with the help of an extra XML file,called <strong>core.xml</strong>, which keeps track of level tiers, and acts as a container that allows the developer to name and easily enable or disable specific levels .</p><p>The structure for the <strong>core.xml</strong> file looks like this:</p><p><pre class="brush: xml">
&lt;tiers&gt;
  &lt;tier name=&quot;GO, GO, TEDDY&quot;&gt;
    &lt;level name=&quot;mind travels&quot; file=&quot;GoGoTeddy\mind.xml&quot;&gt;&lt;/level&gt;
    &lt;level name=&quot;falling in&quot; file=&quot;Nightmare\full_pilot.xml&quot;&gt;&lt;/level&gt;
    &lt;level name=&quot;frontlines&quot; file=&quot;Nightmare\the_beginning.xml&quot;&gt;&lt;/level&gt;
    &lt;level name=&quot;the chase&quot; file=&quot;Nightmare\chasing_monsters.xml&quot;&gt;&lt;/level&gt;
  &lt;/tier&gt;
  &lt;tier name=&quot;SECRET GARDEN&quot;&gt;
    &lt;level name=&quot;bean stalking&quot; file=&quot;Garden\bean_stalking.xml&quot;/&gt;
    &lt;level name=&quot;thorn apart&quot; file=&quot;Garden\thorn_apart.xml&quot;/&gt;
  &lt;/tier&gt;
  &lt;!--&lt;tier name=&quot;Obstacle ***TEST***&quot;&gt;
    &lt;level name=&quot;Nightmare 0&quot; file=&quot;test\Obstacle\nightmare\0.xml&quot; /&gt;
    &lt;level name=&quot;Nightmare 1&quot; file=&quot;test\Obstacle\nightmare\1.xml&quot; /&gt;
    &lt;level name=&quot;Bean 0&quot; file=&quot;test\Obstacle\bean\0.xml&quot; /&gt;
    &lt;level name=&quot;Bean 1&quot; file=&quot;test\Obstacle\bean\1.xml&quot; /&gt;
    &lt;level name=&quot;Dream 0&quot; file=&quot;test\Obstacle\dream\0.xml&quot; /&gt;
    &lt;level name=&quot;Dream 1&quot; file=&quot;test\Obstacle\dream\1.xml&quot; /&gt;
  &lt;/tier&gt;--&gt;
  &lt;!--&lt;tier name=&quot;Death ***TEST***&quot;&gt;
    &lt;level name=&quot;Monster 0&quot; file=&quot;test\death\0.xml&quot; /&gt;
  &lt;/tier&gt;--&gt;
  &lt;!--&lt;tier name=&quot;Monster ***TEST***&quot;&gt;
    &lt;level name=&quot;0&quot; file=&quot;test\Monsters\0.xml&quot; /&gt;
    &lt;level name=&quot;1&quot; file=&quot;test\Monsters\1.xml&quot; /&gt;
    &lt;level name=&quot;2&quot; file=&quot;test\Monsters\2.xml&quot; /&gt;
    &lt;level name=&quot;3&quot; file=&quot;test\Monsters\3.xml&quot; /&gt;
    &lt;level name=&quot;4&quot; file=&quot;test\Monsters\4.xml&quot; /&gt;
    &lt;level name=&quot;5&quot; file=&quot;test\Monsters\5.xml&quot; /&gt;
    &lt;level name=&quot;6&quot; file=&quot;test\Monsters\6.xml&quot; /&gt;
    &lt;level name=&quot;7&quot; file=&quot;test\Monsters\7.xml&quot; /&gt;
    &lt;level name=&quot;8&quot; file=&quot;test\Monsters\8.xml&quot; /&gt;
    &lt;level name=&quot;9&quot; file=&quot;test\Monsters\9.xml&quot; /&gt;
    &lt;level name=&quot;10&quot; file=&quot;test\Monsters\10.xml&quot; /&gt;
  &lt;/tier&gt;--&gt;
  &lt;!--&lt;tier name=&quot;MEDALS *****TEST******&quot;&gt;
    &lt;level name=&quot;gold&quot; file=&quot;test\Medals\gold.xml&quot;&gt;&lt;/level&gt;
    &lt;level name=&quot;silver&quot; file=&quot;test\Medals\silver.xml&quot;&gt;&lt;/level&gt;
    &lt;level name=&quot;bronze&quot; file=&quot;test\Medals\bronze.xml&quot;&gt;&lt;/level&gt;
  &lt;/tier&gt;
  &lt;tier name=&quot;Buttons ***TEST***&quot;&gt;
    &lt;level name=&quot;1&quot; file=&quot;test\Buttons\single.xml&quot; /&gt;
    &lt;level name=&quot;Lots&quot; file=&quot;test\Buttons\multiple.xml&quot; /&gt;
  &lt;/tier&gt;
  &lt;tier name=&quot;Obstacles ***TEST***&quot;&gt;
    &lt;level name=&quot;Cape&quot; file=&quot;test\PowerUps\0.xml&quot; /&gt;
  &lt;/tier&gt;--&gt;
&lt;/tiers&gt;
</pre></p><p>Tiers that are commented out are ignored and the included levels aren’t on the game list. Also, the paths indicated for each <strong>file</strong> attribute—for each individual tier—are relative to the game folder itself. There is no limit on the number of subfolders that can be included in the path. The above structure will render this level set:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image002%5B3%5D-6.jpg"><img title="clip_image002" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image002_thumb-7.jpg" alt="clip_image002" width="640" height="360" border="0"></a></p><h4>The Level XML</h4><p>Let’s now take a look at the layout of the level descriptor XML file:</p><p><pre class="brush: xml">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
&lt;level type=&quot;0&quot;&gt;
  &lt;meta score=&quot;0&quot; buttonPrice=&quot;10&quot;&gt;&lt;/meta&gt;
  &lt;bear maxHealth=&quot;100&quot; startPosition=&quot;300&quot; velocity=&quot;8.0&quot; damage=&quot;11&quot; criticalDamage=&quot;20&quot; defaultAmmo=&quot;100&quot; /&gt;
  &lt;obstacles&gt;
    &lt;obstacle type=&quot;1&quot; x=&quot;119&quot; y=&quot;2300&quot; inflictsDamage=&quot;true&quot; healthDamage=&quot;5&quot; rotation=&quot;3.14&quot; scale=&quot;1&quot; /&gt;
    &lt;obstacle type=&quot;3&quot; x=&quot;534.5&quot; y=&quot;3000&quot; inflictsDamage=&quot;true&quot; healthDamage=&quot;5&quot; rotation=&quot;0&quot; scale=&quot;1&quot; /&gt;
    &lt;obstacle type=&quot;3&quot; x=&quot;534.5&quot; y=&quot;3300&quot; inflictsDamage=&quot;true&quot; healthDamage=&quot;5&quot; rotation=&quot;0&quot; scale=&quot;1&quot; /&gt;
    &lt;obstacle type=&quot;1&quot; x=&quot;119&quot; y=&quot;4200&quot; inflictsDamage=&quot;true&quot; healthDamage=&quot;5&quot; rotation=&quot;3.14&quot; scale=&quot;1&quot; /&gt;
    &lt;obstacle type=&quot;2&quot; x=&quot;546&quot; y=&quot;5000&quot; inflictsDamage=&quot;true&quot; healthDamage=&quot;5&quot; rotation=&quot;0&quot; scale=&quot;1&quot; /&gt;
    &lt;obstacle type=&quot;1&quot; x=&quot;119&quot; y=&quot;5800&quot; inflictsDamage=&quot;true&quot; healthDamage=&quot;5&quot; rotation=&quot;3.14&quot; scale=&quot;1&quot; /&gt;
    &lt;obstacle type=&quot;2&quot; x=&quot;546&quot; y=&quot;6600&quot; inflictsDamage=&quot;true&quot; healthDamage=&quot;5&quot; rotation=&quot;0&quot; scale=&quot;1&quot; /&gt;
  &lt;/obstacles&gt;
  &lt;monsters&gt;
    &lt;monster lifetime=&quot;3000&quot; scale=&quot;.2&quot; velocityX=&quot;2&quot; velocityY=&quot;2&quot; type=&quot;0&quot; x=&quot;460&quot; y=&quot;19900&quot; maxHealth=&quot;80&quot; bonus=&quot;100&quot; lives=&quot;0&quot; damage=&quot;10&quot; criticalDamage=&quot;8&quot; defaultAmmo=&quot;50&quot; /&gt;
    &lt;monster lifetime=&quot;3000&quot; scale=&quot;.2&quot; velocityX=&quot;2&quot; velocityY=&quot;2&quot; type=&quot;1&quot; x=&quot;460&quot; y=&quot;25000&quot; maxHealth=&quot;80&quot; bonus=&quot;100&quot; lives=&quot;0&quot; damage=&quot;10&quot; criticalDamage=&quot;8&quot; defaultAmmo=&quot;50&quot; /&gt;
    &lt;monster lifetime=&quot;3000&quot; scale=&quot;.2&quot; velocityX=&quot;2&quot; velocityY=&quot;2&quot; type=&quot;2&quot; x=&quot;460&quot; y=&quot;34500&quot; maxHealth=&quot;80&quot; bonus=&quot;100&quot; lives=&quot;0&quot; damage=&quot;10&quot; criticalDamage=&quot;8&quot; defaultAmmo=&quot;50&quot; /&gt;
    &lt;monster lifetime=&quot;6000&quot; scale=&quot;.4&quot; velocityX=&quot;2&quot; velocityY=&quot;2&quot; type=&quot;3&quot; x=&quot;460&quot; y=&quot;41400&quot; maxHealth=&quot;180&quot; bonus=&quot;100&quot; lives=&quot;0&quot; damage=&quot;17&quot; criticalDamage=&quot;8&quot; defaultAmmo=&quot;50&quot; /&gt;
  &lt;/monsters&gt;
  &lt;buttons&gt;
    &lt;button x=&quot;300&quot; y=&quot;800&quot; /&gt;
    &lt;button x=&quot;360&quot; y=&quot;800&quot; /&gt;
    &lt;button x=&quot;300&quot; y=&quot;860&quot; /&gt;
    &lt;button x=&quot;360&quot; y=&quot;860&quot; /&gt;
    &lt;button x=&quot;300&quot; y=&quot;920&quot; /&gt;
    &lt;button x=&quot;360&quot; y=&quot;920&quot; /&gt;
    &lt;button x=&quot;300&quot; y=&quot;980&quot; /&gt;
    &lt;button x=&quot;360&quot; y=&quot;980&quot; /&gt;
  &lt;/buttons&gt;
  &lt;powerups&gt;
    &lt;powerup category=&quot;1&quot; type=&quot;4&quot; x=&quot;140&quot; y=&quot;9200&quot; effect=&quot;3&quot; lifespan=&quot;4&quot;&gt;&lt;/powerup&gt;
    &lt;powerup category=&quot;1&quot; type=&quot;3&quot; x=&quot;480&quot; y=&quot;19800&quot; effect=&quot;10&quot; lifespan=&quot;6&quot;&gt;&lt;/powerup&gt;
    &lt;powerup category=&quot;1&quot; type=&quot;0&quot; x=&quot;480&quot; y=&quot;27500&quot; effect=&quot;10&quot; lifespan=&quot;6&quot;&gt;&lt;/powerup&gt;
    &lt;powerup category=&quot;1&quot; type=&quot;1&quot; x=&quot;100&quot; y=&quot;34000&quot; effect=&quot;10&quot; lifespan=&quot;6&quot;&gt;&lt;/powerup&gt;
    &lt;powerup category=&quot;1&quot; type=&quot;0&quot; x=&quot;100&quot; y=&quot;41200&quot; effect=&quot;10&quot; lifespan=&quot;6&quot;&gt;&lt;/powerup&gt;
  &lt;/powerups&gt;
&lt;/level&gt;
</pre></p><p>The opening <strong>level</strong> tag carries a type attribute. This is level theme flag. It can be set to one of the three four values:</p><ul><li><strong>0</strong> – The Nightmare Theme </li><li><strong>1</strong> – The Magic Bean Theme </li><li><strong>2</strong> – The Dream Theme </li><li><strong>3</strong> – The Space Theme </li></ul><p>You can see the design differences in the images below:</p><table border="0" cellspacing="0" cellpadding="0"><tbody><tr><td valign="top" width="360"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image004%5B3%5D-4.jpg"><img title="clip_image004" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image004_thumb-5.jpg" alt="clip_image004" width="270" height="270" border="0"></a></p></td><td valign="top" width="360"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image006%5B3%5D-2.jpg"><img title="clip_image006" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image006_thumb-3.jpg" alt="clip_image006" width="269" height="270" border="0"></a></p></td></tr><tr><td valign="top" width="360"><p>Nightmare</p></td><td valign="top" width="360"><p>Magic Bean</p></td></tr><tr><td valign="top" width="719">&nbsp;</td></tr><tr><td valign="top" width="360"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image008%5B3%5D-3.jpg"><img title="clip_image008" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image008_thumb-4.jpg" alt="clip_image008" width="269" height="270" border="0"></a></p></td><td valign="top" width="360"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image010%5B3%5D-1.jpg"><img title="clip_image010" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image010_thumb-2.jpg" alt="clip_image010" width="269" height="270" border="0"></a></p></td></tr><tr><td valign="top" width="360"><p>Dream</p></td><td valign="top" width="360"><p>Space</p></td></tr></tbody></table><p>Remember, that obstacles and the level theme itself do not influence much other than the background and soundboard.</p><p>Once the type is specified, the <strong>meta</strong> tag brings up the <strong>score</strong> and <strong>buttonPrice</strong> attributes. If you for some reason want to create a level including an initial score, you can specify it here. And because buttons are fixed bonus assets that are all created equal, each of them carries a given bonus point weight. The score based on the collected buttons is calculated at the end of the game and relies on the value specified in the <strong>meta</strong> tag.</p><h4>Obstacles</h4><p>Next comes the obstacle collection, which is represented by the <strong>obstacles</strong> tag. This tag is required even if there are no obstacles on a given level. Simply use <strong>&lt;obstacles /&gt;</strong> as necessary. Each child node represents an instance of an obstacle that can be choosen from the following enum:</p><p><pre class="brush: cpp">
enum class ObstacleType
{
    OT_CLOUD = 0,
    OT_SPIKE_NIGHTMARE_LARGE = 1,
    OT_SPIKE_NIGHTMARE_MEDIUM = 2,
    OT_SPIKE_NIGHTMARE_SMALL = 3,
    OT_BEAN_A = 4,
    OT_BEAN_B = 5,
    OT_BEAN_C = 6,
    OT_BEAN_D = 7,
    OT_BEAN_E = 8,
    OT_SPACE_ROCKET = 9,
    OT_SPACE_COMET_A = 10,
    OT_SPACE_COMET_B = 11,
    OT_SPACE_SATELLITE = 12,
    OT_SPACE_UFO = 13,
    OT_SPACE_BALL = 14
};
</pre></p><p>Here is the complete table showing the appearance of each of them:</p><table border="0" cellspacing="0" cellpadding="0"><tbody><tr><td width="246"><p>OT_CLOUD</p></td><td valign="top" width="474"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image012%5B3%5D-3.jpg"><img title="clip_image012" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image012_thumb-3.jpg" alt="clip_image012" width="285" height="103" border="0"></a></p></td></tr><tr><td valign="top" width="246">&nbsp;</td><td valign="top" width="474">&nbsp;</td></tr><tr><td width="246"><p>OT_SPIKE_NIGHTMARE_LARGE</p></td><td valign="top" width="474"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image014%5B3%5D-3.jpg"><img title="clip_image014" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image014_thumb-3.jpg" alt="clip_image014" width="126" height="116" border="0"></a></p></td></tr><tr><td width="246">&nbsp;</td><td valign="top" width="474">&nbsp;</td></tr><tr><td width="246"><p>OT_SPIKE_NIGHTMARE_MEDIUM</p></td><td valign="top" width="474"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image016%5B3%5D-2.jpg"><img title="clip_image016" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image016_thumb-3.jpg" alt="clip_image016" width="234" height="131" border="0"></a></p></td></tr><tr><td width="246">&nbsp;</td><td valign="top" width="474">&nbsp;</td></tr><tr><td width="246"><p>OT_SPIKE_NIGHTMARE_SMALL</p></td><td valign="top" width="474"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image018%5B3%5D-2.jpg"><img title="clip_image018" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image018_thumb-2.jpg" alt="clip_image018" width="245" height="126" border="0"></a></p></td></tr><tr><td width="246">&nbsp;</td><td valign="top" width="474">&nbsp;</td></tr><tr><td width="246"><p>OT_BEAN_A</p></td><td valign="top" width="474"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image020%5B3%5D-1.jpg"><img title="clip_image020" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image020_thumb-1.jpg" alt="clip_image020" width="281" height="174" border="0"></a></p></td></tr><tr><td width="246">&nbsp;</td><td valign="top" width="474">&nbsp;</td></tr><tr><td width="246"><p>OT_BEAN_B</p></td><td valign="top" width="474"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image022%5B3%5D-1.jpg"><img title="clip_image022" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image022_thumb-1.jpg" alt="clip_image022" width="133" height="165" border="0"></a></p></td></tr><tr><td width="246">&nbsp;</td><td valign="top" width="474">&nbsp;</td></tr><tr><td width="246"><p>OT_BEAN_C</p></td><td valign="top" width="474"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image024%5B3%5D-1.jpg"><img title="clip_image024" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image024_thumb-1.jpg" alt="clip_image024" width="179" height="152" border="0"></a></p></td></tr><tr><td width="246">&nbsp;</td><td valign="top" width="474">&nbsp;</td></tr><tr><td width="246"><p>OT_BEAN_D</p></td><td valign="top" width="474"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image026%5B3%5D-1.jpg"><img title="clip_image026" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image026_thumb-1.jpg" alt="clip_image026" width="197" height="198" border="0"></a></p></td></tr><tr><td width="246">&nbsp;</td><td valign="top" width="474">&nbsp;</td></tr><tr><td width="246"><p>OT_BEAN_E</p></td><td valign="top" width="474"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image028%5B3%5D-1.jpg"><img title="clip_image028" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image028_thumb-1.jpg" alt="clip_image028" width="217" height="181" border="0"></a></p></td></tr><tr><td width="246">&nbsp;</td><td valign="top" width="474">&nbsp;</td></tr><tr><td width="246"><p>OT_SPACE_ROCKET</p></td><td valign="top" width="474"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image030%5B3%5D-1.jpg"><img title="clip_image030" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image030_thumb-1.jpg" alt="clip_image030" width="165" height="181" border="0"></a></p></td></tr><tr><td valign="top" width="246">&nbsp;</td><td valign="top" width="474">&nbsp;</td></tr><tr><td width="246"><p>OT_SPACE_COMET_A</p></td><td valign="top" width="474"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image032%5B3%5D-1.jpg"><img title="clip_image032" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image032_thumb-1.jpg" alt="clip_image032" width="186" height="186" border="0"></a></p></td></tr><tr><td width="246">&nbsp;</td><td valign="top" width="474">&nbsp;</td></tr><tr><td width="246"><p>OT_SPACE_COMET_B</p></td><td valign="top" width="474"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image034%5B3%5D.jpg"><img title="clip_image034" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image034_thumb.jpg" alt="clip_image034" width="131" height="132" border="0"></a></p></td></tr><tr><td width="246">&nbsp;</td><td valign="top" width="474">&nbsp;</td></tr><tr><td width="246"><p>OT_SPACE_SATELLITE</p></td><td valign="top" width="474"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image036%5B3%5D.jpg"><img title="clip_image036" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image036_thumb.jpg" alt="clip_image036" width="150" height="197" border="0"></a></p></td></tr><tr><td width="246">&nbsp;</td><td valign="top" width="474">&nbsp;</td></tr><tr><td width="246"><p>OT_SPACE_UFO</p></td><td valign="top" width="474"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image038%5B3%5D.jpg"><img title="clip_image038" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image038_thumb.jpg" alt="clip_image038" width="202" height="187" border="0"></a></p></td></tr><tr><td width="246">&nbsp;</td><td valign="top" width="474">&nbsp;</td></tr><tr><td width="246"><p>OT_SPACE_BALL</p></td><td valign="top" width="474"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image040%5B3%5D.jpg"><img title="clip_image040" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image040_thumb.jpg" alt="clip_image040" width="179" height="189" border="0"></a></p></td></tr></tbody></table><p>No matter how the obstacles are positioned, they will either be located in the visible area or displaced outside the viewport and not displayed. The ultimate position is taken from the obstacle size and is relative to the center of the texture. For example, if an obstacle texture is 400- pixels wide, the X-relative position should be set to 200. If the position differs from the starting one, however, the obstacle texture is cut to include the area that fits in the 768 pixel wide playable zone visible. There are no restrictions regarding the Y position.</p><p>To help in level creation, some obstacles have pre-defined left and right margins. For example:</p><ul><li><strong>OT_BEAN_A:</strong> 269.5 (Left), 498.5 (right, with 3.14 rotation) </li><li><strong>OT_BEAN_B:</strong> 128.5 (left), 638.5 (right, with 3.14 rotation) </li><li><strong>OT_BEAN_C:</strong> 172 (left), 596 (right, with 3.14 rotation) </li><li><strong>OT_BEAN_D:</strong> 188.5 (left), 579.5 (right, with 3.14 rotation) </li><li><strong>OT_BEAN_E:</strong> 206.5 (left), 561.5 (right, with 3.14 rotation) </li></ul><p>The <strong>inflictsDamage</strong> attribute determines whether the obstacle harms the main character. If it is set to <strong>false</strong>, the character will still make the sound of colliding with it but will not lose any health points. The primary use for this attribute is level testing.If it is set to <strong>true</strong>, the character will loose the amount of health points indicated by the <strong>healthDamage</strong> attribute.</p><p>The <strong>rotation</strong> and <strong>scale</strong> attributes can be used to flip and resize the texture as needed. Rotation is measured in radians, and the scale is a normalized value in which 1.0 represents 100% of the scale.</p><h4>Monsters</h4><p>As with obstacles, the <strong>monsters</strong> node should never be omitted from the file and should at least contain a placeholder: <strong>&lt;monsters /&gt;</strong>. Unlike obstacles, however, monsters are dynamic and do not have fixed positions. Moreover, monsters have limited active time during gameplay. The first attribute,<strong>lifetime</strong>, determines the length of the fall during which the monster will be visible in the viewport. With the <strong>y</strong> attribute as the Y-based position at which the monster appears, at the <strong>y&#43;lifetime</strong> position the monster simply flies away if not killed.</p><p>The <strong>scale</strong> attribute carries the same purpose as the one for the obstacle—normalized texture size relative to the size of the original image file. As such, the level designer does not have to worry about linking the width and height of the monster when resizing and can instead use a percentage-like value to scale the monster up or down, simultaneously modifying both the width and the height with zero stretching.</p><p>Nextup are <strong>velocityX</strong> and <strong>velocityY</strong>. These two attributes are used to set the motion velocity when the monster is already visible. Instead of being a static shooting entity, the enemy moves on a randomized zig-zag path at the bottom of the screen. The horizontal and vertical displacement—in pixels, per update cycle—is individually set through the values carried by the above-mentioned attributes. If necessary, this functionality can be disabled in the code-behind by assigning a fixed value for the vertical and horizontal movement for all monsters that are being loaded on a given level.</p><p>The monster type is an <strong>integer</strong> value that is translated in a value from the following enum (located in <strong>MonsterType.h</strong>):</p><p><pre class="brush: cpp">
enum class MonsterType
{
    MT_NIGHTMARE_A = 0,
    MT_NIGHTMARE_B = 1,
    MT_NIGHTMARE_C = 2,
    MT_MAGICBEAN_A = 3,
    MT_MAGICBEAN_B = 4,
    MT_MAGICBEAN_C = 5,
    MT_CANDYLAND_A = 6,
    MT_CANDYLAND_B = 7,
    MT_CANDYLAND_C = 8,
    MT_CANDYLAND_D = 9,
    MT_CANDYLAND_E = 10
};
</pre></p><p>Here is a table that shows the texture associated with each identifier:</p><table border="0" cellspacing="0" cellpadding="0"><tbody><tr><td width="162"><p>MT_NIGHTMARE_A</p></td><td valign="top" width="216"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image042%5B3%5D.jpg"><img title="clip_image042" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image042_thumb.jpg" alt="clip_image042" width="132" height="130" border="0"></a></p></td></tr><tr><td width="162">&nbsp;</td><td valign="top" width="216">&nbsp;</td></tr><tr><td width="162"><p>MT_NIGHTMARE_B</p></td><td valign="top" width="216"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image044%5B3%5D.jpg"><img title="clip_image044" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image044_thumb.jpg" alt="clip_image044" width="111" height="140" border="0"></a></p></td></tr><tr><td width="162">&nbsp;</td><td valign="top" width="216">&nbsp;</td></tr><tr><td width="162"><p>MT_NIGHTMARE_C</p></td><td valign="top" width="216"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image046%5B3%5D.jpg"><img title="clip_image046" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image046_thumb.jpg" alt="clip_image046" width="79" height="139" border="0"></a></p></td></tr><tr><td width="162">&nbsp;</td><td valign="top" width="216">&nbsp;</td></tr><tr><td width="162"><p>MT_MAGICBEAN_A</p></td><td valign="top" width="216"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image048%5B3%5D.jpg"><img title="clip_image048" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image048_thumb.jpg" alt="clip_image048" width="200" height="136" border="0"></a></p></td></tr><tr><td width="162">&nbsp;</td><td valign="top" width="216">&nbsp;</td></tr><tr><td width="162"><p>MT_MAGICBEAN_B</p></td><td valign="top" width="216"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image050%5B3%5D.jpg"><img title="clip_image050" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image050_thumb.jpg" alt="clip_image050" width="74" height="139" border="0"></a></p></td></tr><tr><td width="162">&nbsp;</td><td valign="top" width="216">&nbsp;</td></tr><tr><td width="162"><p>MT_MAGICBEAN_C</p></td><td valign="top" width="216"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image052%5B3%5D.jpg"><img title="clip_image052" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image052_thumb.jpg" alt="clip_image052" width="123" height="140" border="0"></a></p></td></tr><tr><td width="162">&nbsp;</td><td valign="top" width="216">&nbsp;</td></tr><tr><td width="162"><p>MT_CANDYLAND_A</p></td><td valign="top" width="216"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image054%5B3%5D.jpg"><img title="clip_image054" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image054_thumb.jpg" alt="clip_image054" width="94" height="106" border="0"></a></p></td></tr><tr><td width="162">&nbsp;</td><td valign="top" width="216">&nbsp;</td></tr><tr><td width="162"><p>MT_CANDYLAND_B</p></td><td valign="top" width="216"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image056%5B3%5D.jpg"><img title="clip_image056" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image056_thumb.jpg" alt="clip_image056" width="64" height="117" border="0"></a></p></td></tr><tr><td width="162">&nbsp;</td><td valign="top" width="216">&nbsp;</td></tr><tr><td width="162"><p>MT_CANDYLAND_C</p></td><td valign="top" width="216"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image058%5B3%5D.jpg"><img title="clip_image058" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image058_thumb.jpg" alt="clip_image058" width="121" height="140" border="0"></a></p></td></tr><tr><td width="162">&nbsp;</td><td valign="top" width="216">&nbsp;</td></tr><tr><td width="162"><p>MT_CANDYLAND_D</p></td><td valign="top" width="216"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image060%5B3%5D.jpg"><img title="clip_image060" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image060_thumb.jpg" alt="clip_image060" width="187" height="138" border="0"></a></p></td></tr><tr><td width="162">&nbsp;</td><td valign="top" width="216">&nbsp;</td></tr><tr><td width="162"><p>MT_CANDYLAND_E</p></td><td valign="top" width="216"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image062%5B3%5D.jpg"><img title="clip_image062" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image062_thumb.jpg" alt="clip_image062" width="123" height="139" border="0"></a></p></td></tr><tr><td width="162">&nbsp;</td><td valign="top" width="216">&nbsp;</td></tr></tbody></table><p>Each monster has three separate textures associated with it. The three textures are cycled inside the update loop for each monster entity when the monster becomes visible, creating the movement effect:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image063%5B3%5D.png"><img title="clip_image063" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image063_thumb.png" alt="clip_image063" width="444" height="155" border="0"></a></p><p>Each monster currently shoots only one type of ammo: a red plasma ball. Be aware, however, that there is a preprogrammed condition in which the last monster in the XML file collection is automatically considered the final boss. This means the <strong>scale</strong>, <strong>maxHealth</strong> and <strong>lifetime</strong> properties must be manually adjusted to reflect the effect. Without doing so, the last monster will, regardless of the XML setting, switch in-game to a triple fireball shot that inflicts three times the damage indicated by the <strong>damage</strong> attribute:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image065%5B3%5D.jpg"><img title="clip_image065" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image065_thumb.jpg" alt="clip_image065" width="345" height="279" border="0"></a></p><p>Each monster can have limited ammo as set by the <strong>defaultAmmo</strong> attribute. In the case that the ammo is exhausted before the monster expires, the monster will continue its motion at the bottom of the screen without inflicting direct damage to the main character.</p><h4>Buttons</h4><p>These are the least complex entities and only carry an X and a Y position. Given those coordinates, relative to the left margin of the visible area, a button texture is rendered:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image067%5B3%5D.jpg"><img title="clip_image067" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image067_thumb.jpg" alt="clip_image067" width="408" height="258" border="0"></a></p><p>Once picked-up, the button counter is increased by one and the meta-score incremented by the value set in the <strong>meta</strong> tag at the beginning of the level XML as long as the feature is activated in the code-behind.</p><h4>Power-ups</h4><p>To make the game more fun, there are bonus elements that can be picked up by the bear in order to enhance its performance or protection. These elements are declared in the <strong>&lt;powerups/&gt;</strong> collection. First and foremost, it is important to declare whether the power-up is positive or negative. In the current version of FallFury, only positive power-ups are included. Nonetheless, the harness for negative ones is already integrated in the parser. Therefore, the <strong>category</strong> attribute should be set to 1 if the power-up has a positive effect and 0 for a negative effect. This value will only have an effect over the sound played when the bonus is collected.</p><p>The power-up type can be one of the following (enum located in <strong>PoweupType.h</strong>):</p><p><pre class="brush: cpp">
enum class PowerupType
{
    HEALTH = 0,
    HELMET = 1,
    PARACHUTE = 2,
    BUBBLE = 3,
    CAPE = 4,
    AXE = 5,
    BOOMERANG = 6,
    HAMMER = 7,
    KNIFE = 8,
    PLASMA_BALL = 9,
    CIRCLE = 10
};
</pre></p><p>&nbsp;</p><p>The table below shows the power-up texture appearance. Behaviors are already defined in the game and influenced by only the <strong>effect</strong> and <strong>lifespan</strong> (seconds) attributes:</p><table border="1" cellspacing="0" cellpadding="0"><tbody><tr><td width="120"><p>HEALTH</p></td><td width="360"><p>Restores the character health, incremented by the value in <strong>effect</strong>. The <strong>lifespan</strong> attribute is ignored.</p></td><td valign="top" width="72"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image069%5B3%5D.jpg"><img title="clip_image069" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image069_thumb.jpg" alt="clip_image069" width="52" height="52" border="0"></a></p></td></tr><tr><td width="120"><p>HELMET</p></td><td width="360"><p>Adds a helmet to the bear, setting the maximum health to the <strong>effect</strong> value. Active for the duration of <strong>lifespan</strong>.</p></td><td valign="top" width="72"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image071%5B3%5D.jpg"><img title="clip_image071" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image071_thumb.jpg" alt="clip_image071" width="51" height="53" border="0"></a></p></td></tr><tr><td width="120"><p>PARACHUTE</p></td><td width="360"><p>Slows down the fall of the bear, setting the descent velocity to the <strong>effect</strong> value. Active for the duration of <strong>lifespan</strong>.</p></td><td valign="top" width="72"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image073%5B3%5D.jpg"><img title="clip_image073" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image073_thumb.jpg" alt="clip_image073" width="52" height="52" border="0"></a></p></td></tr><tr><td width="120"><p>BUBBLE</p></td><td width="360"><p>Wraps the character in a protective bubble, setting the maximum health to the value of the <strong>effect</strong> attribute. Active for the duration of <strong>lifespan</strong>.</p></td><td valign="top" width="72"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image075%5B3%5D.jpg"><img title="clip_image075" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image075_thumb.jpg" alt="clip_image075" width="52" height="50" border="0"></a></p></td></tr><tr><td width="120"><p>CAPE</p></td><td width="360"><p>Accelerates the descent by multiplying the velocity by the value of <strong>effect</strong>. Active for the duration of <strong>lifespan</strong>.</p></td><td valign="top" width="72"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image077%5B3%5D.jpg"><img title="clip_image077" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image077_thumb.jpg" alt="clip_image077" width="52" height="52" border="0"></a></p></td></tr><tr><td width="120"><p>AXE</p></td><td width="360"><p>Sets the current character weapon to an axe. The damage is determined by the <strong>effect</strong> attribute and <strong>lifespan</strong> is ignored.</p></td><td valign="top" width="72"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image079%5B3%5D.jpg"><img title="clip_image079" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image079_thumb.jpg" alt="clip_image079" width="52" height="54" border="0"></a></p></td></tr><tr><td width="120"><p>BOOMERANG</p></td><td width="360"><p>Sets the current character weapon to a boomerang. The damage is determined by the <strong>effect</strong> attribute and <strong>lifespan</strong> is ignored.</p></td><td valign="top" width="72"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image081%5B3%5D.jpg"><img title="clip_image081" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image081_thumb.jpg" alt="clip_image081" width="51" height="52" border="0"></a></p></td></tr><tr><td width="120"><p>HAMMER</p></td><td width="360"><p>Sets the current character weapon to a hammer. The damage is determined by the <strong>effect</strong> attribute and <strong>lifespan</strong> is ignored.</p></td><td valign="top" width="72"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image083%5B3%5D.jpg"><img title="clip_image083" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image083_thumb.jpg" alt="clip_image083" width="52" height="52" border="0"></a></p></td></tr><tr><td width="120"><p>KNIFE</p></td><td width="360"><p>Sets the current character weapon to a knife. The damage is determined by the <strong>effect</strong> attribute and <strong>lifespan</strong> is ignored.</p></td><td valign="top" width="72"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image085%5B3%5D.jpg"><img title="clip_image085" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image085_thumb.jpg" alt="clip_image085" width="52" height="52" border="0"></a></p></td></tr><tr><td width="120"><p>PLASMA_BALL</p></td><td width="360"><p>Sets the current character weapon to a plasma ball. The damage is determined by the <strong>effect</strong> attribute and <strong>lifespan</strong> is ignored.</p></td><td valign="top" width="72"><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image087%5B3%5D.jpg"><img title="clip_image087" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image087_thumb.jpg" alt="clip_image087" width="54" height="52" border="0"></a></p></td></tr></tbody></table><p>CIRCLE is a helper power-up that has no effect on the bear and is instead used as an additional texture overlay along with any other power-up in order to create a pulsating circle effect.</p><h4>Conclusion</h4><p>FallFury ships with a dozen of sample levels that showcase all of the elements described in the article. At the moment, a level editor is in the works, but it isn’t too complicated to build XML files manually. To do so, you need to consider the pixel-based locations and ensure that they’re all in the visible area—the game engine will automatically handle all other displacements and adjustments.</p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/DennisDel/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:3a3c8f6f0baa49dab538a14a01384bb7">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-5-Creating-Levels</comments>
      <itunes:summary>Creating LevelsOne of the goals set when developing FallFury was making the game extensible in regards to playable levels. Furthermore, I thought that it would make sense from the development and testing perspective to have levels as a completely separate entity that can be modified as necessary. For example, when a new power-up was introduced, I wanted to add an extra line in a level file and test it out. This was ultimately achieved by creating an XML-based level engine and in this article I will describe the level structure and design process. Check out the video for this article at http://channel9.msdn.com/Series/FallFury/Part-5-Creating-Levels.&amp;nbsp; For a complete, offline version of this series, you may download a nicely formatted PDF of all the articles. The First StepsWhen I started working on the level engine concept, I began designing the potential XML file structure for the level and ended up with the following requirements: Level Type Identifier – As different levels have different backgrounds and sound themes, there should be a way to mark a level type. There are currently four level types: dream, nightmare, space, and magic bean. The Starting Character Descriptor – When the game starts, the teddy bear has some initial, basic properties, such as maximum health level, horizontal position, and velocity. A Collection of Obstacles – For each level, obstacles are positioned differently, and it’s important to specify that. For some obstacles it might be desirable to disable the damage infliction component, while for others it might be good to maximize the damage caused by colliding with them. Also, there are multiple textures associated with different obstacle types, so I wanted to specify the obstacles to render regardless of the selected level type. A Collection of Monsters – Obstacles are not the only component that can damage the bear during gameplay. There are also monsters that can pop up and shoot at the main character. Similar to the bear, monsters r</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-5-Creating-Levels</link>
      <pubDate>Wed, 23 Jan 2013 23:57:11 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-5-Creating-Levels</guid>
      <media:thumbnail url="http://media.ch9.ms/ch9/b079/411aa110-67a6-4cda-9606-e3473f1bb079/FallFuryPart5_100.jpg" height="56" width="100"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/b079/411aa110-67a6-4cda-9606-e3473f1bb079/FallFuryPart5_220.jpg" height="124" width="220"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/b079/411aa110-67a6-4cda-9606-e3473f1bb079/FallFuryPart5_512.jpg" height="289" width="512"></media:thumbnail>      
      <dc:creator>Brian Peek, Clint Rutkas, Dan Fernandez, Den Delimarsky, Rick Barraza</dc:creator>
      <itunes:author>Brian Peek, Clint Rutkas, Dan Fernandez, Den Delimarsky, Rick Barraza</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-5-Creating-Levels/RSS</wfw:commentRss>
      <category>C#</category>
      <category>C++</category>
      <category>DirectX</category>
      <category>Windows Store App</category>
    </item>
  <item>
      <title>Fall Fury: Part 4 - XAML Interop</title>
      <description><![CDATA[<p>As mentioned earlier in the series, FallFury does not solely rely on DirectX to display content to the user. As a Windows Store game, FallFury leverages the new <a href="http://msdn.microsoft.com/en-us/library/windows/apps/hh825871.aspx">Direct2D (XAML) project template</a>, available in Visual Studio 2012.&nbsp; Check out the video for this article at <a href="http://channel9.msdn.com/Series/FallFury/Part-4-XAML-Interop">http://channel9.msdn.com/Series/FallFury/Part-4-XAML-Interop</a>.&nbsp; For a complete, offline version of this series, you may <a href="http://media.ch9.ms/coding4fun/fallfury/FallFury.pdf">download a nicely formatted PDF of all the articles</a>.</p><h4>The Concept of a Swap Chain</h4><p>Before I go into detail about the DirectX and XAML interop in FallFury, I want to cover one important aspect of DirectX development that you need to familiarize yourself with: the swap chain.</p><p>When your graphics adapter draws on the visual surface, you, as the user, see only minor potential redraws. Internally, however, the device switches buffers that reflect the displayed content, with each buffer representing a frame that has to be drawn. You can deduce from this that any swap chain has at least two buffers that it can switch between.</p><p>For example, if I want to display my character as being displaced by a specific amount of pixels, the buffer will at the outset present to me the character in its initial position, while the second buffer will be constructed in the background with the proper position adjustments. The first frame, made from the content from the first buffer, will be discarded, and then the second frame will be displayed, and so on. This process occurs at a very high speed that depends on the processing capabilities of the graphics adapter, so the user does not notice the swapping itself.</p><p>The most common swap chain is composed of two buffers—the screenbuffer and the secondary framebuffer.</p><h4>SwapChainBackgroundPanel</h4><p>DirectX interoperability with XAML simplifies a lot of routine tasks that would otherwise be handled with manual rendering procedures, such as a menu system or a simple game HUD. That being said, the way the XAML workflow is organized in a Direct2D project is <a href="http://msdn.microsoft.com/en-US/library/windows/apps/hh825871">quite different</a> compared to a standard XAML Windows Store or Windows Phone application.</p><p>The core difference is that there is no navigational system per-se and the fundamental entity in a Direct2D (XAML) project that manages the XAML content is a <a href="http://msdn.microsoft.com/library/windows/apps/Hh702626">SwapChainBackgroundPanel</a> control. This control allows the developer to overlay XAML elements on top of the DirectX renders. It replaces the normal page-based layout with one in which it is sole container for every XAML control that has to be used in the application. This necessitates that you will have to organize the secondary elements in such a way that the correct set is displayed for the current application state.</p><p>For example, if the user is in the main menu, menu options as well as the game logo should be shown. When the user switches to the game mode, the HUD should appear and the menu should become hidden. Although both the menu and the HUD are a part of the same SwapChainBackgroundPanel, I will have to manually manage state and visibility changes.</p><p>Using the SwapChainBackgroundPanel also means that you will have to enforce specific graphic configuration rules in your application. One of them applies to setting up the swap chain. When you set up the scaling, it must be set to <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/hh404526(v=vs.85).aspx">DXGI_SCALING_STRETCH</a>:</p><p><pre class="brush: cpp">
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
swapChainDesc.Width = static_cast&lt;UINT&gt;(m_renderTargetSize.Width); 
swapChainDesc.Height = static_cast&lt;UINT&gt;(m_renderTargetSize.Height);
swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
swapChainDesc.Stereo = false; 
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.BufferCount = 2;
swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
swapChainDesc.Flags = 0;
</pre></p><p>&nbsp;</p><p>The swap chain itself should be configured for composition, mixing the native DirectX buffer with the overlaid XAML. This is done by calling <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/hh404558(v=vs.85).aspx">CreateSwapChainForComposition</a>:</p><p><pre class="brush: cpp">
ThrowIfFailed(
    dxgiFactory-&gt;CreateSwapChainForComposition(
        m_d3dDevice.Get(),
        &amp;swapChainDesc,
        nullptr,
        &amp;m_swapChain
        )
    );

ComPtr&lt;ISwapChainBackgroundPanelNative&gt; panelNative;
ThrowIfFailed(
    reinterpret_cast&lt;IUnknown*&gt;(m_panel)-&gt;QueryInterface(IID_PPV_ARGS(&amp;panelNative))
    );

ThrowIfFailed(
    panelNative-&gt;SetSwapChain(m_swapChain.Get())
    );
</pre></p><p>There really isn’t much additional configuration work beyond this point. Remember, that the XAML content will <strong>always be overlaid on top of the DirectX content</strong>; therefore, plan the game components accordingly.</p><h4>The XAML Menu System</h4><p>The menu is at the core of the FallFury experience. When designing it, I was inspired by how Dance Central built the user interaction mechanism, and I tried to implement a similar approach in which the user would have to slide the button to the right instead of simply tapping on it:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image002%5B3%5D-4.jpg"><img title="clip_image002" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image002_thumb-5.jpg" alt="clip_image002" width="624" height="317" border="0"></a></p><p>Each menu item is built around a custom <strong>MenuItem</strong> control (<strong>MenuItem.xaml</strong>):</p><p><pre class="brush: xml">
&lt;UserControl
    x:Class=&quot;Coding4Fun.FallFury.MenuItem&quot;
    xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
    xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
    xmlns:local=&quot;using:Coding4Fun.FallFury&quot;
    xmlns:d=&quot;http://schemas.microsoft.com/expression/blend/2008&quot;
    xmlns:mc=&quot;http://schemas.openxmlformats.org/markup-compatibility/2006&quot;
    mc:Ignorable=&quot;d&quot;
    x:Name=&quot;menuItem&quot;
    Margin=&quot;10, 0, 0, 10&quot;&gt;

    &lt;Grid 
        Height=&quot;65&quot; 
        ManipulationMode=&quot;TranslateX&quot;
        ManipulationCompleted=&quot;Grid_ManipulationCompleted&quot;
        ManipulationDelta=&quot;Grid_ManipulationDelta&quot; 
        x:Name=&quot;ControlContainer&quot;
        PointerPressed=&quot;Grid_PointerPressed&quot; 
        PointerReleased=&quot;Grid_PointerReleased&quot;&gt;
        
        &lt;Grid.Resources&gt;
            &lt;Storyboard x:Name=&quot;ArrowAnimator&quot;&gt;
                &lt;DoubleAnimation Storyboard.TargetName=&quot;ImageTranslateTransform&quot;
                                 Storyboard.TargetProperty=&quot;X&quot;
                                 From=&quot;0&quot;
                                 To=&quot;20&quot;
                                 Duration=&quot;0:0:0.4&quot;
                                 RepeatBehavior=&quot;Forever&quot;
                                 AutoReverse=&quot;True&quot;&gt;
                &lt;/DoubleAnimation&gt;
            &lt;/Storyboard&gt;

        &lt;/Grid.Resources&gt;
        
        &lt;Grid.RowDefinitions&gt;
            &lt;RowDefinition Height=&quot;10&quot; /&gt;
            &lt;RowDefinition /&gt;
            &lt;RowDefinition /&gt;
            &lt;RowDefinition Height=&quot;10&quot; /&gt;
        &lt;/Grid.RowDefinitions&gt;
        &lt;Grid.ColumnDefinitions&gt;
            &lt;ColumnDefinition Width=&quot;10&quot; /&gt;
            &lt;ColumnDefinition /&gt;
        &lt;/Grid.ColumnDefinitions&gt;
        &lt;StackPanel Orientation=&quot;Horizontal&quot; Grid.RowSpan=&quot;4&quot; Grid.ColumnSpan=&quot;4&quot;&gt;
            &lt;!-- width is sent in code behind, have to get this dynamic ...  --&gt;
            &lt;Grid Width=&quot;350&quot; x:Name=&quot;coverRectangle&quot;&gt;
                &lt;Rectangle Fill=&quot;#303030&quot; /&gt;
                &lt;Rectangle 
                    Fill=&quot;Red&quot; 
                    x:Name=&quot;coverActiveRectangle&quot; /&gt;
            &lt;/Grid&gt;
            &lt;Image x:Name=&quot;MenuImage&quot; Source=&quot;ms-appx:///MenuItems/single_arrow.png&quot; Margin=&quot;10,0,0,0&quot; Stretch=&quot;Uniform&quot;&gt;
                &lt;Image.RenderTransform&gt;
                    &lt;TranslateTransform x:Name=&quot;ImageTranslateTransform&quot;&gt;&lt;/TranslateTransform&gt;
                &lt;/Image.RenderTransform&gt;
            &lt;/Image&gt;
        &lt;/StackPanel&gt;
        &lt;!----&gt;

        &lt;TextBlock 
            Text=&quot;{Binding ElementName=menuItem, RelativeSource={RelativeSource Self}, Path=Label}&quot;
            Grid.RowSpan=&quot;4&quot;
            Grid.ColumnSpan=&quot;4&quot;
            Style=&quot;{StaticResource MenuItemText}&quot;&gt;

        &lt;/TextBlock&gt;
        
        &lt;MediaElement x:Name=&quot;coreMenuMedia&quot; Source=&quot;ms-appx:///Assets/Sounds/MenuTap.wav&quot; AutoPlay=&quot;False&quot;&gt;&lt;/MediaElement&gt;
        &lt;MediaElement x:Name=&quot;slideMenuMedia&quot; Source=&quot;ms-appx:///Assets/Sounds/MenuSlide.wav&quot; AutoPlay=&quot;False&quot;&gt;&lt;/MediaElement&gt;
    &lt;/Grid&gt;
&lt;/UserControl&gt;
</pre></p><p>There is a core storyboard that is used to perform an image bounce. Initial tests showed that that most users tend to follow the standard “click-and-go” pattern and even though the implemented button was a slider, they tried to click it at least once, expecting the game to take them to the next screen. To avoid this, I introduced a visual arrow indicator that bounces left and right to indicate the direction of the necessary slide.</p><p>When the sliding occurs, the overlay grid width is being adjusted relative to the manipulation. At the same time, the button changes from passive state (dark background):</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image003%5B3%5D.png"><img title="clip_image003" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image003_thumb.png" alt="clip_image003" width="423" height="75" border="0"></a></p><p>to active state (red background):</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image004%5B3%5D.png"><img title="clip_image004" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image004_thumb.png" alt="clip_image004" width="465" height="76" border="0"></a></p><p>Internally, the double-arrow image replaces the single-arrow one and is translated across the X-axis to create a bouncing effect:</p><p><pre class="brush: cpp">
void MenuItem::Grid_PointerPressed(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e)
{
    BitmapImage^ image = ref new BitmapImage(ref new Uri(&quot;ms-appx:///MenuItems/double_arrow.png&quot;));
    MenuImage-&gt;Source = image;
    
    coverActiveRectangle-&gt;Visibility = Windows::UI::Xaml::Visibility::Visible;
    ((Storyboard^)ControlContainer-&gt;Resources-&gt;Lookup(&quot;ArrowAnimator&quot;))-&gt;Begin();
    
    coreMenuMedia-&gt;Play();
}
</pre></p><p>As the user drags the finger on the button, the red overlay size should be adjusted accordingly. The size adjustment can be easily tracked in the ManipulationDelta event handler for the focused grid:</p><p><pre class="brush: cpp">
void MenuItem::Grid_ManipulationDelta(Platform::Object^ sender, Windows::UI::Xaml::Input::ManipulationDeltaRoutedEventArgs^ e)
{
    double diff = e-&gt;Cumulative.Translation.X;
    
    if (diff &gt; maxDeltaSize)
    {
        diff = maxDeltaSize;
    }
    else if (diff &lt; 0)
    {
        diff = 0;
    }
    
    coverRectangle-&gt;Width = initialBarWidth &#43; diff;
}
</pre></p><p>When the user action on the button is completed, the ManipulationCompleted event handler is triggered on the same overlay grid. If the relative drag hits the critical threshold, the action linked to the button should be invoked:</p><p><pre class="brush: cpp">
void MenuItem::Grid_ManipulationCompleted(Platform::Object^ sender, Windows::UI::Xaml::Input::ManipulationCompletedRoutedEventArgs^ e)
{
    float diff = e-&gt;Cumulative.Translation.X;
    
    if (diff &gt; maxDeltaSize - 50) // slight buffer
    {
        slideMenuMedia-&gt;Play();
        OnButtonSelected(this, Label);
    }
    
    ResetElements();
}
</pre></p><p>There are also local sound effects that are played when the slider-button is tapped and moved to the end. Both are handled by separate <a href="http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.controls.mediaelement">MediaElement</a> controls that avoid an internal sound file switch, calling instead the <a href="http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.controls.mediaelement.play">Play</a> method as necessary. The <strong>OnButtonSelected</strong> event handler can be dynamically hooked in the application backend.</p><p>Each button also has a visible content area that can display a text label. It can be set through a DependencyProperty:</p><p><pre class="brush: cpp">
DependencyProperty^ MenuItem::_LabelProperty = 
    DependencyProperty::Register(&quot;Label&quot;, 
    Platform::String::typeid,
    MenuItem::typeid, 
    nullptr);
</pre></p><p>In its current configuration, the menu label can be also set in XAML:</p><p><pre class="brush: xml">
&lt;local:MenuItem x:Name=&quot;btnNewGame&quot; Label=&quot;new game&quot;&gt;
    &lt;local:MenuItem.RenderTransform&gt;
        &lt;TranslateTransform&gt;&lt;/TranslateTransform&gt;
    &lt;/local:MenuItem.RenderTransform&gt;
&lt;/local:MenuItem&gt;
</pre></p><p>When the button loses the focus, the state resets to the passive one, stopping the animation and resetting the arrow image to the single one:</p><p><pre class="brush: cpp">
void MenuItem::ResetElements()
{
    BitmapImage^ image = ref new BitmapImage(ref new Uri(&quot;ms-appx:///MenuItems/single_arrow.png&quot;));
    MenuImage-&gt;Source = image;
    
    ((Storyboard^)ControlContainer-&gt;Resources-&gt;Lookup(&quot;ArrowAnimator&quot;))-&gt;Stop();
    
    coverRectangle-&gt;Width = initialBarWidth;
    coverActiveRectangle-&gt;Visibility = Windows::UI::Xaml::Visibility::Collapsed;
}
</pre></p><p>That’s about as complex as the menu item control will get. The menu container itself can be any <a href="http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.controls.grid">Grid</a> or <a href="http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.controls.stackpanel">StackPanel</a> control. The way the menu items are used across the game states, there is no need to have a separate unified container.</p><h4>The Main XAML Container &amp; State Changes</h4><p>Going back to <strong>DirectXPage.xaml</strong>, there are several parts of the XAML layout that should be highlighted. First and foremost, the game curtains—the static parts of the screen that are being displayed instead of blacking out parts of the viewport that are not being used when the game runs in landscape mode. Because the game includes a rectangular frame instead of stretching the entire playable area to the size of the screen, there is an unknown amount of unallocated visual space on both the right and left sides of the frame itself:</p><p><pre class="brush: xml">
&lt;Grid HorizontalAlignment=&quot;Left&quot; x:Name=&quot;containerA&quot;&gt;
    &lt;Rectangle Fill=&quot;#09bbe3&quot; /&gt;

    &lt;Rectangle Width=&quot;10&quot; HorizontalAlignment=&quot;Left&quot;&gt;
        &lt;Rectangle.Fill&gt;
            &lt;LinearGradientBrush StartPoint=&quot;0,0&quot; EndPoint=&quot;1,0&quot;&gt;
                &lt;GradientStop Color=&quot;#a000&quot; Offset=&quot;0.0&quot;&gt;&lt;/GradientStop&gt;
                &lt;GradientStop Color=&quot;#0000&quot; Offset=&quot;1.0&quot;&gt;&lt;/GradientStop&gt;
            &lt;/LinearGradientBrush&gt;
        &lt;/Rectangle.Fill&gt;
    &lt;/Rectangle&gt;
&lt;/Grid&gt;

&lt;Grid HorizontalAlignment=&quot;Right&quot; x:Name=&quot;containerB&quot;&gt;
    &lt;Rectangle Fill=&quot;#09bbe3&quot; /&gt;

    &lt;Rectangle Width=&quot;10&quot; HorizontalAlignment=&quot;Right&quot;&gt;
        &lt;Rectangle.Fill&gt;
            &lt;LinearGradientBrush StartPoint=&quot;1,0&quot; EndPoint=&quot;0,0&quot;&gt;
                &lt;GradientStop Color=&quot;#a000&quot; Offset=&quot;0.0&quot;&gt;&lt;/GradientStop&gt;
                &lt;GradientStop Color=&quot;#0000&quot; Offset=&quot;1.0&quot;&gt;&lt;/GradientStop&gt;
            &lt;/LinearGradientBrush&gt;
        &lt;/Rectangle.Fill&gt;
    &lt;/Rectangle&gt;
&lt;/Grid&gt;
</pre></p><p>Although these two grids have set alignments, the actual location on the screen will be set in code-behind because the size will also be re-calculated. Also, I need to make sure that the application is in the full display mode—if it is snapped, there is no need to display the curtains because the visible area will be reduced to an overlay grid.</p><p>The curtain resize and visibility are determined in the UpdateWindowSize method:</p><p><pre class="brush: cpp">
void DirectXPage::UpdateWindowSize()
{
    bool visibility = true;
    if (ApplicationView::Value == ApplicationViewState::Snapped)
            visibility = false;
    
    float margin = (m_renderer-&gt;m_renderTargetSize.Width - 768.0f) / 2.0f;
    if (margin &lt; 2.0)
            visibility = false;
    
    if (visibility)
    {
        containerA-&gt;Width =  margin;
        containerA-&gt;HorizontalAlignment = Windows::UI::Xaml::HorizontalAlignment::Right;
        containerB-&gt;Width =  margin;
        containerB-&gt;HorizontalAlignment = Windows::UI::Xaml::HorizontalAlignment::Left;
        containerA-&gt;Visibility = Windows::UI::Xaml::Visibility::Visible;
        containerB-&gt;Visibility = Windows::UI::Xaml::Visibility::Visible;
    }
    else
    {
        containerA-&gt;Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        containerB-&gt;Visibility = Windows::UI::Xaml::Visibility::Collapsed;
    }
}
</pre></p><p>The snippet above ensures that the curtains will only be displayed when there is extra, unused space in addition to the 768 pixels taken by the playable area.</p><p>Let’s take a look at state-specific content that is being displayed whenever the game switches states. Because of the nature of DirectX interaction, there is no way for me to hook to specific event handlers from the native loop. Therefore, I need to constantly check that the content displayed is associated with the current state.</p><p>This can be done with the help of the <strong>SwitchGameState</strong> method:</p><p><pre class="brush: cpp">
void DirectXPage::SwitchGameState()
{
    switch (m_renderer-&gt;CurrentGameState)
            {
            case GameState::GS_FULL_WIN:
                    {
                            grdCompleteWin-&gt;Visibility = Windows::UI::Xaml::Visibility::Visible;
                            break;
                    }
            case GameState::GS_PLAYING:
                    {
                            Hud-&gt;Visibility = Windows::UI::Xaml::Visibility::Visible;
                            break;
                    }
            case GameState::GS_MAIN_MENU:
                    {
                            stkMainMenu-&gt;Visibility = Windows::UI::Xaml::Visibility::Visible;
                            break;
                    }
            case GameState::GS_GAME_OVER:
                    {
                            UpdateResults();
                            ResultPanel-&gt;Visibility = Windows::UI::Xaml::Visibility::Visible;
                            grdGameOver-&gt;Visibility = Windows::UI::Xaml::Visibility::Visible;
                            break;
                    }
            case GameState::GS_SUBMIT_SCORE:
                    {
                            grdSubmitScore-&gt;Visibility = Windows::UI::Xaml::Visibility::Visible;
                            txtSubmitScoreView-&gt;Text = StaticDataHelper::Score.ToString();
                            break;
                    }
            case GameState::GS_TOP_SCORES:
                    {
                            grdTopScores-&gt;Visibility = Windows::UI::Xaml::Visibility::Visible;
                            break;
                    }
            case GameState::GS_WIN:
                    {
                            UpdateResults();
                            grdWinner-&gt;Visibility = Windows::UI::Xaml::Visibility::Visible;
                            ResultPanel-&gt;Visibility = Windows::UI::Xaml::Visibility::Visible;
                            break;
                    }
            case GameState::GS_ABOUT_SCREEN:
                    {
                            grdAbout-&gt;Visibility =  Windows::UI::Xaml::Visibility::Visible;
                            break;
                    }
            case GameState::GS_LEVEL_SELECT_SINGLE:
                    {
                            animationBeginTime = 0;
            
                            stkLevelSelector-&gt;Visibility = Windows::UI::Xaml::Visibility::Visible;
                            break;
                    }
            case GameState::GS_HOW_TO:
                    {
                            grdHowTo-&gt;Visibility = Windows::UI::Xaml::Visibility::Visible;
                            Storyboard^ howToInitialBoard = (Storyboard^)grdMain-&gt;Resources-&gt;Lookup(&quot;StoryboardChainA&quot;);
                            howToInitialBoard-&gt;Begin();
                            break;
                    }
        default:
                    break;
            }
    
            Storyboard^ loc = (Storyboard^)grdMain-&gt;Resources-&gt;Lookup(&quot;FadingOut&quot;);
            loc-&gt;Begin();
}
</pre></p><p>One thing you’ve probably noticed about the snippet above is the fact that there is no indicator showing that controls are being hidden when the state changes. Just calling <strong>SwitchGameState</strong> in the Update loop would cause multiple controls to be displayed at once. However, there is also the <strong>HideEverything</strong> method that goes through the visual tree and sets the <strong>Visibility</strong> to <strong>Collapsed</strong> for everything:</p><p><pre class="brush: cpp">
void DirectXPage::HideEverything()
{
    for (uint i = 0; i &lt; grdMain-&gt;Children-&gt;Size; i&#43;&#43;)
    {
        grdMain-&gt;Children-&gt;GetAt(i)-&gt;Visibility = Windows::UI::Xaml::Visibility::Collapsed;
    }
}
</pre></p><p>&nbsp;</p><h4>HUD Interaction</h4><p>The Heads-Up Display (HUD) is used to alert the player about the current state of the game and the game character. In FallFury, it is used to display three indicators: how many buttons the character collected, how much time it took the character to get to the current level part, and current character health. It is also the container for the Pause button.</p><p>Here is the visual representation:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image006%5B3%5D.jpg"><img title="clip_image006" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image006_thumb-1.jpg" alt="clip_image006" width="517" height="331" border="0"></a></p><p>Here is the underlying XAML:</p><p><pre class="brush: xml">
&lt;Grid x:Name=&quot;Hud&quot; VerticalAlignment=&quot;Top&quot; Visibility=&quot;Collapsed&quot;&gt;
    &lt;Grid.RowDefinitions&gt;
        &lt;RowDefinition Height=&quot;80&quot; /&gt;
        &lt;RowDefinition Height=&quot;Auto&quot; /&gt;
    &lt;/Grid.RowDefinitions&gt;
    &lt;Grid.ColumnDefinitions&gt;
        &lt;ColumnDefinition /&gt;
        &lt;ColumnDefinition /&gt;
        &lt;ColumnDefinition /&gt;
        &lt;ColumnDefinition Width=&quot;80&quot; /&gt;
    &lt;/Grid.ColumnDefinitions&gt;

    &lt;Rectangle Fill=&quot;Black&quot; Grid.ColumnSpan=&quot;4&quot; /&gt;

    &lt;Button
        Grid.Column=&quot;0&quot;
        x:Name=&quot;btnPause&quot;
        Click=&quot;btnPause_Click&quot;
        Style=&quot;{StaticResource PauseButton}&quot;&gt;
        &lt;Image Source=&quot;ms-appx:///Assets/HUD/pauseButton.png&quot; Stretch=&quot;None&quot; /
    &lt;/Button&gt;

    &lt;StackPanel Grid.Column=&quot;1&quot; Orientation=&quot;Horizontal&quot;&gt;
        &lt;Image Source=&quot;ms-appx:///Assets/HUD/buttonHud.png&quot; Stretch=&quot;None&quot; /&gt;

        &lt;TextBlock
            x:Name=&quot;txtButtons&quot;
            Text=&quot;0&quot;
            Style=&quot;{StaticResource hudResult}&quot;/&gt;
    &lt;/StackPanel&gt;

    &lt;StackPanel Grid.Column=&quot;2&quot; Orientation=&quot;Horizontal&quot;&gt;
        &lt;Image Source=&quot;ms-appx:///Assets/HUD/clockHud.png&quot; Stretch=&quot;None&quot; /&gt;

        &lt;TextBlock
            x:Name=&quot;txtTimer&quot;
            Text=&quot;00:00&quot;
            Style=&quot;{StaticResource hudResult}&quot;/&gt;
    &lt;/StackPanel&gt;

    &lt;Image
        Grid.Column=&quot;3&quot;
        Source=&quot;ms-appx:///Assets/HUD/heartHud.png&quot;
        Stretch=&quot;None&quot; /&gt;

    &lt;Grid
        Grid.Column=&quot;3&quot;
        Grid.Row=&quot;1&quot;&gt;
        &lt;Rectangle Fill=&quot;Black&quot; Opacity=&quot;.8&quot;/&gt;
        &lt;controls:HealthBar x:Name=&quot;healthBar&quot;&gt;&lt;/controls:HealthBar&gt;
    &lt;/Grid&gt;
&lt;/Grid&gt;
</pre></p><p>As I mentioned before, the DirectX layer cannot directly interact with the XAML layer. Therefore, there needs to be an intermediary binding class. As the game progress changes, the <strong>UpdateHUD</strong> method is called, taking a reference to the current DirectX screen and reading the game data from the character and the <strong>StaticDataHelper</strong> class, which is the container for the time elapsed:</p><p><pre class="brush: cpp">
void DirectXPage::UpdateHud(GamePlayScreen^ playScreen)
{
    healthBar-&gt;Update(playScreen-&gt;GameBear-&gt;CurrentHealth, playScreen-&gt;GameBear-&gt;MaxHealth);
    
    txtButtons-&gt;Text = StaticDataHelper::ButtonsCollected.ToString();
    
    // Find a better built-in string formatting code
    if (m_renderer-&gt;CurrentGameState == GameState::GS_PLAYING &amp;&amp; !(StaticDataHelper::IsPaused) &amp;&amp; playScreen-&gt;IsLevelLoaded)
    {
        StaticDataHelper::SecondsTotal &#43;= m_timer-&gt;Delta;
        
        txtTimer-&gt;Text = StaticDataHelper::GetTimeString((int)StaticDataHelper::SecondsTotal);
    }
}
</pre></p><p>As seen above, part of the HUD is taken by a health indicator control—<strong>HealthBar</strong>. It is a simple composite element made out of two overlaying rectangles, one of which is resized as the bear health changes:</p><p><pre class="brush: xml">
&lt;UserControl
    x:Class=&quot;Coding4Fun.FallFury.Controls.HealthBar&quot;
    xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
    xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
    xmlns:local=&quot;using:FallFury&quot;
    xmlns:d=&quot;http://schemas.microsoft.com/expression/blend/2008&quot;
    xmlns:mc=&quot;http://schemas.openxmlformats.org/markup-compatibility/2006&quot;
    mc:Ignorable=&quot;d&quot;
    d:DesignHeight=&quot;410&quot;
    d:DesignWidth=&quot;20&quot; Height=&quot;410&quot; Width=&quot;20&quot;&gt;
    
    &lt;Grid&gt;
        &lt;StackPanel VerticalAlignment=&quot;Top&quot; Margin=&quot;0, 5, 0,20&quot;&gt;
            &lt;Rectangle Height=&quot;400&quot; Style=&quot;{StaticResource HealthRectangle}&quot; /&gt;
        &lt;/StackPanel&gt;

        &lt;StackPanel VerticalAlignment=&quot;Top&quot; Margin=&quot;0, 5, 0, 10&quot;&gt;
            &lt;Rectangle x:Name=&quot;OverlayStacker&quot; Height=&quot;0&quot; Style=&quot;{StaticResource HealthOverlayRectangle}&quot; /&gt;
        &lt;/StackPanel&gt;
    &lt;/Grid&gt;
&lt;/UserControl&gt;
</pre></p><p>Being of a fixed size, it is fairly easy to calculate the health-to-damage ratio and display that as the size of the overlaid rectangle:</p><p><pre class="brush: cpp">
DependencyProperty^ HealthBar::_MaxHealthProperty = 
    DependencyProperty::Register(&quot;MaxHealth&quot;, 
    double::typeid,
    HealthBar::typeid, 
    nullptr);

DependencyProperty^ HealthBar::_CurrentHealthProperty = 
    DependencyProperty::Register(&quot;CurrentHealth&quot;, 
    double::typeid,
    HealthBar::typeid, 
    nullptr);

void HealthBar::Update(double currentHealth, double maxHealth)
{
    CurrentHealth = currentHealth;
    MaxHealth = maxHealth;
    
    if (CurrentHealth &gt;= 0)
    {
        OverlayStacker-&gt;Height = 400.0 - ((400.0 * CurrentHealth) / MaxHealth);
    }
}
</pre></p><h4>Conclusion</h4><p>Using XAML as a part of a DirectX application does not require the developer to do a massive overhaul of the infrastructure. That said, be mindful when deciding whether to use a hybrid XAML application, as it is much easier to integrate a SwapChainBackgroundPanel with the underlying DirectX configuration from the ground up instead of trying to do so when the DirectX component is completed.</p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/DennisDel/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:f25dcd4fcbea4abdab11a1400002dab2">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-4-XAML-Interop</comments>
      <itunes:summary>As mentioned earlier in the series, FallFury does not solely rely on DirectX to display content to the user. As a Windows Store game, FallFury leverages the new Direct2D (XAML) project template, available in Visual Studio 2012.&amp;nbsp; Check out the video for this article at http://channel9.msdn.com/Series/FallFury/Part-4-XAML-Interop.&amp;nbsp; For a complete, offline version of this series, you may download a nicely formatted PDF of all the articles. The Concept of a Swap ChainBefore I go into detail about the DirectX and XAML interop in FallFury, I want to cover one important aspect of DirectX development that you need to familiarize yourself with: the swap chain. When your graphics adapter draws on the visual surface, you, as the user, see only minor potential redraws. Internally, however, the device switches buffers that reflect the displayed content, with each buffer representing a frame that has to be drawn. You can deduce from this that any swap chain has at least two buffers that it can switch between. For example, if I want to display my character as being displaced by a specific amount of pixels, the buffer will at the outset present to me the character in its initial position, while the second buffer will be constructed in the background with the proper position adjustments. The first frame, made from the content from the first buffer, will be discarded, and then the second frame will be displayed, and so on. This process occurs at a very high speed that depends on the processing capabilities of the graphics adapter, so the user does not notice the swapping itself. The most common swap chain is composed of two buffers—the screenbuffer and the secondary framebuffer. SwapChainBackgroundPanelDirectX interoperability with XAML simplifies a lot of routine tasks that would otherwise be handled with manual rendering procedures, such as a menu system or a simple game HUD. That being said, the way the XAML workflow is organized in a Direct2D project is quite different </itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-4-XAML-Interop</link>
      <pubDate>Wed, 23 Jan 2013 23:57:07 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-4-XAML-Interop</guid>
      <media:thumbnail url="http://media.ch9.ms/ch9/04e6/01086880-1f2d-4b77-8261-a7ccc0c804e6/FallFuryPart4_100.jpg" height="56" width="100"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/04e6/01086880-1f2d-4b77-8261-a7ccc0c804e6/FallFuryPart4_220.jpg" height="124" width="220"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/04e6/01086880-1f2d-4b77-8261-a7ccc0c804e6/FallFuryPart4_512.jpg" height="289" width="512"></media:thumbnail>      
      <dc:creator>Brian Peek, Clint Rutkas, Dan Fernandez, Den Delimarsky, Rick Barraza</dc:creator>
      <itunes:author>Brian Peek, Clint Rutkas, Dan Fernandez, Den Delimarsky, Rick Barraza</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-4-XAML-Interop/RSS</wfw:commentRss>
      <category>C#</category>
      <category>C++</category>
      <category>DirectX</category>
      <category>Windows Store App</category>
    </item>
  <item>
      <title>Fall Fury: Part 3 - Basic Rendering and Movement</title>
      <description><![CDATA[<p>Continuing the FallFury series, in this article I talk about basic game element rendering and character movement. As you already know, the FallFury user experience stack is split across two layers—native DirectX and XAML. Here, I will only be talking about the native DirectX component.&nbsp; Check out the video for this article at <a href="http://channel9.msdn.com/Series/FallFury/Part-3-Basic-Rendering-and-Movement">http://channel9.msdn.com/Series/FallFury/Part-3-Basic-Rendering-and-Movement</a>&nbsp; For a complete, offline version of this series, you may <a href="http://media.ch9.ms/coding4fun/fallfury/FallFury.pdf">download a nicely formatted PDF of all the articles</a>.</p><h4>The Background</h4><p>Each game screen in FallFury has a moving background that creates the illusion of a fall. The way the screen is designed, it simulates vertical <a href="http://en.wikipedia.org/wiki/Parallax_scrolling">parallax scrolling</a>, as the background moves faster than the overlaid objects. There is a simple way to make background movement possible without actually having to replicate parts of the texture and render them all over again. Take a look at this image, showcasing the process:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B2%5D-6.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb-7.png" alt="image" width="610" height="480" border="0"></a></p><p>First of all, two textures are loaded that, connected at the bottom, create the illusion of a single texture. In the beginning, texture A takes the entire screen and texture B is positioned directly underneath it, with a non-existing gap between them. To initiate the scrolling, texture A is being displaced vertically by an arbitrary number of pixels, and texture B follows it at the same pace. As texture B reaches the zero point (top of the viewport), texture A is no longer visible, therefore it is displaced vertically to be below texture B. This cycle can be repeated as many times as necessary during gameplay as well as while the user is in the menu.</p><p>Let’s take a look at the code that makes it possible, starting with the main menu screen:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B5%5D-8.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B1%5D-5.png" alt="image" width="623" height="354" border="0"></a></p><p>First of all, you need to be aware that every game screen is automatically inheriting the properties and capabilities of base class <strong>GameScreenBase</strong>. This is the class the offers the foundation both for basic texture loading and movement:</p><p><pre class="brush: cpp">
protected private:
    // Core background textures
    Microsoft::WRL::ComPtr&lt;ID3D11Texture2D&gt;                    m_backgroundBlockA;
    Microsoft::WRL::ComPtr&lt;ID3D11Texture2D&gt;                    m_backgroundBlockB;

void MoveBackground(float velocity);
</pre></p><p>It also offers the core texture containers for the overlaid elements that are present in most screens, such as clouds:</p><p><pre class="brush: cpp">
// Overlayed clouds
Microsoft::WRL::ComPtr&lt;ID3D11Texture2D&gt; m_overlayA;
Microsoft::WRL::ComPtr&lt;ID3D11Texture2D&gt; m_overlayB;
</pre></p><p>The overlay movement is inherently dependent on the base background displacement and can be adjusted relative to the initial velocity. Let’s take a look at <strong>GameScreenBase.cpp</strong>, specifically at <strong>MoveBackground</strong>:</p><p><pre class="brush: cpp">
void GameScreenBase::MoveBackground(float velocity)
{
    if (m_backgroundPositionA &lt;= -BACKGROUND_MIDPOINT)
        m_backgroundPositionA = m_backgroundPositionB &#43; (BACKGROUND_MIDPOINT * 2);

    if (m_backgroundPositionB &lt;= -BACKGROUND_MIDPOINT)
        m_backgroundPositionB = m_backgroundPositionA &#43; (BACKGROUND_MIDPOINT * 2);

    m_backgroundPositionA -= velocity;
    m_backgroundPositionB -= velocity;
}
</pre></p><p>The BACKGROUND_MIDPOINT value is relative to the height of the background texture. As we are working with a variable screen size, given that tablets and desktops do not have the same resolution, the movement has to be adjusted accordingly. One way, however, to ensure the proper texture positioning would be to place it in relation to its previous instance. Hence, this snippet in <strong>UpdateWindowSize</strong>:</p><p><pre class="brush: cpp">
BACKGROUND_MIDPOINT = 1366.0f / 2.0f;
m_backgroundPositionA = BACKGROUND_MIDPOINT;
m_backgroundPositionB = m_backgroundPositionA * 3;
</pre></p><p>Because overlays are not necessarily a part of every screen, I am not including the <strong>MoveOverlay</strong> method in the base class. Let’s now take a look at <strong>MenuScreen.cpp</strong>. Take a look at the Load method and you will see several lines that prepare the background and overlays:</p><p><pre class="brush: cpp">
m_loader = ref new BasicLoader(Manager-&gt;m_d3dDevice.Get(), Manager-&gt;m_wicFactory.Get());

m_loader-&gt;LoadTexture(&quot;Assets\\Backgrounds\\generic_blue_a.png&quot;, &amp;m_backgroundBlockA, nullptr);
m_loader-&gt;LoadTexture(&quot;Assets\\Backgrounds\\generic_blue_b.png&quot;, &amp;m_backgroundBlockB, nullptr);
m_loader-&gt;LoadTexture(&quot;Assets\\Backgrounds\\cloud_overlay_a.png&quot;, &amp;m_overlayA, nullptr);
m_loader-&gt;LoadTexture(&quot;Assets\\Backgrounds\\cloud_overlay_b.png&quot;, &amp;m_overlayB, nullptr);

CurrentSpriteBatch-&gt;AddTexture(m_backgroundBlockA.Get());
CurrentSpriteBatch-&gt;AddTexture(m_backgroundBlockB.Get());
CurrentSpriteBatch-&gt;AddTexture(m_overlayA.Get());
CurrentSpriteBatch-&gt;AddTexture(m_overlayB.Get());
</pre></p><p>The <strong>BasicLoader</strong> class was imported from the <a href="http://code.msdn.microsoft.com/windowsapps/Direct3D-sprite-sample-97ae6262">Direct3D sprite sample</a>. A call to LoadTexture will read the data from a DDS or PNG file and output the data in an <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ff476635%28v=vs.85%29.aspx">ID3D11Texture2D</a> object. Once loaded, the texture is added to the <strong>SpriteBatch</strong> instance associated with the screen, also declared as a part of <strong>GameScreenBase</strong>.</p><p>Depending on the screen, this procedure might have to be done for multiple textures, as you will see later in this article. Each page also has two timed loops—<strong>RenderScreen</strong> and <strong>Update</strong>. RenderScreen is responsible for taking everything from the SpriteBatch instance and showing it to the user. If you’ve used the <a href="http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.spritebatch.aspx">XNA SpriteBatch</a> before, you are aware that you need to start the drawing cycle by calling <strong>Begin</strong> and end it by calling <strong>End</strong>. The same applies here:</p><p><pre class="brush: cpp">
CurrentSpriteBatch-&gt;Begin();

CurrentSpriteBatch-&gt;Draw(
    m_backgroundBlockA.Get(),
    float2(Manager-&gt;m_windowBounds.Width / 2, m_backgroundPositionA),
    PositionUnits::DIPs,
    m_screenSize,
    SizeUnits::Pixels);

CurrentSpriteBatch-&gt;Draw(
    m_backgroundBlockB.Get(),
    float2(Manager-&gt;m_windowBounds.Width / 2 ,m_backgroundPositionB),
    PositionUnits::DIPs,
    m_screenSize,
    SizeUnits::Pixels);

if (m_showBear-&gt;IsLoaded)
    m_showBear-&gt;Render();

if (m_showMonster-&gt;IsLoaded)
    m_showMonster-&gt;Render();

CurrentSpriteBatch-&gt;Draw(
    m_overlayA.Get(),
    float2(Manager-&gt;m_windowBounds.Width/2, m_backgroundPositionA),
    PositionUnits::DIPs,
    m_screenSize,
    SizeUnits::Pixels);

CurrentSpriteBatch-&gt;Draw(
    m_overlayB.Get(),
    float2(Manager-&gt;m_windowBounds.Width / 2 ,m_backgroundPositionB),
    PositionUnits::DIPs,
    m_screenSize,
    SizeUnits::Pixels);

CurrentSpriteBatch-&gt;End();
</pre></p><p>The current overloaded <strong>Draw</strong> call gets the following items:</p><ul><li>The texture object </li><li>The position where the object has to be drawn on the screen </li><li>The way the object is positioned (can also be a normalized value or a pixel value) </li><li>The size of the texture (stretching may occur) </li><li>The type of the size value (in this case, I am using pixels, but can also be normalized) </li></ul><p>The order in which the <strong>Draw</strong> calls are arranged determines the order of objects drawn on the screen. The calls on top will place texture objects at the bottom of the rendering stack, and the calls at the end will place the objects at the top of the stack.</p><h4>The Gameplay Screen Background &amp; Overlays</h4><p>Let’s move on to the arguably most critical screen in the project, <strong>GamePlayScreen.cpp</strong>. There are a few nuances that differentiate it from any other screen—in particular, the background loading routine.</p><p>For every game, there is a different level type that is being used. With each level type, there is a different combination of a background and the overlay. Currently, there are four supported level types:</p><ul><li>Space </li><li>Nightmare </li><li>Magic Bean </li><li>Dream </li></ul><p>When the proper level is detected and the metadata is loaded from the associated XML file (more about this process later on in the series), the level textures are loaded into memory:</p><p><pre class="brush: cpp">
switch (m_currentLevelType)
{
    case LevelType::SPACE:
    {
        m_loader-&gt;LoadTexture(&quot;Assets\\Backgrounds\\generic_dark_blue_a.png&quot;, &amp;m_backgroundBlockA, nullptr);
        m_loader-&gt;LoadTexture(&quot;Assets\\Backgrounds\\generic_dark_blue_b.png&quot;, &amp;m_backgroundBlockB, nullptr);
        m_loader-&gt;LoadTexture(&quot;Assets\\Backgrounds\\star_overlay_a.png&quot;, &amp;m_overlayA, nullptr);
        m_loader-&gt;LoadTexture(&quot;Assets\\Backgrounds\\star_overlay_b.png&quot;, &amp;m_overlayB, nullptr);
        m_loader-&gt;LoadTexture(&quot;Assets\\Backgrounds\\galaxy_overlay_a.png&quot;, &amp;m_overlayGalaxyA, nullptr);
        m_loader-&gt;LoadTexture(&quot;Assets\\Backgrounds\\galaxy_overlay_b.png&quot;, &amp;m_overlayGalaxyB, nullptr);
        
        CurrentSpriteBatch-&gt;AddTexture(m_overlayGalaxyA.Get());
        CurrentSpriteBatch-&gt;AddTexture(m_overlayGalaxyB.Get());
        break;
    }
    case LevelType::NIGHTMARE:
    {
        m_loader-&gt;LoadTexture(&quot;Assets\\Backgrounds\\generic_red_a.png&quot;, &amp;m_backgroundBlockA, nullptr);
        m_loader-&gt;LoadTexture(&quot;Assets\\Backgrounds\\generic_red_b.png&quot;, &amp;m_backgroundBlockB, nullptr);
        m_loader-&gt;LoadTexture(&quot;Assets\\Backgrounds\\cloud_overlay_a.png&quot;, &amp;m_overlayA, nullptr);
        m_loader-&gt;LoadTexture(&quot;Assets\\Backgrounds\\cloud_overlay_b.png&quot;, &amp;m_overlayB, nullptr);
        break;
    }
    case LevelType::MAGIC_BEANS:
    {
        m_loader-&gt;LoadTexture(&quot;Assets\\Backgrounds\\generic_blue_a.png&quot;, &amp;m_backgroundBlockA, nullptr);
        m_loader-&gt;LoadTexture(&quot;Assets\\Backgrounds\\generic_blue_b.png&quot;, &amp;m_backgroundBlockB, nullptr);
        m_loader-&gt;LoadTexture(&quot;Assets\\Backgrounds\\cloud_overlay_a.png&quot;, &amp;m_overlayA, nullptr);
        m_loader-&gt;LoadTexture(&quot;Assets\\Backgrounds\\cloud_overlay_b.png&quot;, &amp;m_overlayB, nullptr);
        
        break;
    }
    case LevelType::DREAM:
    {
        m_loader-&gt;LoadTexture(&quot;DDS\\Levels\\Dream\\TEST_backgroundDream_01.dds&quot;, &amp;m_backgroundBlockA, nullptr);
        m_loader-&gt;LoadTexture(&quot;DDS\\Levels\\Dream\\TEST_backgroundDream_02.dds&quot;, &amp;m_backgroundBlockB, nullptr);
        m_loader-&gt;LoadTexture(&quot;Assets\\Backgrounds\\cloud_overlay_a.png&quot;, &amp;m_overlayA, nullptr);
        m_loader-&gt;LoadTexture(&quot;Assets\\Backgrounds\\cloud_overlay_b.png&quot;, &amp;m_overlayB, nullptr);
        break;
    }
}
</pre></p><p>This way, no unnecessary textures are loaded. A screen-based level flag allows me to control the incoming assets. At this point, the level environment does not change dynamically, so it is safe to assume that the textures should be loaded on a per-level basis.</p><p>The RenderScreen method is called in the same manner as in the menu screen, with the moving background and overlays located at the bottom of the rendering stack:</p><p><pre class="brush: cpp">
CurrentSpriteBatch-&gt;Draw(
    m_backgroundBlockA.Get(),
    float2(Manager-&gt;m_windowBounds.Width / 2, m_backgroundPositionA),
    PositionUnits::DIPs,
    m_screenSize,
    SizeUnits::Pixels);

CurrentSpriteBatch-&gt;Draw(
    m_backgroundBlockB.Get(),
    float2(Manager-&gt;m_windowBounds.Width / 2, m_backgroundPositionB),
    PositionUnits::DIPs,
    m_screenSize,
    SizeUnits::Pixels);

CurrentSpriteBatch-&gt;Draw(
    m_overlayA.Get(),
    float2(Manager-&gt;m_windowBounds.Width / 2, m_overlayPositionA),
    PositionUnits::DIPs,
    float2(768.0f, 1366.0f),
    SizeUnits::Pixels);

CurrentSpriteBatch-&gt;Draw(
    m_overlayB.Get(),
    float2(Manager-&gt;m_windowBounds.Width / 2, m_overlayPositionB),
    PositionUnits::DIPs,
    float2(768.0f, 1366.0f),
    SizeUnits::Pixels);
</pre></p><h4>Character Movement</h4><p>As you are now aware of the basic screen structure and how the basic rendering process is built, let’s take a look at how the main game character moves on the screen. Falling down, the teddy bear also needs to move left and right to ensure that he is able to pick up power-ups and buttons as well as avoid obstacles and enemy ammo.</p><p>There are several important considerations here. The most important one is to not assume that the user will have a specific input device. Potential movement controllers include a keyboard, the mouse, the touch screen and the accelerometer. In the most common scenarios, the desktop machines will not have an accelerometer, and the tablet computers will not have a constantly attached keyboard and a mouse. In FallFury, I decided to leverage all potential input engines and let the user choose the best option for himself.</p><p>When the current GamePlayScreen instance loads, I am attempting to get access to the system accelerometer device:</p><p><pre class="brush: cpp">
m_systemAccelerometer = Windows::Devices::Sensors::Accelerometer::GetDefault();
</pre></p><p><strong>m_systemAccelerometer</strong> is of type <a href="http://msdn.microsoft.com/en-us/library/windows/apps/windows.devices.sensors.accelerometer">Windows::Devices::Sensors::Accelerometer</a> and is declared in <strong>GamePlayScreen.h</strong>. If an accelerometer is detected, I need to bind it to a <a href="http://msdn.microsoft.com/en-us/library/windows/apps/windows.devices.sensors.accelerometer.readingchanged">ReadingChanged</a> event handler that will give me the current G-force transformed into X, Y, and Z displacement:</p><p><pre class="brush: cpp">
if (m_systemAccelerometer != nullptr)
{
    m_systemAccelerometer-&gt;ReadingChanged &#43;= ref new TypedEventHandler&lt;Accelerometer^, AccelerometerReadingChangedEventArgs^&gt;
            (this, &amp;GamePlayScreen::AccelerometerReadingChanged);
}
</pre></p><p><strong>ReadingChanged</strong> itself does not participate in updating the position for the character, but rather passes the current values to <strong>m_xAcceleration</strong>, which is later used in the <strong>Update</strong> method:</p><p><pre class="brush: cpp">
void GamePlayScreen::AccelerometerReadingChanged(_In_ Accelerometer^ accelerometer, _In_ AccelerometerReadingChangedEventArgs^ args)
{
    if (StaticDataHelper::IsAccelerometerEnabled)
    {
        auto currentOrientation = DisplayProperties::CurrentOrientation;
        float accelValue;
        
        if (currentOrientation == DisplayOrientations::Portrait)
                    accelValue = args-&gt;Reading-&gt;AccelerationY;
        else if (currentOrientation == DisplayOrientations::PortraitFlipped)
                    accelValue = -args-&gt;Reading-&gt;AccelerationY;
        else if (currentOrientation == DisplayOrientations::Landscape)
                    accelValue = args-&gt;Reading-&gt;AccelerationX;
        else if (currentOrientation == DisplayOrientations::LandscapeFlipped)
                    accelValue = -args-&gt;Reading-&gt;AccelerationX;
        else
                    accelValue = 0.0f;
        
        if (StaticDataHelper::IsAccelerometerInverted)
                    m_xAcceleration = -accelValue;
        else
                    m_xAcceleration = accelValue;
    }
}
</pre></p><p>The reason for this lies in the fact that <strong>ReadingChanged</strong> is triggered at a much lower rate than the <strong>Update</strong> loop. If the character position would be adjusted through the core accelerometer event handler, the result would be choppy (“step-by-step”) movement instead of a smooth transition.</p><p>Notice, also, that depending on the screen orientation, I need to get the acceleration either on the X- or Y-axes. Since an accelerometer is detected, I am assuming that the device that’s being used is a tablet. Therefore, it can have auto-rotate enabled, which means that the reference axis (horizontal) might change depending on how the user holds the device. <a href="http://msdn.microsoft.com/en-US/library/windowsphone/develop/windows.graphics.display.displayproperties.currentorientation.aspx">DisplayProperties::CurrentOrientation</a> can give me the current orientation, whether portrait (Y acceleration value) or landscape (X acceleration value):</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B8%5D-3.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B2%5D-7.png" alt="image" width="622" height="349" border="0"></a></p><p>As with many other titles, the user may invert the movement based on the accelerometer reading. For example, if the device is tilted to the right, the character will move to the left, and vice-versa. The effect is easily achieved by negating the current reading, regardless of the axis it is relying on.</p><p>Obviously, as the character moves, there should be boundaries that restrict the movement within the context of the current game screen. To get the correct screen bounds, <strong>GameScreenBase</strong>, the foundation class for every screen, sets four properties: <strong>LoBoundX</strong>, <strong>HiBoundX</strong>, <strong>LoBoundY</strong> and <strong>HiBoundY</strong>:</p><p><pre class="brush: cpp">
LoBoundX = (rWidth - 768.0f) / 2.0f;
HiBoundX = LoBoundX &#43; 768.0f;

LoBoundY = 0;
HiBoundY = LoBoundY &#43; rHeight;
</pre></p><p><strong>LoBoundX</strong> is the leftmost limit for the horizontal playable area and <strong>HiBoundX</strong> is the rightmost limit for the same horizontal area. <strong>LoBoundY</strong> and <strong>HiBoundY</strong> are responsible for carrying the limits for the vertical space. All four boundary values are relative to the screen size:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B11%5D-2.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B3%5D-7.png" alt="image" width="624" height="355" border="0"></a></p><p>To consistently get the correct X boundary no matter the screen size, the playable area is set to a fixed width of 768 pixels. The rest of the screen is accordingly cancelled out and the remaining area split in two. The original X point (zero) is added to the curtain size and that way there is the leftmost X boundary. The Y boundaries are simply obtained from the screen height, as there are no gameplay experience restrictions in that domain.</p><p>The bear position is updated in the Update loop in the game screen. There are several parameters that need to be adjusted, such as the vertical velocity, the bear rotation on tilt and the horizontal displacement.</p><p>When the level just starts, the bear falls faster until he reaches the standard static Y point. Because of screen size differences, this should not be done by comparing the pixel distance but rather by utilizing a ratio built from the current bear Y position and the high Y boundary:</p><p><pre class="brush: cpp">
if ((GameBear-&gt;Position.y / HiBoundY) &lt; 0.19f)
{
    GameBear-&gt;Position.y &#43;= GameBear-&gt;Velocity.y * (3.2f);
}
</pre></p><p>Assuming that the game is not paused, and thus the background is moving, the bear Y position should be adjusted relative to the current velocity set for the background scrolling. Because of how parallax scrolling works, the bear velocity has to be higher than the initial screen movement. Therefore, it is multiplied by a fixed value independent of the level played:</p><p><pre class="brush: cpp">
if (!m_isBackgroundMoving)
{
    if (GameBear-&gt;Position.y &gt; m_screenSize.y)
    {
        Manager-&gt;CurrentGameState = GameState::GS_GAME_OVER;
    }
    else
    {
        GameBear-&gt;Position.y &#43;= GameBear-&gt;Velocity.y * 1.5f;
    }
}
</pre></p><p>In the statement above, there is also an extra condition that verifies whether the bear is below the low Y boundary. If it is, then the game is over. This is imposed by a game animation that takes the bear off the Y limits, meaning that the bear is dead.</p><p>Bear rotation is based on the current X acceleration, but the bear shouldn’t rotate 360 degrees. To limit the rotation, there is a rotation threshold set (value taken in radians) that is being checked before rotating the character:</p><p><pre class="brush: cpp">
float compositeRotation = GameBear-&gt;Rotation - (float)m_xAcceleration / 10.0f;
if (compositeRotation &lt; m_rotationThreshold &amp;&amp; compositeRotation &gt; -m_rotationThreshold)
    GameBear-&gt;Rotation = compositeRotation;
</pre></p><p>The composite value lets me verify the perspective rotation without actually assigning it to the bear. If it is within the imposed threshold, only then will the bear rotation be adjusted.</p><p>Using the composite value approach is also efficient when performing the horizontal displacement adjustment. The initial value is composed of the current position and the X-based acceleration multiplied by a dynamic multiplier value to create the inertia effect:</p><p><pre class="brush: cpp">
float compositePosition = GameBear-&gt;Position.x &#43; ((float)m_xAcceleration * m_accelerationMultiplier);

if (m_xAcceleration &lt; 0)
    compositePosition -= 100.0f;
else
    compositePosition &#43;= 100.0f;

if (Manager-&gt;IsWithinScreenBoundaries(float2(compositePosition, GameBear-&gt;Position.y)))
{
    GameBear-&gt;Position.x &#43;= (float)m_xAcceleration * m_accelerationMultiplier;
}
else
{
    if (GameBear-&gt;Position.x &gt; HiBoundX)
    {
        GameBear-&gt;Position.x = HiBoundX - 180.0f;
    }
    else if (GameBear-&gt;Position.x &lt; LoBoundX)
    {
        GameBear-&gt;Position.x = LoBoundX &#43; 180.0f;
    }
}
</pre></p><p>If the bear is attempting to hit a “wall” (screen limit), its position is set back to the one barely prior to the limit. By doing this, I am avoiding locking the character on the side of the screen.</p><p>There is something in this snippet above that you might not be aware of—a reference to <strong>Manager-&gt;IsWithinScreenBoundaries</strong>. This method belongs to the ScreenManager (ScreenManager.cpp) class—a utility class that ensures the proper screen is displayed depending on the current game mode, and also allows control of mouse actions and boundary checks:</p><p><pre class="brush: cpp">
bool ScreenManager::IsWithinScreenBoundaries(float2 position)
{
    if (position.x &lt; CurrentGameScreen-&gt;LoBoundX || position.x &gt; CurrentGameScreen-&gt;HiBoundX || position.y &lt; CurrentGameScreen-&gt;LoBoundY || position.y &gt; CurrentGameScreen-&gt;HiBoundY)
            return false;
    else
            return true;
}
</pre></p><p>You saw how the movement is accomplished with the help of the accelerometer. Let’s take a look at how a keyboard can be used to do the same thing. There is a <strong>HandleKeyInput</strong> method, exposed through the <strong>GamePlayScreen</strong> class. As a matter of fact, <strong>HandleKeyInput</strong> is wired into the <strong>GameScreenBase</strong> class, therefore if a specific combination needs to be handled outside the context of the game play screen, it can be:</p><p><pre class="brush: cpp">
void GamePlayScreen::HandleKeyInput(Windows::System::VirtualKey key)
{
    if (key == Windows::System::VirtualKey::Right)
    {
        if (GameBear-&gt;IsWithinScreenBoundaries(GameBear-&gt;Size.x, 0.0f, GetScreenBounds()))
        {
            GameBear-&gt;Direction = TurningState::RIGHT;
            
            m_xAcceleration = 0.8f;
            
            if (GameBear-&gt;Rotation &gt;= -m_rotationThreshold)
                            GameBear-&gt;Rotation -= 0.02f;
        }
    }
    else if (key == Windows::System::VirtualKey::Left)
    {
        if (GameBear-&gt;IsWithinScreenBoundaries(-GameBear-&gt;Size.x, 0.0f, GetScreenBounds()))
        {
            GameBear-&gt;Direction = TurningState::LEFT;
            
            m_xAcceleration = -0.8f;
            
            if (GameBear-&gt;Rotation &lt;= m_rotationThreshold)
                            GameBear-&gt;Rotation &#43;= 0.02f;
        }
    }
}
</pre></p><p>As the accelerometer is no longer influencing the rotation or displacement, both indicators have to be manipulated through key presses. There are still standard thresholds in place to limit the potential incorrect movement, but the idea remains the same. This method is being called from the XAML page, which is overlaid on top of the DirectX renders:</p><p><pre class="brush: xml">
&lt;SwapChainBackgroundPanel
    x:Class=&quot;Coding4Fun.FallFury.DirectXPage&quot;
    xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
    xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
    xmlns:local=&quot;using:Coding4Fun.FallFury&quot; x:Name=&quot;XAMLPage&quot;
    xmlns:controls=&quot;using:Coding4Fun.FallFury.Controls&quot;
    xmlns:d=&quot;http://schemas.microsoft.com/expression/blend/2008&quot;
    xmlns:mc=&quot;http://schemas.openxmlformats.org/markup-compatibility/2006&quot;
    mc:Ignorable=&quot;d&quot; Loaded=&quot;OnLoaded&quot; KeyDown=&quot;OnKeyDown&quot; LayoutUpdated=&quot;XAMLPage_LayoutUpdated&quot;&gt;
</pre><pre class="brush: cpp">
void DirectXPage::OnKeyDown(Platform::Object^ sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs^ e)
{
    m_renderer-&gt;CurrentGameScreen-&gt;HandleKeyInput(e-&gt;Key);
}
</pre></p><p>When the keyboard is not available, movement can be controlled with the help of a mouse. Again, with standard event handlers, I am simply using <strong>OnPointerMoved</strong>:</p><p><pre class="brush: cpp">
void GamePlayScreen::OnPointerMoved(Windows::UI::Core::PointerEventArgs^ args)
{
    if (StaticDataHelper::IsMouseEnabled)
    {
        if (GameBear != nullptr)
        {
            m_touchCounter&#43;&#43;;
            if (GameBear-&gt;IsWithinScreenBoundaries(GameBear-&gt;Size.x, 0.0f, GetScreenBounds()))
            {
                m_xAcceleration = (args-&gt;CurrentPoint-&gt;RawPosition.X - GameBear-&gt;Position.x) / m_screenSize.x;
            }
        }
    }
}
</pre></p><p>By using this method, the bear will accelerate to the point where the mouse cursor is located, having a higher velocity the further it is located from the cursor. Once again, this creates the inertia visualization.</p><h4>Conclusion</h4><p>Concluding Part 3 of the series, remember that because Windows 8 is not a tablet-only OS, some users might have different input devices. Try to accommodate as many of those as possible.</p><p>The next article in this series will focus on the XAML overlay used in FallFury.</p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/DennisDel/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:4c48bfe7230449a1af4ca13f017fd4e4">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-3-Basic-Rendering-and-Movement</comments>
      <itunes:summary>Continuing the FallFury series, in this article I talk about basic game element rendering and character movement. As you already know, the FallFury user experience stack is split across two layers—native DirectX and XAML. Here, I will only be talking about the native DirectX component.&amp;nbsp; Check out the video for this article at http://channel9.msdn.com/Series/FallFury/Part-3-Basic-Rendering-and-Movement&amp;nbsp; For a complete, offline version of this series, you may download a nicely formatted PDF of all the articles. The BackgroundEach game screen in FallFury has a moving background that creates the illusion of a fall. The way the screen is designed, it simulates vertical parallax scrolling, as the background moves faster than the overlaid objects. There is a simple way to make background movement possible without actually having to replicate parts of the texture and render them all over again. Take a look at this image, showcasing the process:  First of all, two textures are loaded that, connected at the bottom, create the illusion of a single texture. In the beginning, texture A takes the entire screen and texture B is positioned directly underneath it, with a non-existing gap between them. To initiate the scrolling, texture A is being displaced vertically by an arbitrary number of pixels, and texture B follows it at the same pace. As texture B reaches the zero point (top of the viewport), texture A is no longer visible, therefore it is displaced vertically to be below texture B. This cycle can be repeated as many times as necessary during gameplay as well as while the user is in the menu. Let’s take a look at the code that makes it possible, starting with the main menu screen:  First of all, you need to be aware that every game screen is automatically inheriting the properties and capabilities of base class GameScreenBase. This is the class the offers the foundation both for basic texture loading and movement: 
protected private:
    // Core background textur</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-3-Basic-Rendering-and-Movement</link>
      <pubDate>Wed, 23 Jan 2013 23:57:03 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-3-Basic-Rendering-and-Movement</guid>
      <media:thumbnail url="http://media.ch9.ms/ch9/f2a1/9afdc0cb-6045-4e66-97d6-89d9297bf2a1/FallFuryPart3_100.jpg" height="56" width="100"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/f2a1/9afdc0cb-6045-4e66-97d6-89d9297bf2a1/FallFuryPart3_220.jpg" height="124" width="220"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/f2a1/9afdc0cb-6045-4e66-97d6-89d9297bf2a1/FallFuryPart3_512.jpg" height="289" width="512"></media:thumbnail>      
      <dc:creator>Brian Peek, Clint Rutkas, Dan Fernandez, Den Delimarsky, Rick Barraza</dc:creator>
      <itunes:author>Brian Peek, Clint Rutkas, Dan Fernandez, Den Delimarsky, Rick Barraza</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-3-Basic-Rendering-and-Movement/RSS</wfw:commentRss>
      <category>C#</category>
      <category>C++</category>
      <category>DirectX</category>
      <category>Windows Store App</category>
    </item>
  <item>
      <title>Fall Fury: Part 2 - Shaders</title>
      <description><![CDATA[<h4>Introduction to Shaders</h4><p>FallFury not only relies on standard C&#43;&#43;/C# and XAML code, but also on shaders. This article is intended for developers who are not aware of what shaders are and want to know how to use them in their projects. I will talk about creating shaders, as well as the shaders used in my project.</p><p>Check out the video for this article at <a href="http://channel9.msdn.com/Series/FallFury/Part-2-Shaders">http://channel9.msdn.com/Series/FallFury/Part-2-Shaders</a>.&nbsp; For a complete, offline version of this series, you may <a href="http://media.ch9.ms/coding4fun/fallfury/FallFury.pdf">download a nicely formatted PDF of all the articles</a>.</p><h4>Code on GPU</h4><p>In simple terms, shaders are small programs that are executed on the Graphical Processing Unit (GPU) instead of the Central Processing Unit (CPU). In recent years, we’ve seen a major spike in the capabilities of graphic devices, allowing hardware manufacturers to design an execution layer tied to the GPU, therefore being able to target device-specific manipulations to a highly optimized unit. Shaders are not used for simple calculations, but rather for image processing. For example, a shader can be used to adjust image lighting or colors.</p><p>Modern GPUs give access to the rendering pipeline that allows developers to execute arbitrary image processing code. This is a step forward from a fixed-function pipeline that was present in older GPUs, where image processing tasks were integrated into the hardware unit and were only able to perform a limited set of actions, such as transforms. Unlike the rendering pipeline, the fixed-function pipeline was not programmable, therefore the developers were often tied to the hardware they used for offering specific game effects, in some cases having to resort to software-based adjustments.</p><h4>Types of Shaders</h4><p>There are different types of image manipulations that can be performed on a given input, and so there are different types of shaders designed to handle that. Currently, we can highlight three main shader types:</p><ul><li><strong>Vertex shaders</strong> – because what the user sees on the screen is not really three-dimensional, but rather a three-dimensional simulation in a 2D space, vertex shaders translate the coordinates of a vector in 3D space in relation to the 2D frame. Vertex shaders are executed one time per vector passed to the GPU. Typically, vectors carry data related to their position and the coordinate of the bound texture as well as color. A vertex shader is able to manipulate all these properties, but there is never a situation where a new vertex is created as a result of the execution. </li><li><strong>Pixel shaders</strong> – these programs are executed on the GPU in relation to every passed pixel, working on a much lower level. For example, if you want specific pixels adjusted for lighting or 3D bump mapping, a pixel shader can provide the desired effect for a surface. Rarely, there are situations where only a few pixels should be re-adjusted at once. Pixel shaders are often run with an input of millions of pixels, resulting in complex effects. </li><li><strong>Geometry shaders</strong> – these shaders are the next progression from vertex shaders, introduced with DirectX 10. The developer is able to pass specific primitives as input and either have the output represent the modified version of what was passed to the program or have new primitives, such as triangles, be generated as a result. Geometry shaders are always executed on post-vertex processing in the rendering pipeline. When vertex shader execution is completed, geometry shaders step in, if present. Geometry shaders can be used to refine the level of detail of a specific object. For example, when an object is closer or further away from the viewport camera, the mesh would have to be refined to minimize the rendering load. </li></ul><p>FallFury uses all these shader types as a part of the game.</p><h4>Enough Talk, Let’s Code</h4><p>Now that you are aware of what shaders are, let’s write some sample code and test it. It is worth mentioning that shaders are not written in a standard high-level language, but rather in a language defined by the environment the shader is used in. For Direct3D, this is the High-Level Shader Language, or HLSL. It is somewhat similar to C, but with some specific nuances.</p><p>Start by creating a test Direct3D Windows Store application:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image002%5B3%5D-3.jpg"><img title="clip_image002" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image002_thumb-4.jpg" alt="clip_image002" width="624" height="380" border="0"></a></p><p>If you create and run this sample application, you will see that the output of it is a simple 3D spinning cube:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image004%5B3%5D-2.jpg"><img title="clip_image004" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image004_thumb-3.jpg" alt="clip_image004" width="435" height="243" border="0"></a></p><p>You probably also noticed that there are two shaders that are a component part of the newly created solution: <strong>SimplePixelShader.hlsl</strong> and <strong>SimpleVertexShader.hlsl</strong>. Take a look inside the pixel shader:</p><p><pre class="brush: cpp">
struct PixelShaderInput
{
    float4 pos : SV_POSITION;
    float3 color : COLOR0;
};

float4 main(PixelShaderInput input) : SV_TARGET
{
    return float4(input.color,1.0f);
}
</pre></p><p>First of all, there is a PixelShaderInput <a>struct</a><a name="_msoanchor_1"></a>[DW1] . It represents a single pixel – it has a float4 field that represents the position of the pixel and a float3 field that represents the RGB pixel color. The field itself is also marked by a predefined type, such as SV_POSITION or COLOR. This is a string that determines the use of the field. You can read more about the shader semantics <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/bb509647(v=vs.85).aspx">here</a>.</p><p>The strings that are prefixed with SV_ are representing system-value semantics. Those have special meaning in the pipeline during the processing stages. In the pixel shader above, SV_POSITION will always mean the pixel position.</p><p>Look at what is being returned from the pixel shader—instead of the standard float3 color indicator, you are now returning a float4, which couples the existing value, input.color, with a 1.0f float value that represents the alpha-channel value. Remember, that inside shaders the color is clamped between 0 and 1 instead of the standard 255-value limit.</p><p>Since the cube rendering mechanism is already in place, let’s experiment with the pixel shader a bit. You’ve already got the float4 color representation:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image006%5B3%5D.png"><img title="clip_image006" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image006_thumb.png" alt="clip_image006" width="580" height="157" border="0"></a></p><p>You can set any of these values to 1.0 to return the solid color, so let’s do that. Let’s render the cube green. Modify the return statement to be this:</p><p>return float4(0.0, 1.0, 0.0, 1.0);</p><p>At this point, if you will run the program you will get a rendering very similar to this:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image008%5B3%5D-1.jpg"><img title="clip_image008" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image008_thumb-2.jpg" alt="clip_image008" width="624" height="346" border="0"></a></p><p>This is a good start.. Now, let’s now take a look at the vertex shader in the project. By default, you get this:</p><p><pre class="brush: cpp">
cbuffer ModelViewProjectionConstantBuffer : register(b0)
{
    matrix model;
    matrix view;
    matrix projection;
};

struct VertexShaderInput
{
    float3 pos : POSITION;
    float3 color : COLOR0;
};

struct VertexShaderOutput
{
    float4 pos : SV_POSITION;
    float3 color : COLOR0;
};

VertexShaderOutput main(VertexShaderInput input)
{
    VertexShaderOutput output;
    float4 pos = float4(input.pos, 1.0f);
    
    pos = mul(pos, model);
    pos = mul(pos, view);
    pos = mul(pos, projection);
    output.pos = pos;
    
    // Pass through the color without modification.
    output.color = input.color;
    
    return output;
}
</pre></p><p>There are a couple of differences here compared to the above mentioned pixel shader:</p><ul><li><strong>cbuffer ModelViewProjectionConstantBuffer</strong> – represents a constant buffer that contains three matrices, to which vertices are related—the model, view and projection matrices. Constant buffers are interesting structures that have been optimized to allow block-wise updates, where multiple constants are grouped in one boxed unit and can be updated simultaneously instead of having a one-by-one iterative update cycle. </li><li><strong>struct VertexShaderInput</strong> – vertices are passed one-by-one to the shader, and this specific structure represents the input. Notice that it carries the 3D representation of the vertex position as well as its RGB color value. </li><li><strong>struct VertexShaderOutput </strong>– the final processed output, which now carries the position in relation to all three matrices mentioned above as well as the processed color. Notice that the fourth value is the camera distance in the demo. </li><li><strong>VertexShaderOutput main(VertexShaderInput input) </strong>– this is the main function that performs the vertex processing. Initially, it performs the position adjustment relative to the camera and then uses <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/bb509628(v=vs.85).aspx">mul</a>, a built-in function that multiplies matrices, to represent the current vertices in the projected space. </li></ul><p>So let’s play around with what we have in stock. Take a look at the main function and how initially, the float3-based position is transformed to contain the camera distance:</p><p><pre class="brush: cpp">
float4 pos = float4(input.pos, 1.0f);
</pre></p><p>This position is normalized in relation to the current viewport. Afterwards, the vertex is transformed in the current 3D space (relative to three matrices – model, view, and projection):</p><p><pre class="brush: cpp">
pos = mul(pos, model);
pos = mul(pos, view);

pos = mul(pos, projection);

output.pos = pos;
</pre></p><p>As with the pixel shader, these are some very basic manipulations. Let’s flip the cube upside-down. To do this, we need to apply a rotation transformation. Here is an interesting piece of advice—when working with manipulations in shaders, make sure that you know basic matrix operations.</p><p>For example, to perform a simple 2D rotation, you need to use the <a href="http://en.wikipedia.org/wiki/Rotation_matrix">rotation matrix</a>:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image009%5B3%5D.png"><img title="clip_image009" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image009_thumb.png" alt="clip_image009" width="169" height="48" border="0"></a></p><p>But since we’re in 3D space, we not only have the X and Y coordinates, which relate to the matrix above, but also the Z coordinate. Therefore, a different method should be applied. There are three fundamental matrices that can be used to rotate an object around the three possible axes:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image011%5B3%5D.png"><img title="clip_image011" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image011_thumb.png" alt="clip_image011" width="236" height="285" border="0"></a></p><p>For now, we want to rotate the cube along the X-axis. To do this, inside the main function, we need to declare a constant that represents the rotation angle, in radians:</p><p><pre class="brush: cpp">
const float angle = 1.3962634;
</pre></p><p>Looking at the matrix above, we need to find out the sine and cosine of the given angle. When working with vertex shaders, HLSL offers a built-in function, called <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/bb147382(v=vs.85).aspx">sincos</a> that is able to get both values from an input value:</p><p><pre class="brush: cpp">
float cosLength, sinLength;
sincos(angle, sinLength, cosLength);
</pre></p><p>Now you need to declare the rotation matrix. Again, HLSL comes with some built-in capabilities to declare matrices and set their values:</p><p><pre class="brush: cpp">
float3x3 xAxisRotation = { 
    1.0, 0.0, 0.0, // Row 1
    0, cosLength, -sinLength, // Row 2
    0, sinLength, cosLength}; // Row 3
</pre></p><p>&nbsp;</p><p>The standard format for matrix declaration in this case follows the following pattern:</p><p>Matrix&lt;type,size&gt; localName</p><p>For matrix multiplication, we can once again leverage the mul function:</p><p><pre class="brush: cpp">
float3 temporaryPosition;
temporaryPosition = mul(input.pos,xAxisRotation);
</pre></p><p>Now we can normalize the position to a float4 value that also includes the camera distance:</p><p><pre class="brush: cpp">
float4 pos = float4(temporaryPosition, 1.0f);
</pre></p><p>The rest of the transformation procedures can be taken directly from the original shader, multiplying the float4 position by the model, view, and projection matrices. Your entire main function should now look like this:</p><p><pre class="brush: cpp">
VertexShaderOutput main(VertexShaderInput input)
{
    VertexShaderOutput output;

    const float angle = 1.3962634;
    float cosLength, sinLength;
    sincos(angle, sinLength, cosLength);

    float3x3 xAxisRotation = { 
        1.0, 0.0, 0.0, // Row 1
        0, cosLength, -sinLength, // Row 2
        0, sinLength, cosLength}; // Row 3

    float3 temporaryPosition;
    temporaryPosition = mul(input.pos,xAxisRotation);
    float4 pos = float4(temporaryPosition, 1.0f);

    // Transform the vertex position into projected space.
    pos = mul(pos, model);
    pos = mul(pos, view);
    pos = mul(pos, projection);
    output.pos = pos;

    // Pass through the color without modification.
    output.color = input.color;

    return output;
}
</pre></p><p>The current angle is set to 80 degrees, or 1.3962634 radians. If you run the rendering test application, the result you will get will be similar to this:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image013%5B3%5D.jpg"><img title="clip_image013" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image013_thumb.jpg" alt="clip_image013" width="449" height="252" border="0"></a></p><p>Now, let’s look at how shaders are handled on the DirectX side.</p><h4>Shaders in DirectX</h4><p>Open <strong>CubeRenderer.cpp</strong>. This is the source file where internal shaders are read and passed to the device to be executed. Notice one interesting aspect of the process – the shader file contents are being read first and then passed to <strong>m_d3dDevice-&gt;CreateVertexShader</strong>. m_d3dDevice is a pointer to a virtual adapter that can be used to create device-specific resources. <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ff476524(v=vs.85).aspx">CreateVertexShader</a> creates a vertex shader from an already compiled shader. You can notice it from the fact that the data is read not from the initial <strong>.hlsl</strong> file, but rather from the <strong>.cso (Compiled Shader Object)</strong>:</p><p>auto loadVSTask = DX::ReadDataAsync(&quot;SimpleVertexShader.cso&quot;);</p><p>As with any program, before it is passed onto the execution layer, it has to be compiled first. Visual Studio 2012 comes with a bundled HLSL compiler, <strong>fxc</strong>—the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/bb232919(v=vs.85).aspx">Effect Compiler Tool</a>. The default behavior for a shader is to be compiled with the .cso file extension in the same output directory as the project, but this can be changed by setting the <strong>Object File Name</strong> in the shader properties:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image015%5B3%5D.jpg"><img title="clip_image015" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image015_thumb.jpg" alt="clip_image015" width="624" height="443" border="0"></a></p><p>You can read more about the shader compilation process <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/bb509633(v=vs.85).aspx">here</a>.</p><p>Looking back at the sample vertex shader that was created as a part of the project, you will notice that there is a specific input layout set for the incoming object:</p><p><pre class="brush: cpp">
struct VertexShaderInput
{
    float3 pos : POSITION;
    float3 color : COLOR0;
};
</pre></p><p>&nbsp;</p><p>The virtual adapter is not aware of the structure layout. Therefore, the developer needs to explicitly create an internal <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ff476180(v=vs.85).aspx">D3D11_INPUT_ELEMENT_DESC</a> array that will contain the type of information passed to the shader:</p><p><pre class="brush: cpp">
const D3D11_INPUT_ELEMENT_DESC vertexDesc[] = 
{
    { 
        &quot;POSITION&quot;, 
        0, 
        DXGI_FORMAT_R32G32B32_FLOAT, 
        0, 
        0, 
        D3D11_INPUT_PER_VERTEX_DATA, 
        0 },
    {
        &quot;COLOR&quot;, 
        0, 
        DXGI_FORMAT_R32G32B32_FLOAT, 
        0, 
        12, 
        D3D11_INPUT_PER_VERTEX_DATA, 
        0 },
};
</pre></p><p>&nbsp;</p><p>Once the description is complete, the input needs to be assembled for processing. That’s where <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ff476512%28v=vs.85%29.aspx">CreateInputLayout</a> comes into play:</p><p><pre class="brush: cpp">
DX::ThrowIfFailed(
    m_d3dDevice-&gt;CreateInputLayout(
        vertexDesc,
        ARRAYSIZE(vertexDesc),
        fileData-&gt;Data,
        fileData-&gt;Length,
        &amp;m_inputLayout
        )
    );
</pre></p><p>&nbsp;</p><p>You are basically passing a shader signature to the input assembler that will perform all the consequent processing. A similar process is applied for the existing pixel shader, with the main difference being the fact that instead of CreateVertexShader, <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ff476513%28v=vs.85%29.aspx">CreatePixelShader</a> is called:</p><h4>Passing Custom Parameters to Shaders</h4><p>Going back to our vertex shader where we performed the rotation relative to the X-axis, you probably noticed that the angle is hard-coded and is applied to each vector in the same way. This is rarely the case, as the angle would normally come from inside the game itself, often responding to internal behavior, such as character movement or action.</p><p>To pass a parameter to the shader, you need to first of all redefine the input structure. Let’s add an angle carrier to the <strong>VertexShaderInput</strong> struct in <strong>SimpleVertexShader.hlsl</strong>:</p><p><pre class="brush: cpp">
struct VertexShaderInput
{
    float3 pos : POSITION;
    float3 color : COLOR0;
    float angle : TRANSFORM0;
};
</pre></p><p>This alone won’t do anything. Go the entry point function (<strong>main</strong>) and make sure that the angle constant is set to <strong>input.angle</strong>:</p><p><pre class="brush: cpp">
const float angle = input.angle;
</pre></p><p>Now the shader is ready, but you also need to let your game know that the vertex shader has a modified input layout. To do this, go to <strong>CubeRenderer.cpp</strong> and find the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ff476180%28v=vs.85%29.aspx">D3D11_INPUT_ELEMENT_DESC</a> array that defines the input layout for incoming vertex shaders. Simply add an identifying item to the existing array:</p><p><pre class="brush: cpp">
const D3D11_INPUT_ELEMENT_DESC vertexDesc[] = 
{ 
    { &quot;POSITION&quot;, 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 
    { &quot;COLOR&quot;, 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 
    { &quot;TRANSFORM&quot;, 0, DXGI_FORMAT_R32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 } 
};
</pre></p><p>The first parameter is the pre-defined semantic used in the shader. The second parameter defines the input index. After that, use <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/bb173059%28v=vs.85%29.aspx">DXGI_FORMAT_R32_FLOAT</a> to indicate that the value passed will be a standard float. Pay close attention when you specify the input offset. Notice that the two FLOAT3 values, POSITION and COLOR, take 12 bytes each —a float takes 32 bits (4 bytes), and you have a triplet, therefore the offset for TRANSFORM should be 24 bytes (two times 12 bytes from previous indicators).</p><p>Now you need to modify the internal vector descriptors that are being passed to the rendering pipe. In the sample project those are created with the help of the VertexPositionColor class, located in the <strong>CubeRenderer.h</strong>. Add a simple float field to the existing struct, so it looks like this:</p><p><pre class="brush: cpp">
struct VertexPositionColor 
{ 
    DirectX::XMFLOAT3 pos; 
    DirectX::XMFLOAT3 color; 
    float angle; 
};
</pre></p><p>&nbsp;</p><p>In <strong>CubeRenderer.cpp</strong>, find the <strong>cubeVerticles</strong> array. For each created <strong>VertexPositionColor</strong> you are now able to add a third value representing the rotation:</p><p><pre class="brush: cpp">
auto createCubeTask = (createPSTask &amp;&amp; createVSTask).then([this] () { 
    VertexPositionColor cubeVertices[] = 
    { 
        {XMFLOAT3(-0.5f, -0.5f, -0.5f), XMFLOAT3(0.0f, 0.0f, 0.0f), 1.38f}, 
        {XMFLOAT3(-0.5f, -0.5f, 0.5f), XMFLOAT3(0.0f, 0.0f, 1.0f), 1.38f}, 
        {XMFLOAT3(-0.5f, 0.5f, -0.5f), XMFLOAT3(0.0f, 1.0f, 0.0f), 1.38f}, 
        {XMFLOAT3(-0.5f, 0.5f, 0.5f), XMFLOAT3(0.0f, 1.0f, 1.0f), 1.38f}, 
        {XMFLOAT3( 0.5f, -0.5f, -0.5f), XMFLOAT3(1.0f, 0.0f, 0.0f), 1.38f}, 
        {XMFLOAT3( 0.5f, -0.5f, 0.5f), XMFLOAT3(1.0f, 0.0f, 1.0f), 1.38f}, 
        {XMFLOAT3( 0.5f, 0.5f, -0.5f), XMFLOAT3(1.0f, 1.0f, 0.0f), 1.38f}, 
        {XMFLOAT3( 0.5f, 0.5f, 0.5f), XMFLOAT3(1.0f, 1.0f, 1.0f), 1.38f}, 
    };
</pre></p><p>&nbsp;</p><p>Now you will be able to pass parameters to the vertex shader without having to manually modify the shader itself.</p><h4>Shaders in FallFury</h4><p>There are several shaders used in FallFury, which must be selected depending on the Direct3D feature level available on the machine. A feature level determines what a video adapter can do in terms of rendering—even though Direct3D is a unified framework, it still heavily relies on how individual graphic cards can perform.</p><p>There are 5 shaders used internally for texture rendering. Specifically, there is a pixel shader, a replication vertex shader, an instancing vertex shader and geometry shaders. This could be familiar if you worked with Microsoft DirectX sprite samples before:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image016%5B3%5D.png"><img title="clip_image016" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image016_thumb.png" alt="clip_image016" width="337" height="167" border="0"></a></p><p>Given the platform limitations, geometry shaders can only be used on devices supporting Direct3D Feature Level 10. When FallFury detects that the feature level is lower than that, it has to fall back on either the instancing or the replication shaders. Some devices, such as the Microsoft Surface, are at feature level 9.1. Therefore, the replication render technique must be enforced.</p><p>Following the <a href="http://code.msdn.microsoft.com/windowsapps/Direct3D-sprite-sample-97ae6262">Microsoft DirectX Sprite Sample</a>, it is fairly easy to simply select the correct render technique once the feature level is detected with <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ff476528%28v=vs.85%29.aspx">GetFeatureLevel</a>:</p><p><pre class="brush: cpp">
auto featureLevel = m_d3dDevice-&gt;GetFeatureLevel(); 
if (featureLevel &gt;= D3D_FEATURE_LEVEL_10_0) 
{ 
    m_technique = RenderTechnique::GeometryShader; 
} 
else if (featureLevel &gt;= D3D_FEATURE_LEVEL_9_3) 
{ 
    m_technique = RenderTechnique::Instancing; 
} 
else 
{ 
    m_technique = RenderTechnique::Replication; 
    if (capacity &gt; static_cast&lt;int&gt;(Parameters::MaximumCapacityCompatible)) 
    { 
        // The index buffer format for feature-level 9.1 devices may only be 16 bits. 
        // With 4 vertices per sprite, this allows a maximum of (1 &lt;&lt; 16) / 4 sprites. 
        throw ref new Platform::InvalidArgumentException(); 
    } 
}
</pre></p><p>&nbsp;</p><p>Depending on the selected render technique, which is determined on application startup, the proper input layout is selected for each shader and is used to control the rendering pipe.</p><p>Different graphic adapters also support different <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ff471356%28v=vs.85%29.aspx">shader models</a>. You need to account for those, and before running the application, the HLSL compiler will take on the task of determining whether a proper shader component is supported by the given model. In the shader properties, make sure that you specify the used shader model, as well as the type of the shader:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image018%5B3%5D-1.jpg"><img title="clip_image018" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/clip_image018_thumb-1.jpg" alt="clip_image018" width="624" height="443" border="0"></a></p><p>Without this, you are bound to experience compile time errors that will prevent you from launching the application or deploying it to different devices.</p><h4>Conclusion</h4><p>Shaders are not an easy subject. I highly recommend reading <a href="http://http.developer.nvidia.com/CgTutorial/cg_tutorial_frontmatter.html">The Cg Tutorial</a>, published online for free by nVidia. Even though it describes the Cg shader language, it is virtually identical to HLSL and you will not have any problems using the practices you learned there in building HLSL shaders.</p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/DennisDel/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:e11fdf9075a54e749835a13f017319dd">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-2-Shaders</comments>
      <itunes:summary>Introduction to ShadersFallFury not only relies on standard C&amp;#43;&amp;#43;/C# and XAML code, but also on shaders. This article is intended for developers who are not aware of what shaders are and want to know how to use them in their projects. I will talk about creating shaders, as well as the shaders used in my project. Check out the video for this article at http://channel9.msdn.com/Series/FallFury/Part-2-Shaders.&amp;nbsp; For a complete, offline version of this series, you may download a nicely formatted PDF of all the articles. Code on GPUIn simple terms, shaders are small programs that are executed on the Graphical Processing Unit (GPU) instead of the Central Processing Unit (CPU). In recent years, we’ve seen a major spike in the capabilities of graphic devices, allowing hardware manufacturers to design an execution layer tied to the GPU, therefore being able to target device-specific manipulations to a highly optimized unit. Shaders are not used for simple calculations, but rather for image processing. For example, a shader can be used to adjust image lighting or colors. Modern GPUs give access to the rendering pipeline that allows developers to execute arbitrary image processing code. This is a step forward from a fixed-function pipeline that was present in older GPUs, where image processing tasks were integrated into the hardware unit and were only able to perform a limited set of actions, such as transforms. Unlike the rendering pipeline, the fixed-function pipeline was not programmable, therefore the developers were often tied to the hardware they used for offering specific game effects, in some cases having to resort to software-based adjustments. Types of ShadersThere are different types of image manipulations that can be performed on a given input, and so there are different types of shaders designed to handle that. Currently, we can highlight three main shader types: Vertex shaders – because what the user sees on the screen is not really three-dimensional, b</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-2-Shaders</link>
      <pubDate>Wed, 23 Jan 2013 23:57:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-2-Shaders</guid>
      <media:thumbnail url="http://media.ch9.ms/ch9/0419/408466c0-5dee-4616-b76d-3c5e824a0419/FallFuryPart2_100.jpg" height="56" width="100"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/0419/408466c0-5dee-4616-b76d-3c5e824a0419/FallFuryPart2_220.jpg" height="124" width="220"></media:thumbnail>
      <media:thumbnail url="http://media.ch9.ms/ch9/0419/408466c0-5dee-4616-b76d-3c5e824a0419/FallFuryPart2_512.jpg" height="289" width="512"></media:thumbnail>      
      <dc:creator>Brian Peek, Clint Rutkas, Dan Fernandez, Den Delimarsky, Rick Barraza</dc:creator>
      <itunes:author>Brian Peek, Clint Rutkas, Dan Fernandez, Den Delimarsky, Rick Barraza</itunes:author>
      <slash:comments>2</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Fall-Fury-Part-2-Shaders/RSS</wfw:commentRss>
      <category>C#</category>
      <category>C++</category>
      <category>DirectX</category>
      <category>Windows Store App</category>
    </item>    
</channel>
</rss>