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
- While Kongregate’s tutorials assume you nothing about writing applications in Flash, here I assume you know the basics of programming and have at least skimmed my previous Silverlight tutorials so you know how to build and deploy a basic Silverlight application. If you haven’t and don’t understand something, please take moment to refresh yourself with the concepts of building applications in Silverlight by reading the tutorials below (concentrate on the last one, in particular):
- Also, I posted an introduction to writing games in Silverlight that you may find helpful: Introduction to game programming in Silverlight
- If nothing else, make sure you have all the prerequisites defined in the Silverlight MSBuild tutorial, so you can build and run the program at the end of this tutorial
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.
- Shootorial #1 Sample (you may read this software’s license here)
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.
- Learn more about the KeyDown event
- Learn more about the KeyEventHandler delegate
- Learn more about the KeyEventArgs class
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?
- Learn more about GetLeft static function
- Learn more about GetTop static function
- Learn more about SetLeft static function
- Learn more about SetTop static function
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:
- In step 5, Kongregate creates a Ship class derived from MovieClip. The MovieClip class acts as Flash’s main workhorse. Without going too deep, a MovieClip is just that: it has a time line, stop/pause/play capability, seek functionality, etc. It also represents the easiest way to get bitmap data to the screen, so unsurprisingly they used it here. Now , I could have also subclassed Image (or, better yet, used composition ;)), however it looked like Kongregate subclassed MovieClip to put their key handling logic inside its onEnterFrame function. Since, I want the root Canvas to handle key input I decided not to subclass…for now ;). Speaking of onEnterFrame…
- In step 11, Kongregate handles all the key logic in onEnterFrame. For those unacquainted with Flash, the onEnterFrame gets called every frame that Flash draws. To explain “frames” in layman’s terms, typically, Flash redraws its portion of the screen many times per second and a “frame” represents a completed drawing. The combination of quick drawing and incremental movement of MovieClips creates the illusion of fluid movement to the naked eye. So, in Kongregates example, for each frame, they poll the keyboard for input, and move the ship according to the key pressed. Silverlight works differently because it pushes keyboard events to you. However, the differences equate to the same functionality: Flash polls, moves, then draws while Silverlight pushes, moves, and then draws. Both the push method Silverlight uses, and the pull method Flash uses have their pros and cons, and you will discover them as we dig further into game programming.
Finally, for your information, Silverlight has an event named CompositionTarget.Rendering which Silverlight raises every frame similar to how Flash calls onEnterFrame every frame. You will see this used in later tutorials.
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 ;).
Related Posts:
Comments
One Response to “10 Minute Game Programming Tutorial: Silverlight - Shootorial #1 Conversion (C#)”




[…] 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… […]