Entries:
Comments:
Posts:

Loading User Information from Channel 9

Something went wrong getting user information from Channel 9

Latest Achievement:

Loading User Information from MSDN

Something went wrong getting user information from MSDN

Visual Studio Achievements

Latest Achievement:

Loading Visual Studio Achievements

Something went wrong getting the Visual Studio Achievements

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.

image 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

  1. 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).
    image
  2. 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.
  3. Select the LayoutRoot Grid and set its Width to 480 and its Height to 800.
  4. 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.
    image
  5. 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>
        <RectangleGeometry Rect="0,0,480,800"/>
    </Canvas.Clip>
  6. 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:

    \ShuffleBoard\Bin\Debug\FarseerPhysics.dll
    \ShuffleBoard\Bin\Debug\Spritehand.FarseerHelper.dll
    \ShuffleBoard\Bin\Debug\Spritehand.PhysicsBehaviors.dll

    NOTE: To learn more about the Physics Helper Library, visit http://physicshelper.codeplex.com

Get Microsoft Silverlight

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.

  1. Right-click the Shuffleboard Silverlight project and select Add New Item. Select UserControl and name the control “ucMainGame”.
    image
  2. Change the LayoutRoot element from a Grid to a Canvas.
  3. Set the Width to 480 and the Height to 800 for both the UserControl and LayoutRoot Canvas elements.
  4. Set the Background color to Black for the LayoutRoot Canvas.
  5. Build the project by pressing Ctrl+Shift+B.
  6. 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.
    image
  7. Rename the ucMainGame control to ucMainGame1.
  8. 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.

  1. Create a new subfolder in the Silverlight project named “images”.
  2. Add the following JPG image into the new images subfolder, located in the sample download:
    \ShuffleBoard\images\shuffleboardTable.jpg
  3. Open the ucMainGame user control.
  4. Insert a new Canvas element named cnvTable, and set the following attributes:
    1. Width = 480
    2. Height = 800
    3. Left = 0
    4. Top = 0
  5. 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):
    image
  6. Inside the cnvTable Canvas, add a second Canvas named cnvTableInner, which will hold the table image. Set the following properties on cnvTableInner:
    1. Width = 360
    2. Height = 1077
    3. Left = 60
    4. Top = -277
  7. Drag the shuffleboardTable.jpg image from the Projects Panel into cnvTableInner. Set the following properties on the image:
    1. Width = 360
    2. Height = 1077
    3. Left = 0
    4. Top = 0
  8. The Objects and Timeline Panel should look like so:
    image
  9. 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.
  10. Add a new Rectangle named rectSensorLeft and size it so that it covers the entire left side of the table. Set the following properties:image
    1. Width = 60
    2. Height = 1190
    3. Left = -40
    4. Top = -334
    5. Opacity = 20%
  11. Drag a PhysicsObjectBehavior from the Assets Panel Behaviors onto rectSensorLeft, and then set its IsStatic property to true.
  12. Add three more Rectangles by copying rectSensorLeft, so that they surround the borders of the table:
    1. rectSensorRight
    2. rectSensorTop
    3. rectSensorBottom
  13. Your artboard should look similar to the following:
    image
  14. 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.
  15. 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:
    image
  16. 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:
    1. Width=360
    2. Height=292
    3. Left = 60
    4. Top = 508
    5. Fill = No Brush
    6. Stroke = Red

Get Microsoft Silverlight

Adding the Pucks

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

  1. Right-click the project and select Add Existing Item.
  2. Browse to the following two files in the sample code download:
    \ShuffleBoard\ucPuck.xaml
    \ShuffleBoard\ucPuck.xaml.cs
  3. Open ucPuck.xaml on the artboard and notice the following in the Objects and Timeline Panel:
    image
    1. 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.”
      image
    2. There is a “cnvInner” Canvas that defines the look of the Puck.
    3. There is a StoryBoard defined, sbLostPuck, which we will execute when the puck “falls off the edge” of the table.
    4. 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.
  4. Build the project by hitting Ctrl+Shift+F5 and go back to ucMainGame.
  5. From the Assets Panel, expand Controls/All and find the ucPuck control. Drag an instance of this onto the artboard. Name this bluePuck1.
  6. Copy and paste bluePuck1 twice so that you have three blue pucks. Name the new pucks bluePuck2 and bluePuck3.
  7. 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:
    image
  8. Copy and Paste redPuck1 two times and rename these new pucks redPuck2 and redPuck3.
  9. 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.
  10. Run the project by clicking F5. Try dragging some pucks around with the mouse.

Get Microsoft Silverlight

Adding the Scoreboard

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

  1. Right-click the project and select Add Existing Item.
  2. Browse to the following two files in the download:
    \ShuffleBoard\ShuffleBoard\ucScoreBoard.xaml
    \ShuffleBoard\ShuffleBoard\ucScoreBoard.xaml.cs
  3. Open ucScoreBoard and notice the following:
    1. It has a TextBlock for Red scores and a TextBlock for Blue scores.
    2. In the code-behind, there are setters and getters to set the score.
  4. Build the project by selecting Ctrl+Shift+B.
  5. Switch back to ucMainGame.
  6. Drag an instance of ucScoreBoard from the Assets Panel onto into LayoutRoot.
  7. Name the element ucScoreBoard1, and position it at the top left of the Canvas like so:

image

Adding a Player Up Display

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

  1. Right-click the Silverlight project and select Add/Existing Item.
  2. Browse to and select the following two files in the sample folder:
    \ShuffleBoard\ucPlayerUp.xaml
    \ShuffleBoard\ucPlayerUp.xaml.cs
  3. Note the following about ucPlayerUp:
    1. The code-behind file has a simple property, IsBlueTurn, which shows the appropriate message in the UI.
  4. Build the project by clicking Ctrl+Shift+B
  5. Back on ucMainGame, drag an instance of ucPlayerUp into cnvTableInner.
  6. Name the control ucPlayerUp1 , and set the following properties:
    image

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.

  1. Create a new StoryBoard named sbRotateTable.
    image
  2. Select the cnvTable Canvas element.
  3. Advance the timeline ahead one second.
  4. In the Properties Panel, under Projection, set the X value to -40.
    image
  5. Your artboard should now look something like this:
    image
  6. Close the Storyboard to end recording.
    image
  7. 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;
  8. 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.
    PhysicsControllerMain _physicsController;
    List<PhysicsSprite> _pucks = new List<PhysicsSprite>();
    List<PhysicsSprite> _redPucks = new List<PhysicsSprite>();
    Point _ptStartShot;
    bool _draggingPuck;
    int _draggingStartTick;
    
    int _currentPuckToShoot = 0;
    int _currentPuckShot = -1;
    int _gameOverScore = 15;
  9. 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.
    this.Loaded += new RoutedEventHandler(ucMainGame_Loaded);
    Application.Current.Host.Settings.MaxFrameRate = 30;
  10. Implement the ucMainGame_Loaded event handler, which gets a reference to the Physics Controller and wires up our event handlers.
    This code is snippet “ucMainGame Loaded” inside snippets.txt.
    void ucMainGame_Loaded(object sender, RoutedEventArgs e)
    {
        if (DesignerProperties.GetIsInDesignMode(this))
            return;
    
        _physicsController = 
            cnvTable.GetValue(
                PhysicsControllerMain.PhysicsControllerProperty
            ) as PhysicsControllerMain;
        _physicsController.Initialized += _physicsController_Initialized;
        _physicsController.Collision += _physicsController_Collision;
        _physicsController.TimerLoop += _physicsController_TimerLoop;
    }
  11. 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.
    void _physicsController_Initialized(object source)
    {
        sbRotateTable.Begin();
    }
    
    void _physicsController_Collision(string sprite1, string sprite2)
    { }
    
    void _physicsController_TimerLoop(object source)
    { }
  12. 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.

  1. Let's turn off the default mouse manipulation. Select the PhysicsControllerBehavior just under the cnvTable Canvas and set the MousePickEnabled property to false.
  2. 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.
  3. 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.
  4. 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”.
    ucPuck GetPuckControl(string spriteName)
    {
        ucPuck puck;
        var parent = PhysicsControllerMain.ParentCanvas;
        switch (spriteName)
        {
            case "Puck":
                puck = parent.FindName("bluePuck1") 
                        as ucPuck;
                break;
            case "Puck_1":
                puck = parent.FindName("bluePuck2") 
                        as ucPuck;
                break;
            case "Puck_2":
                puck = parent.FindName("bluePuck3") 
                        as ucPuck;
                break;
            case "Puck_3":
                puck = parent.FindName("redPuck1") 
                        as ucPuck;
                break;
            case "Puck_4":
                puck = parent.FindName("redPuck2") 
                        as ucPuck;
                break;
            default:
                puck = parent.FindName("redPuck3") 
                        as ucPuck;
                break;
        }
    
        return puck;
    }
  5. Finally, to score, we'll determine if the puck lies between any of the Rectangles in the end zone.
    This code is the snippet “Get Points for Puck” in snippets.txt.
    int GetPointsForPuck(PhysicsSprite puck)
    {
        int score = 0;
        Vector2 puckPos = puck.BodyObject.Position;
    
        double left = Convert.ToDouble(
            rectPoints3.GetValue(Canvas.LeftProperty));
        double top = Convert.ToDouble(
            rectPoints3.GetValue(Canvas.TopProperty));
    
        if ((puckPos.X > left && puckPos.X < left + rectPoints3.Width) 
         && (puckPos.Y > top && puckPos.Y < top + rectPoints3.Height))
            score = 3;
    
        left = Convert.ToDouble(rectPoints2.GetValue(Canvas.LeftProperty));
        top = Convert.ToDouble(rectPoints2.GetValue(Canvas.TopProperty));
        if ((puckPos.X > left && puckPos.X < left + rectPoints2.Width) 
         && (puckPos.Y > top && puckPos.Y < top + rectPoints2.Height))
            score = 2;
    
        left = Convert.ToDouble(rectPoints1.GetValue(Canvas.LeftProperty));
        top = Convert.ToDouble(rectPoints1.GetValue(Canvas.TopProperty));
        if ((puckPos.X > left && puckPos.X < left + rectPoints1.Width) 
         && (puckPos.Y > top && puckPos.Y < top + rectPoints1.Height))
            score = 1;
    
        return score;
    }

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.

  1. 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.
    void _physicsController_TimerLoop(object source)
    {
        // check to see if the current shot is completed
        if (_currentPuckShot >= 0)
        {
        var puck = _pucks[_currentPuckShot].BodyObject;
    
            if (puck.Enabled == false ||
              Math.Abs(puck.LinearVelocity.X) < 3                                   
              && 
              Math.Abs(puck.LinearVelocity.Y) < 3)
            {
                // did the shot clear the end zone?
                if (!PointWithinBounds(
                  new Point(puck.Position.X, 
                           puck.Position.Y)))
                {
                    _currentPuckShot = -1;
                    _currentPuckToShoot++;
                    SetupThePuck();
                }
            }
        }
    }
    
    void _physicsController_Collision(string sprite1, string sprite2)
    {
        // check for puck off sides
        if (sprite1.StartsWith("rectSensor") && sprite2.StartsWith("Puck"))
        {
            ucPuck puck = GetPuckControl(sprite2);
    
            _physicsController.PhysicsObjects[sprite2].
                BodyObject.Enabled = false;
    
            puck.sbLostPuck.Begin();
        }
    }

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.

  1. Right-click the Silverlight solution in Blend and select Add New Project.
  2. Select Windows Phone Application and enter ShuffleBoard.WindowsPhone for the name.
    image
  3. Delete the TitleGrid and ContentGrid elements from the Objects and Timeline Panel.
  4. Convert LayoutRoot to a Canvas by right-clicking it and selecting Change Layout Type/Canvas.
  5. 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):

    \ShuffleBoard.WindowsPhone\Bin\Debug\FarseerPhysics.dll
    \ShuffleBoard.WindowsPhone\Bin\Debug\Spritehand.FarseerHelper.dll
    \ShuffleBoard.WindowsPhone\Bin\Debug\Spritehand.PhysicsBehaviors.dll
  6. 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.
  7. 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:
    1. ucMainGame.xaml
    2. ucMainGame.xaml.cs
    3. ucPlayerUp.xaml
    4. ucPlayerUp.xaml.cs
    5. ucPuck.xaml
    6. ucPuck.xaml.cs
    7. ucScoreBoard.xaml
    8. ucScoreBoard.xaml.cs
  8. 8. Add a new folder to the project named images.
  9. 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
  10. Build the project by clicking Ctrl+Shift+B.
  11. From the Assets Panel, under Controls/All, find ucMainGame and drag an instance onto LayoutRoot. Set the Left and Top properties to 0.
  12. Right-click the WindowsPhone project and select “Startup” to set this as the startup project.
  13. Run the project by clicking F5.

Get Microsoft Silverlight

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.

  1. 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.
  2. Open the solution inside Visual Studio by right-clicking it in the Projects Panel and then select “Edit in Visual Studio”
    image
  3. Right-click the ShuffleBoard.WindowsPhone Project and select Properties.
  4. 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.
    image
  5. 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.
    #if WINDOWS_PHONE
        puck.ManipulationStarted += 
          new EventHandler<ManipulationStartedEventArgs>
          (puck_ManipulationStarted);
        puck.ManipulationCompleted += 
          new EventHandler<ManipulationCompletedEventArgs>
          (puck_ManipulationCompleted);
        puck.ManipulationDelta += 
          new EventHandler<ManipulationDeltaEventArgs>
          (puck_ManipulationDelta);
    #else
        puck.MouseLeftButtonDown += 
          new MouseButtonEventHandler(puck_MouseLeftButtonDown);
        puck.MouseMove += 
          new MouseEventHandler(puck_MouseMove);
        puck.MouseLeftButtonUp += 
          new MouseButtonEventHandler(puck_MouseLeftButtonUp);
    #endif
  6. 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:

    Add the code snippet “Manipulation Event Handlers” from snippets.txt

    Vector2 force = new Vector2(
        (float)(e.FinalVelocities.LinearVelocity.X * scalePower), 
        (float)(e.FinalVelocities.LinearVelocity.Y * scalePower));
  7. Run the project by clicking F5, and try sliding some pucks.

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. 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;
  2. 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.

  1. Open ucPuck.xaml and note that there is a CacheMode attribute on the Puck Canvas.
  2. Open ucMainGame.xaml and add a CacheMode attribute to the cnvTable Canvas element.
    <Canvas x:Name="cnvTable" Width="480" Height="800" 
    d:LayoutOverrides="Width, Height" CacheMode="BitmapCache">
  3. Run the project and note the frame rate change.

Get Microsoft Silverlight

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.

  1. In the ShuffleBoard (Silverlight Web) project, right-click and select Add Folder.
  2. Name the folder sounds.
  3. Add an existing item to the sounds folder from this location:
    \ShuffleBoard\ShuffleBoard\sounds\hitPuck.wma
  4. Set the Build Action of the file to Content.
  5. In the ShuffleBoard.WindowsPhone project, right-click and select Add Folder.
  6. Name the folder sounds.
  7. Add an existing item to the sounds folder from this location:
    \ShuffleBoard.WindowsPhone\sounds\hitPuck.wav
  8. Set the Build Action of the file to Content.
  9. 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. 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.
    #if WINDOWS_PHONE
        _soundPuckHit = new SoundMain(this.LayoutRoot,
                       "sounds/hitPuck.wav", 2, 0);
    #else
        _soundPuckHit = new SoundMain(this.LayoutRoot, 
                       "/sounds/hitPuck.wma", 2, 0);
    #endif
  11. Inside the _physicscontroller_collision event, add code to play the sound if a puck-to-puck collision occurs and the velocity is > 10:
    This snippet is “Play the Sound” inside snippets.txt.
    // check for puck to puck collsion
    if (sprite1.StartsWith("Puck") && sprite2.StartsWith("Puck"))
    {
        PhysicsSprite sprite = _physicsController.PhysicsObjects[sprite1];
    
        if (Math.Abs(sprite.BodyObject.LinearVelocity.X) > 10
            || Math.Abs(sprite.BodyObject.LinearVelocity.Y) > 10)
        {
            _soundPuckHit.Play();
        }
    }
  12. Run the project and try hitting pucks together.

Get Microsoft Silverlight

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.

Here are a few resources for more information:

Andy's blog
http://www.andybeaulieu.com

Andy's Silverlight Demos
http://www.spritehand.com

The Physics Helper Library
http://physicshelper.codeplex.com

Great free resource for learning Expression Blend and Silverlight
http://www.microsoft.com/design/toolbox/

Tags:

Follow the Discussion

  • Clint RutkasClint I'm a "developer"

    @ge-force WPF sure with a bit of work, you could do a Silverlight OOB (Out of browser) as well and that should "just work".

    Windows form, not scrapping almost everything.

  • ge-forcege-force

    !his is great - would it be easy to do in a wpf or windows forms app?

  • Clint RutkasClint I'm a "developer"

    @Bendy, tooling was just released, looking into it right now

  • BendyBendy

    Are you going to do an update for the beta tools for WP7

  • Clint RutkasClint I'm a "developer"

    @Bendy, source has been updated

  • GunnerzGunnerz

    Excellent work Andy. Which version of expression blend are you using? Where can I download/buy it from?

  • GunnerzGunnerz

    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.

  • Clint RutkasClint I'm a "developer"

    @Gunnerz Expression Blend for the Phone is free and can be downloaded from developer.windowsphone.com

Remove this comment

Remove this thread

close

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.