10 Minute Game Programming Tutorial: Silverlight - Shootorial #1 Conversion (C#)

Welcome to the first of many Silverlight game programming tutorials on dieajax.com. In a burst of originality and creativity, for this initial set of tutorials, I decided to convert Kongregate’s excellent beginning Flash game programming tutorial series to Silverlight. The first of these let’s the developer get their feet wet by walking them through drawing a space ship on the screen that they can move with the arrow keys. These tutorials focus on simplicity, clarity and “getting something to work”, rather than writing battle-hardened, production-ready code. However, as time goes on, the tutorials will certainly get more advanced and I, personally, have plans to create and give away the source code to as many fully-playable Silverlight games as I can make.

Alright, let’s begin!

Prerequisites

QuickStart

If you want to see the end result of this tutorial and you have installed all the prerequisites, then please download the ZIP file below, unzip it and open the shootorial.html file in your browser. You should see a little ship that you can move using the arrow keys. Note, you will need to click on the Silverlight control to give it focus first.

You can also see it in action, here.

Lesson

Step 1: Create the HTML

Since we will display our Silverlight application on an HTML page, we’ll need the HTML to display it. Create a file named “shootorial.html” and put this HTML code in it:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
   <head>
      <title>Silverlight Shootorial #1 Application</title>
      <script type="text/javascript" src="Silverlight.js"></script>
      <script type="text/javascript" src="createSilverlight.js"></script>
    </head>
    <body>
      <div id="silverlightControlHost">
      </div>
      <script type="text/javascript">
          // Find the div by id
          var hostElement = document.getElementById("silverlightControlHost");
 
            // Create the Silverlight control
          createSilverlight(hostElement);
       </script>
    </body>
</html>
 

Now, place the Javascript that will create the Silverlight control in the usual “createSilverlight.js” file:


//creates the silverlight control within the tag specified by controlHostId
 
function createSilverlight( controlHost )
{
  Silverlight.createObjectEx({
    source: "ClientBin/ShootorialApplication.xap",
    parentElement: controlHost,
    id: "silverlightControl",
    properties: {
      width: "640",
      height: "480",
      version: "2.0.31005.0",
      background: "white",
      isWindowless: "true",
      enableHtmlAccess: "true"
    },
    events: {}
  });
}

This is par for the course when creating a Silverlight applicatoin. If you don’t understand the two code samples above, please read my Silverlight Application Framework tutorial. Also, remember to grab the latest version of Microsoft’s Silverlight.js file.

Step 2: Draw the Ship

Silverlight will need a Canvas to draw the space ship on, so create a file named “ShootorialControl.xaml” and add this code to it:


<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="ShootorialApplication.ShootorialControl">
  <Canvas x:Name="theCanvas" Width="640" Height="480">
  </Canvas>
</UserControl>

Kongregate’s Shootorial #1 represents the ship using a PNG image found here. The sample download ZIP file also contains that same PNG. To make Silverlight display it, add an Image object and assign the Source property to its location:


<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="ShootorialApplication.ShootorialControl">
  <Canvas x:Name="theCanvas" Width="640" Height="480">
    <Image x:Name="spaceShip" Canvas.Left="281" Canvas.Top="222" Source="/ship.png">
    </Image>
  </Canvas>
</UserControl>

Assinging Source to “/ship.png” tells Silverlight to look on the server starting under the same path as the XAP file. So if, per usual, the XAP file is deployed in a folder named “ClientBin”, setting the Source to a URI of “/ship.png” means you will need to copy ship.png to the ClientBin directory, since that essentially represents the “root” of the lookup.

Step 3: Move the Ship

Moving the ship will require logic, which requires a class, so create file named “ShootorialControl.xaml.cs” and put this code in it:


namespace ShootorialApplication
{
  using System;
  using System.Windows;
  using System.Windows.Input;
  using System.Windows.Media;
  using System.Windows.Controls;
  using System.Windows.Shapes;
 
  public partial class ShootorialControl : UserControl
  {
    public ShootorialControl()
    {
                InitializeComponent();
    }
  }
}

Nothing out of the ordinary here; just our typical UserControl. The ship will move in response to keyboard input events, so the class will need a key event handler:


namespace ShootorialApplication
{
  using System;
  using System.Windows;
  using System.Windows.Input;
  using System.Windows.Media;
  using System.Windows.Controls;
  using System.Windows.Shapes;
 
  public partial class ShootorialControl : UserControl
  {
    public ShootorialControl()
    {
                InitializeComponent();
      
                this.KeyDown += new KeyEventHandler(ShootorialControl_KeyDown);
    
}
    
    private void ShootorialControl_KeyDown(object sender, KeyEventArgs e)
    {
    }

  }
}

Everytime the player presses a key while this UserControl has focus, it raises a KeyDown event. Adding the function ShootorialControl_KeyDown as a KeyEventHandler to the KeyDown event insures that everytime the event raises, Silverlight calls the ShootorialControl_KeyDown function. The KeyEventArgs object contains the information on which key the user pressed.

Depending on which key the user pressed, we will either increment or decrement the X or Y position by small amounts to give the illusion of fluid movement. For example, if the user presses the “right” arrow key, the ship should increase its X position so Silverlight moves it to the right.

In this tutorial, the ship will change its X and Y position in increments of 10, stored in a variable named velocity:


...
public partial class ShootorialControl : UserControl
{
  private int velocity = 10;
 
  public ShootorialControl()
  {
           InitializeComponent();
 
    this.KeyDown += new KeyEventHandler(ShootorialControl_KeyDown);    
  }
...

And finally, the movement code:


...
private void ShootorialControl_KeyDown(object sender, KeyEventArgs e)
{
  if( e.Key == Key.Right )
    Canvas.SetLeft(spaceShip, Canvas.GetLeft(spaceShip) + velocity);
  else if( e.Key == Key.Left )
    Canvas.SetLeft(spaceShip, Canvas.GetLeft(spaceShip) - velocity);
  else if( e.Key == Key.Up )
    Canvas.SetTop(spaceShip, Canvas.GetTop(spaceShip) - velocity);
  else if( e.Key == Key.Down )
    Canvas.SetTop(spaceShip,Canvas.GetTop(spaceShip) + velocity);
}
...

This should read fairly easily: the code checks the Key property of the KeyEventArgs to determine which key the user pressed. Depending on that key, the code first gets the current left or top coordinate of the Image object stored in the spaceShip variable (by setting the x:Name attribute in the XAML), and then adds or subtracts the velocity value from it. Finally, it then sets that same left or top value to the newly computed value, effectively moving the ship in the user-designated direction.

Pretty simple, eh?

For completeness, here’s the code in its entirety:


namespace ShootorialApplication
{
  using System;
  using System.Windows;
  using System.Windows.Input;
  using System.Windows.Media;
  using System.Windows.Controls;
  using System.Windows.Shapes;
 
  public partial class ShootorialControl : UserControl
  {
    private int velocity = 10;
 
    public ShootorialControl()
    {
                InitializeComponent();
 
      this.KeyDown += new KeyEventHandler(ShootorialControl_KeyDown);    
    }
 
    private void ShootorialControl_KeyDown(object sender, KeyEventArgs e)
    {
      if( e.Key == Key.Right )
        Canvas.SetLeft(spaceShip, Canvas.GetLeft(spaceShip) + velocity);
      else if( e.Key == Key.Left )
        Canvas.SetLeft(spaceShip, Canvas.GetLeft(spaceShip) - velocity);
      else if( e.Key == Key.Up )
        Canvas.SetTop(spaceShip, Canvas.GetTop(spaceShip) - velocity);
      else if( e.Key == Key.Down )
        Canvas.SetTop(spaceShip,Canvas.GetTop(spaceShip) + velocity);
    }
  }
}
Step 4: Build it

The build file for this tutorial looks very similar to the one in the MSBuild tutorial with one exception:


...
<ItemGroup>
  <Page Include="ShootorialControl.xaml">
   <Generator>MSBuild:CompileXaml</Generator>
  </Page>
  <Compile Include="ShootorialControl.xaml.cs">
   <DependentUpon>ShootorialControl.xaml</DependentUpon>
  </Compile>
</ItemGroup>

<ItemGroup>
   <None Include="ship.png">
     <CopyToOutputDirectory>Always</CopyToOutputDirectory>
   </None>
</ItemGroup>

<ItemGroup>
  <Reference Include="mscorlib" />
  <Reference Include="system" />
  <Reference Include="System.Windows" />
</ItemGroup>
...

As you’ll notice, the highlighted ItemGroup contains a build action of None for the file named “ship.png”. This means that MSBuild won’t try to compile or transform the image in any way, which would be invalid. The element CopyToOutputDirectory tells MSBuild to put the ship.png directory in the same output directory of the XAP file. Convenient since, per the XAML, the Image’s Source property points to this path.

For this first tutorial, I will go ahead and put all the files needed to build this application in this post. If there’s something you don’t understand, please refer to my previous MSBuild tutorial.

App.xaml


<Application
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="ShootorialApplication.App"
    Startup="Application_Startup">
 
</Application>

App.xaml.cs


using System.Windows;
 
namespace ShootorialApplication
{
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();
        }
 
        void Application_Startup(object sender, StartupEventArgs e)
        {
            // Load the main control
            this.RootVisual = new ShootorialControl();
        }
    }
}

AppManifest.xml


<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</Deployment>

ShootorialApplication.csproj


<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
   <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
   <SchemaVersion>2.0</SchemaVersion>
   <NoStdLib>true</NoStdLib>
   <NoStdCfg>true</NoStdCfg>
 
   <RootNamespace>ShootorialApplication</RootNamespace>
   <AssemblyName>ShootorialApplication</AssemblyName>
 
   <OutputType>Library</OutputType>
   <OutputPath>ClientBin</OutputPath>
</PropertyGroup>
 
<ItemGroup>
  <Compile Include="App.xaml.cs">
   <DependentUpon>App.xaml</DependentUpon>
  </Compile>
  <ApplicationDefinition Include="App.xaml">
   <Generator>MSBuild:MarkupCompilePass1</Generator>
  </ApplicationDefinition>
</ItemGroup>
 
<ItemGroup>
  <Page Include="ShootorialControl.xaml">
   <Generator>MSBuild:CompileXaml</Generator>
  </Page>
  <Compile Include="ShootorialControl.xaml.cs">
   <DependentUpon>ShootorialControl.xaml</DependentUpon>
  </Compile>
</ItemGroup>
 
<ItemGroup>
   <None Include="ship.png">
     <CopyToOutputDirectory>Always</CopyToOutputDirectory>
   </None>
</ItemGroup>
 
<ItemGroup>
  <Reference Include="mscorlib" />
  <Reference Include="system" />
 
  <Reference Include="System.Windows" />
</ItemGroup>
 
<PropertyGroup>
 
   <SilverlightApplication>true</SilverlightApplication>
   <SilverlightAppEntry>ShootorialApplication.App</SilverlightAppEntry>
   <SilverlightManifestTemplate>AppManifest.xml</SilverlightManifestTemplate>
   <GenerateSilverlightManifest>true</GenerateSilverlightManifest>
   <XapOutputs>true</XapOutputs>
   <XapFilename>ShootorialApplication.xap</XapFilename>
</PropertyGroup>
 
<Import Project="$(MSBuildExtensionsPath)\Microsoft\Silverlight\v2.0\Microsoft.Silverlight.CSharp.targets" />
</Project>

You can build the software with this command:


"C:\WINDOWS\Microsoft.NET\Framework\v3.5\msbuild.exe" ShootorialApplication.csproj
Step 5: Run it

To run it, just open the shootorial.html file in your browser. Before you can move the ship, you may need to click on the Silverlight control to give it focus (just try clicking on the ship itself). Using the arrow keys, you should be able to move the ship up, down, left and right.

Conclusion

That concludes the first Shootorial conversion. However, before we part ways, I wanted to quickly address some of the differences between this and the Kongregate’s Flash version:

Well, I hope you learned something useful from this tutorial. I know I did. And not to worry, the next one is on its way ;).

Share and Enjoy:
These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • StumbleUpon
  • Reddit
  • del.icio.us
Related Posts:
10 Minute Silverlight Game Programming Tutorial - Shootorial Conversion #4 (C#)
10 Minute Silverlight Game Programming Tutorial - Shootorial Conversion #2 (C#)
10 Minute Silverlight Game Programming Tutorial - Shootorial Conversion #3 (C#)
10 Minute Silverlight Game Programming Tutorial - Shootorial Conversion #5 (C#)

Comments

One Response to “10 Minute Game Programming Tutorial: Silverlight - Shootorial #1 Conversion (C#)”

  1. Silverlight Cream for November 07, 2008 -- #422 on November 7th, 2008 1:41 pm

    […] out there that I’m going to have to catch up with!. In addition to this first post, he has 10 Minute Game Programming Tutorial: Silverlight - Shootorial #1 Conversion (C#) and 10 Minute Silverlight Game Programming Tutorial - Shootorial Conversion #2 (C#) available… […]