Creating a Shuffleboard Game using Silverlight

In this walkthrough, we will create a
table shuffleboard style game for Windows Phone 7 using Silverlight. Many bars feature these long wooden table games, in which players slide metal pucks down the length of the table, attempting to get as close as possible to the far end without sliding
off the edge.

Multi-Targeting

Windows Phone 7 uses a version of Silverlight 3 with a few bonus features. Because this version of Silverlight is so close to the Web version of Silverlight 3, we'll take the approach of
Multitargeting a solution for both platforms. To do so, start with a Silverlight 3 (web) application template, and then add in a Windows Phone project with linked files that re-use the Silverlight 3 solution. This allows us to deploy to many different
platforms using the same code base.

Let's get started by creating our Solution in this way.

Creating the Solution and MainPage

In Expression Blend 4, create a new Silverlight Application + Website template named Shuffleboard. Be sure to select “3.0” from the Version dropdown, as this is what is supported by Windows Phone (in a little bit we'll add in the Windows Phone project template
as well).

In the Objects and Timeline Panel, select the main UserControl and set its Width to 480 and its Height to 800. This is the size of a Windows Phone UI in Portrait mode.

Select the LayoutRoot Grid and set its Width to 480 and its Height to 800.

For games, a Canvas layout container is better than a Grid, so let's change the LayoutRoot container type. Right-click LayoutRoot and select Change Layout Type/Canvas.

Since some parts of our UI can appear outside of the game area, we want to add a Clip to this main canvas so that the user does not see these outside elements. Add the following just under the LayoutRoot Canvas:
This XAML is snippet “MainPage Clip” inside snippets.txt.

<Canvas.Clip><RectangleGeometryRect="0,0,480,800"/></Canvas.Clip>

We'll be using some pre-built Behaviors that make it easy to introduce physics into Silverlight using the Farseer Physics Library. Right-click the Silverlight project and select Add Reference. Select the following assemblies, located in the sample download:

Creating the Game User Control

Next we'll create a separate user control that will contain the core game logic. By creating a separate user control, we can easily target different platforms by placing the user control inside different MainPage elements.

Right-click the Shuffleboard Silverlight project and select Add New Item. Select UserControl and name the control “ucMainGame”.

Change the LayoutRoot element from a Grid to a Canvas.

Set the Width to 480 and the Height to 800 for both the UserControl and LayoutRoot Canvas elements.

Set the Background color to Black for the LayoutRoot Canvas.

Build the project by pressing Ctrl+Shift+B.

Back on MainPage, add an instance of ucMainGame to the page by going to the Assets Panel and expanding Controls/All. Drag an instance of ucMainGame to the artboard.

Rename the ucMainGame control to ucMainGame1.

Set the Left and Top properties of ucMainGame1 to 0.

Creating the Table

We'll use a pre-rendered PNG image for the shuffleboard table.

Create a new subfolder in the Silverlight project named “images”.

Add the following JPG image into the new images subfolder, located in the sample download:
\ShuffleBoard\images\shuffleboardTable.jpg

Open the ucMainGame user control.

Insert a new Canvas element named cnvTable, and set the following attributes:

Width = 480

Height = 800

Left = 0

Top = 0

In the Assets Panel, expand the Behaviors category and drag a PhysicsControllerBehavior on the cnvTable. This behavior introduces the core physics simulation into the game. Set the properties of the Physics Contoller as follows (this turns of gravity and
sets some other physics parms):

Inside the cnvTable Canvas, add a second Canvas named cnvTableInner, which will hold the table image. Set the following properties on cnvTableInner:

Width = 360

Height = 1077

Left = 60

Top = -277

Drag the shuffleboardTable.jpg image from the Projects Panel into cnvTableInner. Set the following properties on the image:

Width = 360

Height = 1077

Left = 0

Top = 0

The Objects and Timeline Panel should look like so:

We will need to detect when a puck hits the edge of the table and “falls off.” Let's add in some Rectangle elements and add Physics Behaviors to them.

Add a new Rectangle named rectSensorLeft and size it so that it covers the entire left side of the table. Set the following properties:

Width = 60

Height = 1190

Left = -40

Top = -334

Opacity = 20%

Drag a PhysicsObjectBehavior from the Assets Panel Behaviors onto rectSensorLeft, and then set its IsStatic property to true.

Add three more Rectangles by copying rectSensorLeft, so that they surround the borders of the table:

rectSensorRight

rectSensorTop

rectSensorBottom

Your artboard should look similar to the following:

Now we'll add in the goal Rectangles at the end of the table. These will be used to determine the number of points a puck receives. Draw out three Rectangles that cover the width of the board and are 100 pixels high. Name these rectPoints3, rectPoints2,
and rectPoints1. Set their Stroke to Red and their Fill to No brush.

Add a TextBlock element inside each Rectangle to depict the points. Set the text properties to 3, 2, and 1 so that the artboard looks similar to the following:

We'll also need a Rectangle representing the “slide zone” where players can legally slide a puck (we don't want to allow sliding all of the way down the table!). Add a Rectangle named rectInBounds and position it at the lower end of the table:

Width=360

Height=292

Left = 60

Top = 508

Fill = No Brush

Stroke = Red

Adding the Pucks

For the pucks, we are going to add in an existing control which has the artwork completed.

Right-click the project and select Add Existing Item.

Browse to the following two files in the sample code download:
\ShuffleBoard\ucPuck.xaml
\ShuffleBoard\ucPuck.xaml.cs

Open ucPuck.xaml on the artboard and notice the following in the Objects and Timeline Panel:

There is a Canvas named Puck that has a PhysicsObjectBehavior applied to it. This allows each instance of this Canvas to behave like a Physics Object so it animates with velocity and force and participates in collisions. Note that this Behavior has a large
MomentOfInertia value. This keeps the object from rotating due to torque and collisions. Also note the RestitutionCoefficient, which gives the object some “bounce.”

There is a “cnvInner” Canvas that defines the look of the Puck.

There is a StoryBoard defined, sbLostPuck, which we will execute when the puck “falls off the edge” of the table.

Open the code-behind file, ucPuck.xaml.cs, and note the get / set property for the color of the puck. This will allow us to create both Red and Blue pucks for each player.

Build the project by hitting Ctrl+Shift+F5 and go back to ucMainGame.

From the Assets Panel, expand Controls/All and find the ucPuck control. Drag an instance of this onto the artboard. Name this
bluePuck1.

Copy and paste bluePuck1 twice so that you have three blue pucks. Name the new pucks
bluePuck2 and bluePuck3.

Copy and paste a fourth puck and name it redPuck1. In the Properties Panel, go to the Miscellaneous Category and change the ColorHighlight and ColorMain properties to a Red color:

Copy and Paste redPuck1 two times and rename these new pucks redPuck2 and
redPuck3.

Let's test our table. Find the PhysicsControllerBehavior just under the cnvTable Canvas in the Objects and Timeline Panel and set the MousePickEnabled property to true.

Run the project by clicking F5. Try dragging some pucks around with the mouse.

Adding the Scoreboard

We need a way of tracking players' scores, so let's add in a simple scoreboard for Blue vs. Red.

Right-click the project and select Add Existing Item.

Browse to the following two files in the download:
\ShuffleBoard\ShuffleBoard\ucScoreBoard.xaml
\ShuffleBoard\ShuffleBoard\ucScoreBoard.xaml.cs

Open ucScoreBoard and notice the following:

It has a TextBlock for Red scores and a TextBlock for Blue scores.

In the code-behind, there are setters and getters to set the score.

Build the project by selecting Ctrl+Shift+B.

Switch back to ucMainGame.

Drag an instance of ucScoreBoard from the Assets Panel onto into LayoutRoot.

Name the element ucScoreBoard1, and position it at the top left of the Canvas like so:

Adding a Player Up Display

We'll need a simple control that displays which player's turn it is.

Right-click the Silverlight project and select Add/Existing Item.

Browse to and select the following two files in the sample folder:
\ShuffleBoard\ucPlayerUp.xaml
\ShuffleBoard\ucPlayerUp.xaml.cs

Note the following about ucPlayerUp:

The code-behind file has a simple property, IsBlueTurn, which shows the appropriate message in the UI.

Build the project by clicking Ctrl+Shift+B

Back on ucMainGame, drag an instance of ucPlayerUp into cnvTableInner.

Name the control ucPlayerUp1 , and set the following properties:

Adding a 3D Look

Let's give our table a bit of a 3D look by adding a Perspective transform so the table appears to go off into the distance.

Create a new StoryBoard named sbRotateTable.

Select the cnvTable Canvas element.

Advance the timeline ahead one second.

In the Properties Panel, under Projection, set the X value to -40.

Your artboard should now look something like this:

Close the Storyboard to end recording.

We want to rotate the table after the PhysicsController is initialized so the Physics Helper can determine the boundaries of the physics objects properly. Start by adding in some Using statements at the top of ucMainGame.xaml.cs:
This code is snippet “ucMainGame Imports” inside snippets.txt.

using System.Collections.Generic;
using Spritehand.FarseerHelper;
using FarseerGames.FarseerPhysics.Mathematics;
using System.ComponentModel;

Next, let's add in some class-level declarations, which will store the physics controller, list of pucks, and some variables used to track shooting and scoring:
This code is snippet “ucMainGame Declarations” inside snippets.txt.

In the ucMainGame() constructor, add some code to set the MaxFrameRate to 30 (Windows Phone will be limited to 30 FPS) and wire up the Loaded event handler.
This code is snippet “ucMainGame Constructor” inside snippets.txt.

Next, we'll add in the event handlers that we just wired up in the loaded event. Note that the Initialized event starts the Rotate Table StoryBoard.
This code is “ucMainGame Event Handlers” inside snippets.txt.

Run the Project by clicking F5. Note the 3D look and try manipulating the pucks with the mouse.

Controlling the Pucks

Next, we'll add logic to control the player's turn and control and along with score. Note that, when we implement the Windows Phone version in a bit, we can take advantage of Multitouch Manipulation events. But since these events are not available in the
Web version of Silverlight 3, we'll use a simple mouse input mechanism.

Let's turn off the default mouse manipulation. Select the PhysicsControllerBehavior just under the cnvTable Canvas and set the MousePickEnabled property to false.

We need to get references to our Pucks, which the Physics Helper has translated into PhysicsSprite objects. A Physics Sprite contains the XAML UI for the Physics Object, plus the Physics Engine attributes for the underlying physics objects–including boundary
shape, mass, velocity, etc.
This code is “ucMainGame Initialized” inside snippets.txt.

Now we need to handle the Mouse events on the pucks in order to control the player's shot. When the player clicks the mouse down on a puck, we track the position along with time that they clicked. When the player moves the mouse, we update the puck position
and also check if the player paused or moved backwards. We do this in case the player is just adjusting the puck position and not yet sliding the puck for a shot. Finally, in the Mouse up event, we release the puck in the specified direction and apply an appropriate
amount of force to it. Copy in the snippet “Puck Mouse Control” from snippets.txt. Code is not shown here for brevity.

When the Physics Helper Library does its magic, it translates existing UI Elements into PhysicsSprite objects. So what if we want to get at the original controls, perhaps to execute a StoryBoard that we defined on them? We can do this by using the FindName
method to get the original user control instance. So, add the code below, which we'll use to get a reference to the Puck Storyboard “sbLostPuck”.

Implement the “Game Loop”

Most games are controlled by a “Game Loop” that executes many times per second. Within this Game Loop, we can check for collisions, perform enemy AI, and scoring. The PhysicsController fires an event called “TimerLoop” that we can use for this purpose.

Replace the existing TimerLoop and Collision events with the following code snippet, which checks to see if any pucks have been shot and if we are ready for the next shot. Do this by seeing if the puck velocity has slowed down to nearly a stop…
This code is snippet “Timer Loop” inside snippets.txt.

Targeting Windows Phone

So far, we've created a Silverlight 3, web-based version of a shuffleboard game. Next we'll quickly port this to Windows Phone, taking advantage of some of the platform's capabilities, such as multitouch. We'll do this by using
linked files that point back to our existing Silverlight 3 project.

Right-click the Silverlight solution in Blend and select Add New Project.

Select Windows Phone Application and enter ShuffleBoard.WindowsPhone for the name.

Delete the TitleGrid and ContentGrid elements from the Objects and Timeline Panel.

Convert LayoutRoot to a Canvas by right-clicking it and selecting Change Layout Type/Canvas.

Right-click the project and select Add Reference. Browse to the following assemblies located in the sample download (these are the WindowsPhone versions of the Physics Helper and Farseer):

We need references to the assemblies used for Behaviors. An easy way to do this is to add a Behavior to an element and then delete it. From the Assets panel, drag a PhysicsControllerBehavior onto LayoutRoot and then delete it. Note that this adds a reference
to System.Windows.Interactivity to the project.

Next, we'll add in the linked files from the existing Silverlight 3 project. Right-click the ShuffleBoard.WindowsPhone project and select Add/Link to Existing Item. Select the following files:

ucMainGame.xaml

ucMainGame.xaml.cs

ucPlayerUp.xaml

ucPlayerUp.xaml.cs

ucPuck.xaml

ucPuck.xaml.cs

ucScoreBoard.xaml

ucScoreBoard.xaml.cs

8. Add a new folder to the project named images.

9. Right-click the images folder and select Link to Existing item, then navigate to the following image in the sample folder:
\ShuffleBoard\images\shuffleboardTable.jpg

Build the project by clicking Ctrl+Shift+B.

From the Assets Panel, under Controls/All, find ucMainGame and drag an instance onto LayoutRoot. Set the Left and Top properties to 0.

Right-click the WindowsPhone project and select “Startup” to set this as the startup project.

Run the project by clicking F5.

Windows Phone Touch Input

So far, we've used a simple mouse-event-based input mechanism for shooting the pucks. But on the Windows Phone 7 platform, we can do better than that by using Multitouch events. These events include an inertia property that will make our puck physics more
realistic.

Since we are going to need to support two different platforms now (Web and Windows Phone), we need to introduce a Conditional Compilation Symbol so that the compiler can differentiate between each platform's code.

Open the solution inside Visual Studio by right-clicking it in the Projects Panel and then select “Edit in Visual Studio”

4. Add in a new compilation symbol for WINDOWS_PHONE.
NOTE: Future releases of WP7 Tools will likely define a default compilation symbol, so you may already see one defined here.

Now we'll add in the Windows Phone-specific events for manipulation using touch. Open ucMainGame.xaml.cs and find the _physicsController_Initialized event handler. Replace the events for the mouse events with the following, which will wire up either the
manipulation events (for Windows Phone) or the mouse events (for Silverlight Web):
This code is snippet “Manipulation Events” inside snippets.txt.

Now we just need to implement those event handlers for manipulation. The main consideration here is that the ManipulationCompleted event passes in a FinalVelocity.LinearVelocity parameter, which we can use to create realistic physics from the user's shot:

Performance

Depending on your configuration, you may experience poor performance for the shuffleboard game when running it in the Windows Phone emulator. There are different reasons for this, including video card drivers and virtualization settings. Please refer to
this blog post, which details these performance considerations.

1. Inside the ucMainGame constructor, let's turn on the Frame Rate counter so we can see our current frame rate. This code is snippet “Frame Rate Counter” inside snippets.txt

Application.Current.Host.Settings.EnableFrameRateCounter = true;

Run the project by hitting F5, and note the current frame rate. NOTE: Your development configuration may prevent you from having an adequate framerate in the Windows Phone Emulator! Please refer to
this blog post for tips on emulator performance.

One performance tweak we can easily make is taking advantage of hardware acceleration. Silverlight enables us to use the video card to render elements, which can greatly increase performance. To do this, we add a Cachemode=”BitmapCache” attribute to any
elements we want to hardware accelerate.

Open ucPuck.xaml and note that there is a CacheMode attribute on the Puck Canvas.

Open ucMainGame.xaml and add a CacheMode attribute to the cnvTable Canvas element.

Adding Sound

Sound is one area where Windows Phone and Web Silverlight differ a bit. Under Silverlight for Web, we can use the MediaElement class to play back WMA and MP3 format audio. Multiple instances of the MediaElement class can be played simultaneously, and the
sound output will be automatically mixed.

However, on Windows Phone we have access to the XNA game libraries, including sound support. This is a much more efficient way to add mixed sound to a Silverlight game on Windows Phone, but it only supports WAV format sound files.

The Physics Helper Library has a useful class wrapper for sounds, which we'll use to play a “hit puck” sound on both platforms.

Add an existing item to the sounds folder from this location:
\ShuffleBoard\ShuffleBoard\sounds\hitPuck.wma

Set the Build Action of the file to Content.

In the ShuffleBoard.WindowsPhone project, right-click and select Add Folder.

Name the folder sounds.

Add an existing item to the sounds folder from this location:
\ShuffleBoard.WindowsPhone\sounds\hitPuck.wav

Set the Build Action of the file to Content.

Inside ucMainGame.xaml.cs, add a class-level declaration for a SoundMain class (this is defined in the Physics Helper Library):
This snippet is “Declare the Sound” inside snippets.txt.

SoundMain _soundPuckHit;

10. Inside the ucMainGame_Loaded event, add code to declare the two sounds. Note that Windows Phone uses a WAV format sound without a “/” prefix for the root.
This snippet is “Declare the Sound” inside snippets.txt.

Summary

Since the 1.1 Alpha release, Silverlight has offered a compelling casual game development environment. With the addition of Windows Phone, along with demos of Silverlight running on other embedded devices, you can bet the future of Silverlight for gaming
is bright.

Thanks Andy. I am unable to use Expression blend for phone because of the poor performance of emulator on my system (my system's GPU is not supported i reckon). So I was thinking of following your lead and develop silverlight games for web initially - and later port them to phone.

Remove this comment

Remove this thread

Comments Closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation,
please create a new thread in our Forums, or
Contact Us and let us know.