anatomy february 1 of a silverlight 2009 game · anatomy of a silverlight game february 1 2009...

33
Anatomy of a Silverlight Game February 1 2009 Typical online games have a start screen, levels, storyline, transitions, high scores, chat, and other features that can take significant amount of time to develop. There are challenges when building online games, such as full screen support and scaling; speed optimization; animations; realtime calculations. Learn how to develop compelling Silverlight games faster, by using a base framework for the common game elements outlined above. Easily Create Engaging Online Games

Upload: others

Post on 17-Sep-2019

2 views

Category:

Documents


0 download

TRANSCRIPT

 

   

Anatomy of a Silverlight Game 

February 1 

2009 Typical online games have a start screen, levels, storyline, transitions, highscores, chat, and other features that can take significant amount of time to develop. There are challenges when building online games, such as full screen support and scaling; speed optimization; animations; real‐time calculations. Learn how to develop compelling Silverlight games faster, by using a base framework for the common game elements outlined above.  

Easily Create Engaging Online Games  

2  

Contents About the Author................................................................................................................................................. 4 

About this Document .......................................................................................................................................... 4 

Goal .................................................................................................................................................................. 4 

Scope ................................................................................................................................................................ 4 

Target Audience .............................................................................................................................................. 5 

Getting Started ................................................................................................................................................ 5 

1.  Introduction: Why Care About the “Details”? .......................................................................................... 5 

2.  Components of an Online Game ................................................................................................................ 6 

3.  Screen Layout .............................................................................................................................................. 6 

Visual Layers that Make Up Your Game ........................................................................................................ 6 

Game Interface Layer.................................................................................................................................. 7 

In‐game Controls Layer ............................................................................................................................... 7 

Sounds Layer................................................................................................................................................ 8 

Start Screen Layer ....................................................................................................................................... 8 

Main Screen Popup Controls Layer ............................................................................................................ 9 

4.  Silverlight Game Internals ........................................................................................................................ 10 

The Game Loop.............................................................................................................................................. 10 

Some Classes That You’ll Likely Use in Every Game.................................................................................... 13 

The Game Class ......................................................................................................................................... 13 

Defaults Class ............................................................................................................................................ 14 

Globals Class .............................................................................................................................................. 15 

Enumeration Classes ................................................................................................................................. 16 

Sounds Class .............................................................................................................................................. 17 

Other Classes ............................................................................................................................................. 18 

Keyboard and Mouse .................................................................................................................................... 18 

Full Screen Support ....................................................................................................................................... 19 

Returning from Full Screen to Embedded Mode .................................................................................... 20 

Aspect Ratio ............................................................................................................................................... 20 

More Info ................................................................................................................................................... 22 

Transitions ..................................................................................................................................................... 22 

Sound and Music ........................................................................................................................................... 23 

3  

5.  Networking ................................................................................................................................................ 24 

Score ............................................................................................................................................................... 25 

Chat and Multiplayer .................................................................................................................................... 28 

Network Speed Optimizations...................................................................................................................... 28 

6.  Host Integration ........................................................................................................................................ 30 

7.  Cheat Protection ....................................................................................................................................... 32 

8.  Tips and Tricks ........................................................................................................................................... 32 

9.  Summary .................................................................................................................................................... 33 

 

   

4  

About the Author Nikola Mihaylov is a Software Design Engineer in Test at Microsoft, working on the WPF/Silverlight tools for Visual Studio. Nikola’s first Silverlight game topped the http://silverlight.net charts for 2 weeks after its v1.00 release in 2008. Contact at [email protected] or [email protected].  

About this Document 

Goal This document will help you get started and quickly develop compelling Silverlight games. 

It will provide you with a base framework for many repeatable game elements in order to save you significant development time, reduce coding mistakes, and increase traffic and desirability of your game. 

As a running example, I will use the latest (at the time of this writing) release of a game called Shock: http://nokola.com/shock  

You can download the first release of Shock’s source from here: http://nokola.com/sources/ShockSource.zip.  

The source code is free for personal use only. 

Scope In the next few chapters, we’ll discuss the following: 

Chapters 1 and 2: What makes up a Silverlight game? 

Chapter 3 – Screen Layout: Laying out game elements to allow easy update to the UI, reduce XAML and code‐behind clutter and have fewer bugs. 

Chapter 4 – Game Internals: Discusses the typical classes that make up a game, how to make use of mouse and keyboard in code, how to support full screen, add transitions, and produce sound. 

Chapter 5 – Networking: In this chapter you will learn how to setup a network connection to retrieve highscore list from a server, and some techniques to make your game load fast and look smooth. There is a short Chat and Multiplayer section that I intend to expand in the next release of this writing. 

Chapter 6 – Host Integration discusses one important piece of an online game – interaction with the host browser. 

Chapter 7 – Tips and Tricks describes some methods that you can use to increase traffic to your game, enhance game play, or just make your game look better. 

Not in scope of this document: 

• Game play and game idea 

5  

• Authoring graphics content 

• Authoring sound content 

Target Audience I assume that you have good understanding of XAML, Silverlight and basic understanding of Web Services. You probably developed a Silverlight application in the past and are ready to take on bigger challenges. Or you are a game enthusiast who wants to develop a good online game.  

Getting Started If you accidentally bumped into this document, or you’re just beginning to work with Silverlight, I recommend going to http://silverlight.net/GetStarted. The resources there will help you get into the Silverlight development world quickly. 

As you are reading through the document, check out this game: http://www.nokola.com/shock. I used screenshots from Shock to illustrate various methods for Silverlight game development.  

You will also see references like this: 

 

These references point into the first release of Shock’s source code, which is free for personal use and available here: http://www.nokola.com/sources/ShockSource.zip.  

I intentionally removed a lot of the game’s functionality from the published source code in order to make it easier to read and understand. The live game on http://www.nokola.com/shock contains more functionality than the published source code. 

1. Introduction: Why Care About the “Details”? When I first started making games in high school I was mostly paying attention to the “game engine”, and completely overlooked other capabilities that I perceived as fit‐and‐finish back then.  

I found out later that many hobbyist or even some advanced game developers are also not paying enough attention to “small” details – such as a good high score table, chat capabilities and other. The end result was: they never finished their project, or were lacking some taken‐for‐granted feature (e.g. scoring) in their game. They were making the same mistake as I did. 

Having the right “fit‐and‐finish details”, can increase your web traffic tenfold. This document will help you easily implement the right capabilities to make your good game a great one! 

As you read through we’ll be building a library of different components that you can reuse later. 

Here are few examples of why should we care: 

Source Code: File.xaml.cs, function SomeFunction() 

6  

• Advanced high‐score table: increases the time people play a game and they return more often. I increased the traffic to Shock more than twice using small tweaks in the high‐score table. 

• Terms of use, credits, login and other repetitive components are better done once and forgotten. It’s best to not reinvent them every time. 

• Features perceived as “small” can take significant time to develop right. 

2. Components of an Online Game A compelling online game has some of these features: 

• Startup screen 

• Instructions screens 

• Levels and transitions between levels 

• Storyline 

• Sign Up/Login 

• Terms of use • Credits 

• Secret codes/Development (Staging) UI 

• Send to Friend 

• Embed link 

• Feedback/Rating link 

• Chat 

• Community 

This is a not all‐inclusive list of items to think about when designing your game. You probably don’t need all and should think and decide which components are most appropriate for your game. 

3. Screen Layout There are many controls for various purposes in a game. Dealing with hundreds of different controls can get messy without a proper layout. 

Having a good idea of what lays out where, will reduce complexity of your main Page.xaml file, and make your project easier to work on.  

Visual Layers that Make Up Your Game Your game’s Page.xaml will typically have these layers at minimum: 

7  

 

Game Interface Layer The game interface layer is what the player sees as they are playing: 

• Score 

• Lives • Elements that make up your game – e.g. a space ship for space battle game 

• Health, energy, rank, time, and other indicators 

 

Figure 1 – Shock’s Game Interface Layer 

In­game Controls Layer All UI that will appear on top of the game interface goes here.  

For example: Item Shop, Level selection controls, or fly‐in high scores. The “Choose Your Path” control (not included in the source code) below is defined in the in‐game controls layer: 

Game Interface 

In‐game controls (High score, Skill selection, Transitions)

Sounds 

Start Screen (Main) interface

Main screen popup controls (high‐score, instructions)

8  

 

Figure 2 – Shock’s In‐game Controls 

Sounds Layer The sounds layer can pretty much go anywhere. It contains a collection of MediaElement‐s to play various effects and music throughout the game. The sounds layer is not visible on the screen. 

Start Screen Layer The start screen is what the user sees after going to your game’s web page. 

Typically, you would put information that is good‐to‐know before the game starts here: 

• Instructions 

• Play/Restart buttons 

• Terms of Service • Login info 

• Chat Lobby 

As with any other UI, keep exactly the information that is usable on this screen, nothing more nothing less. 

Here’s an example start screen: 

9  

 

Figure 3 ‐ Shock's Start Screen 

Main Screen Popup Controls Layer The main screen contains various controls, such as login/logout windows, instructions, boxes to enter names, codes. All of the elements that are visible on the start screen, but are invisible inside the game, should go here. During game play, this screen will have its Visibility set to Collapsed, to increase the performance of your game. Panels with Visibility=”Collapsed” will be skipped by the Silverlight rendering pipeline. 

10  

 

Figure 4 – the Instructions control is part of the Main Screen Popup Controls Layer 

4. Silverlight Game Internals 

The Game Loop The “game loop” is a function or set of functions that are called periodically (for example, 100 times per second or when a key is pressed), and does some computations and screen updates. 

A typical game loop in pseudo code looks like this: 

11  

 

The above loop does not have keyboard and mouse handling. Why? Since Silverlight fires events on key presses and mouse movements, part of the “game loop” executes asynchronously in separate functions. For example: 

 

Depending on the type of game you’re building there are different choices for a game loop. The most important thing to consider is:  

Are you making a real‐time, fast‐paced game (e.g. space shooter), or a turn‐by‐turn one (e.g. Chess)? 

For turn‐by‐turn games, you don’t need to get very creative with the game loop – pretty much anything works. I recommend using a timer in this case – see DispatcherTimer class in MSDN online.  

For fast‐paced, action‐packed games, you need more than a simple timer.   

Event handling, Source Code: Page.xaml.cs, function root_MouseMove()  

OnKeyUpPressed() {

1. Calculate new game state and update animations since the user pressed the up arrow

}

OnKeyDownPressed() {

1. Calculate new game state and update animations since the user pressed the down arrow

}

...and so on

Main game loop, Source Code: Page.xaml.cs, function OnTimer() 

while not Gameover {

1. Calculate stuff (e.g. bullet collisions) or “think” (e.g. Chess)

2. Update game state (check for game over, winning condition, and other)

3. Update screen

}

12  

The reason why you can’t just get everything working with a simple timer is because you can get at most, at the time of this writing, 15 milliseconds (msec) resolution from the Silverlight DispatcherTimer class. Someone may think that’s enough: 1000 msec/15 msec is about 66 frames per second (FPS), and regular TV broadcast is about 30 FPS. What is the problem? 

The fundamental issue is that although 30 FPS may be enough for the screen to update smoothly, it may not be enough for all internal calculations to work properly. For example, if your game fires a super‐fast projectile at a speed of 1 pixels/msec, the projective will pass about 15 pixels on the screen for 15 milliseconds. For 15 pixels, the projectile can easily miss the target.  

In my initial implementation of the game loop in Shock the fastest balls sometimes went straight through bricks instead of correctly bouncing off them. How should we fix it? 

There are several approaches to mitigate the problem. For example, you could start a storyboard instead of timer or a separate thread for computations only – which yield higher resolution than DispatcherTimer. 

I decided on this approach: simulate a higher resolution timer in the lower‐resolution timer function. The default DispatcherTimer can still be used, and the same game loop suitable for both turn‐by‐turn and fast‐paced games.  

Here is the updated game loop using the simulated high‐resolution timer: 

 

In the new game loop, the calculations are done every 1 msec (=1000 times per second) instead of every X msecs where X is the resolution of DispatcherTimer (typically X = 15 msec). This ensures that a fast ball will hit the brick and a projectile will not pass through the target. 

How did I choose 1 msec? Depending on the game, you should choose the largest number that works correctly in order to minimize the amount of computations in your game loop. For example, if your 

Updated game loop, Source Code: Page.xaml.cs, function OnTimer() 

while not Gameover {

1. TimeDelta = <calculate time since we last executed the main game loop function>

2. For I from 1 to TimeDelta STEP 1 msec: a. Calculate stuff with 1 msec step(e.g. bullet

collisions) or “think” (e.g. Chess) b. Update game state (check for game over, winning

condition, and other)

3. Update screen

}

13  

fastest projectile travels with speed 2 pixel/msec and your smallest target size is approximately 10x10 pixels, your step should be 10/2 = 5msec, because that step is good enough to ensure that there will be calculation every 10 pixels at most and the projectile will not miss the target. 

Depending on the game, you may want to avoid the artificial high‐resolution timer altogether and do some other checks instead – e.g. in the projectile case, check if the line drawn between the position of the projectile before and after the calculation crosses the target. 

Try to optimize your game loop for speed, since as your game gets more and more complex you may need every free bit of processing power of your target users’ PC. 

Some Classes That You’ll Likely Use in Every Game 

The Game Class This class stores information about the current game such as state (GameOver, Paused, Playing), current level, lives left, where things are on the screen, such as the player position. 

The Game class has functions to start a level, go to the next level, update score, and other functions related to the game being played. 

14  

 

Defaults Class Your project will use a lot of pre‐defined values. Some can be related to the gameplay itself, such as the number of lives a player starts with. Others are specifying the environment in which the game executes – such as default screen resolution and zoom. I encourage you to group and put all your default values at this single class: it is a big time saver when you start tweaking the game and/or other values later. 

Typical Game class, Source Code: Game.cs 

/// <summary> /// Information about a game /// </summary> class Game { /// The current level public Level Level; /// All balls in the current level public List<Ball> Balls = new List<Ball>(5); /// All currently visible bonuses on screen public List<Bonus> Bonuses = new List<Bonus>(); /// Paddle information: state, location, size, etc public Paddle Paddle; /// Score of the current player public int Score; /// Life of the current player public int Life; public void StartNewLevel(Level newLevel); /// Sets the game in a game over state public void GameOver(); /// Restarts the current level public void RestartLevel(); // ... and so on }

15  

 

 

Globals Class You will also use quite a lot of global variables within your project. Putting all of these at a single location makes them easy to find and easy to change. The Globals class contains information and the current state of various objects that change during gameplay – such as Silverlight TextBoxes, Panels, and the current Zoom level (which is initialized to Defaults.Zoom initially). 

Sample pre‐defined values, Source Code: Defaults.cs 

/// <summary> /// Default constants /// </summary> static class Defaults { /// Amount of paddles that a player has at the start of each game public const int InitialPaddleCount = 2; /// Frequency for updating the game timer public const int TimerUpdateFreqMsec = 10; /// Default zoom private const double Zoom = 1.0; ... /// Default ball X position on screen public const double BallX = XMax / 2; /// Default ball Y position on screen public const double BallY = (YMax * 3) / 5; /// Default ball speed in pixels/msec at zoom 1.0 public const double BallSpeed = 0.4; ... }

16  

 

 

Enumeration Classes I find it convenient to put most enumerations at one place to avoid clicking through multiple files. Since enums are relatively short, it seems like a good approach. Enumerations include things like: all the different bonuses you have in the game; game state; different player states (for a shooter game, the ship’s states may be: WithSmallGun, WithBigGun, WithHugeGun, WithoutGun). Below are some of Shock’s enumerations. Take a special note of the GameState enumeration, since your game is likely to use a similar one. 

Example of global objects, Source Code: Globals.cs 

/// <summary> /// Stores state of objects that need access from various classes /// </summary> static class Globals { ... /// Dictionary used to create and store keys for storyboards and other resources private static Dictionary<object, string> _keyMapping = new Dictionary<object, string>(); /// returns a free key that we can use for adding a resource to a dictionary private static string GetFreeKey(); /// true if the left mouse button is down, false otherwise public static bool IsLeftMouseButtonDown = false; /// Current zoom level public static double Zoom; /// The current x resolution public static double XResolution; /// The current y resolution /// </summary> public static double YResolution; ... /// Panel that contains all bricks public static Panel PanelBricks; /// The high score control public static Highscore HighscoreControl; ... }

17  

 

 

Sounds Class The Sounds contains functions to play the various sound effects in the game such as Fire(), Blast(), Win(), Lose(). In Shock I did not implement all sounds. Nevertheless the functions are there! If I decide to add sounds later it will just require a small change to the Sounds class! 

 Typical class to process sound effects and music, Source Code: Sounds.cs 

/// The game sound system public static class Sounds { /// Sound of bolt firing public static void Fire(); /// Sound when balls turn to plasma balls public static void PlasmaBall(); /// Sound when a bonus is received public static void ReceiveBonus();

...

}

Some enumerations found in games, Source Code: Enums.cs 

/// Brick appearance, order is important - see Defaults.BrickImageNames* enum BrickAppearance { /// Metal brick Hard, /// Brick appearance 1 Color1, /// Brick appearance 2 Color2, ... } enum BonusContents {...} ... enum GameState { NotStarted, Playing, Paused, GameOver } ...

18  

 

Other Classes I encourage you to structure (but not over structure) your classes based on the different elements in your game. For example, a space shooter will likely have a Ship class. Chess or other two‐player game will likely have Player class and so on. In Shock I consider a Player class to be overkill, because there is only one player.  

Another class you may want to have is the Effects class: having one will reduce some clutter in the Game class, in case your game has more complex effects with several parameters.  

Here are the other game‐specific classes in Shock: 

 

 

Keyboard and Mouse Keyboard and mouse are relatively easy to setup in Silverlight, but sometimes can be tricky. 

To make it easier, we’ll add a canvas that is invisible, spans the whole screen and has a Transparent background. The Transparent background enables the Canvas to catch clicks, instead of passing them through.  

 

The Canvas is placed directly on top of our game interface: 

The Canvas that receives all clicks and key events, Source Code: Page.xaml 

<Canvas x:Name="canvasTopmost" Background="Transparent" MouseLeftButtonDown="canvasTopmost_MouseLeftButtonDown" MouseLeftButtonUp="canvasTopmost_MouseLeftButtonUp" /> 

Sample game‐specific classes, Source Code: Game/*.cs 

/// Represents a ball on the screen class Ball /// Information about a Bonus /// Bonus is an enhancement dropped from a brick class Bonus /// Information about a single brick class Brick /// Information about a level class Level /// Information about the paddle class Paddle 

19  

 

 

Here’s a quick cheat sheet on how to setup keyboard and mouse events to work correctly: 

Event  Where to catch it?MouseMove  Root UserControl MouseMove="root_MouseMove"Mouse buttons  canvasTopmostKeyboard  canvasTopmost, be careful about focus

Note in fullscreen only a subset of the keyboard works (arrow keys and few other: see Full Screen Support below) 

 

Full Screen Support  I think of full screen browser apps as the next great thing on the web. It’s amazing to see how the Internet evolved over the years to the point where it’s easy to write full screen games running in a secure browser environment and distribute them to a wide range of users. 

The “web” part of “full screen web game” still sets some boundaries for what you can do, mostly for security reasons. For example, you wouldn’t want a program to trick the user that he’s seeing a login box that looks similar to a dialog from his OS and typing their password that is actually intercepted by a web page for malicious purposes. 

Thus, Silverlight sets some intentional limits to what you can do in full screen: 

• Keyboard: in full screen mode only arrow keys, Enter, space and few other keys are supported 

• You can go full‐screen only in response to a user‐initiated action.  This means that you can switch to full screen mode from code, only in a user‐input event handler (e.g. in Button.Click). For example, if you try to go to full screen mode in the Startup or Loaded event handlers, the setting will be ignored. 

Game Interface 

canvasTopmost goes here 

In‐game controls (High score, Skill selection, Transitions)

Sounds 

Start Screen (Main) interface

Main screen popup controls (high‐score, instructions)

20  

Above said, it’s easy to switch to full screen in Silverlight: 

 

Returning from Full Screen to Embedded Mode  The user can also decide to go out of full screen and back to embedded mode at any time, by either pressing Esc or switching to another application. You have to intercept when the application goes back to embedded mode and present the user with an appropriate set of actions from there. For example, you may pause the game if the user presses Escape to go to embedded mode. 

 

Aspect Ratio Knowing the resolution and aspect ratio (4:3, 16:9, etc) of the target user’s screen is important in order to make your game appear correctly in full screen mode.  In Shock, the game automatically zooms to fit the screen and at the same time preserves the aspect ratio of the images. As a result, when played on 

Intercepting and processing full screen changes, Source Code: Page.cs 

public Page() { InitializeComponent(); Application.Current.Host.Content.FullScreenChanged += new EventHandler(Content_FullScreenChanged);

}

void Content_FullScreenChanged(object sender, EventArgs e) { if (Application.Current.Host.Content.IsFullScreen) { if (game.State == GameState.Paused) game.State = GameState.Playing; if (game.State == GameState.NotStarted) ctlHighscoreSlide.ShowHighscoreSlide(); // show score UpdateOnFullScreen(); // update view and zoom } else { if (game.State == GameState.Playing) game.State = GameState.Paused; ...more code to update view here...

} }

Switching to full screen mode, Source Code: Page.cs 

private void btnPlay_Click() { Application.Current.Host.Content.IsFullScreen = true; ... } 

21  

16:9 screen, there is less space between the paddle and the bricks and the game is harder to play. This is a conscious decision I made when developing Shock. Depending on your game, there are different choices on how to handle different aspect ratios. You always want to ensure that your game looks OK under any (or most) aspect ratios.  

Notice how the screen looks good in the first two images below. In the third one the view is stretched, because the game does not account for the 16:9 ratio.  

 

Figure 5 ‐ Shock at 4:3 Ratio, Correct 

 

 

Figure 6 ‐ Shock at 16:9 Ratio, Correct 

 

 

Figure 7 ‐ Shock at 16:9 Ratio, Incorrect 

The code below detects the screen resolution and aspect ratio (assuming pixels are square): 

22  

 

More Info For more detailed information about full screen in Silverlight check this page:  

http://msdn.microsoft.com/en‐us/library/cc189023(VS.95).aspx 

Transitions Transitions are something to think about when designing and implementing your game. They are small animations that usually play at the end of a level, game over, or other change of game state.  

Example transitions you may have are: “ship destroyed”, “level complete”, and so on.  

A game without transitions can be still good. At the same time having them enhances the player’s experience. Shock’s source code currently does not include transitions. 

Most transitions happen on the game interface layer (see Chapter 3: Screen Layout). Also, the game interface is hidden whenever the start screen is visible. For these reasons usually you don’t have to take special steps to stop the animations that make up your transition: just start them and let them play until they finish “naturally”.  

It is unlikely that you’ll need to invent new game states other than the few basic ones (GameOver, NotStarted, etc – see Enums in Chapter 4: Silverlight Game Internals) in order to support transitions. 

Detecting screen size and aspect ratio, Source Code: Page.cs 

void Content_FullScreenChanged(object sender, EventArgs e) { if (Application.Current.Host.Content.IsFullScreen) { ... UpdateOnFullScreen(); // update view and zoom } else ...more code to update here... } /// Detect screen size, aspect ratio, calculate zoom, update game and view private void UpdateOnFullScreen() { // size to screen root.Width = double.NaN; root.Height = double.NaN; // update zoom and current resolution Globals.XResolution = Application.Current.Host.Content.ActualWidth; Globals.YResolution = Application.Current.Host.Content.ActualHeight; Globals.Zoom = Globals.XResolution / ((double)Defaults.XMax); ... more code to update game state here ...

}

23  

Sound and Music I think it’s a good idea is to think about sound effects and music from the start and add those once the game is close to completion. 

Here’s how to do sound and music in a Silverlight game: 

1. Create a Sound class that will play your sound effects and music (see Chapter 4: Silverlight Game Internals, Sound class) 

2. Add a set of media elements for each sound effect in your Sound layer (see Chapter  3: Screen Layout for the different layers on screen) You will need several media elements per effect, because you may want to play more than one of the same effect simultaneously.  

The below code shows how to add support for the Explosion (Fire) sound: 

 

Then I initialize an array of sounds MediaFire:  

 

Sound effects, XAML, Source Code: Page.xaml 

<Canvas x:Name="panelSounds" Visibility="Collapsed"> <MediaElement x:Name="mediaFire1" AutoPlay="False" Source="Sounds/Brick_explosion.mp3" /> <MediaElement x:Name="mediaFire2" AutoPlay="False" Source="Sounds/Brick_explosion.mp3" /> <MediaElement x:Name="mediaFire3" AutoPlay="False" Source="Sounds/Brick_explosion.mp3" /> <MediaElement x:Name="mediaFire4" AutoPlay="False" Source="Sounds/Brick_explosion.mp3" /> <MediaElement x:Name="mediaFire5" AutoPlay="False" Source="Sounds/Brick_explosion.mp3" /> </Canvas>  

24  

 

And finally use the array of media elements in the Sounds class: 

 

For music you can either use the above approach or embed music on your page. See Chapter 6: Host Integration for example how to use embedded music. 

5. Networking For communicating with a web server I chose using WCF services: once you set them up you will find them very easy to work with and extend.  

The setup part can be hard though: 

• I spend two weeks getting my web services to work for different hosting providers and various IIS settings. There are some very tricky areas, and it’s easy to miss some cases. For example, http://nokola.com and http://www.nokola.com are considered to be different web sites: you have to take special care to make your communication work reliably. 

• Testing the game on your local host is much different than running on a public web site. Usually your host provider will have some predefined IIS settings you may not be able to change easily. 

Sound effects, XAML, Source Code: Page.xaml 

/// The game sound system public static class Sounds { /// Sound of bolt firing public static void Fire() { int index = Globals.CurrentMediaFireIndex; Globals.CurrentMediaFireIndex = (Globals.CurrentMediaFireIndex + 1) % Globals.MediaFireCount; Globals.MediaFire[index].Stop(); Globals.MediaFire[index].Play(); } 

Sound effects initialization, Source Code: Page.xaml.cs 

public Page() { InitializeComponent(); ... // init sounds Globals.CurrentMediaFireIndex = 0; Globals.MediaFireCount = 5; Globals.MediaFire = new MediaElement[] {mediaFire1, mediaFire2, mediaFire3, mediaFire4, mediaFire5}; ... }

25  

• You will likely want to debug your web services on your local box (unless you are a software god, who writes bug‐free software from the first try). There are different settings for your IIS server that you have to take into account to enable debugging and WCF service support. 

For the above reasons, I encourage you to take a quick break from reading this document and: 

1. Check out all the links below. They summarize all the issues I encountered until I got my network code up and running and in the state it is today. 

2. Create a simple project that transfers a string from a web server to a Silverlight application. It will help you get a good foundation to build upon 

Information on setting up network communication in Silverlight: 

• Basic WCF Service sample and source code: http://www.nokola.com/SampleService/ServiceClientAppTestPage.aspx   

• Accessing Web Services in Silverlight on MSDN http://msdn.microsoft.com/en‐us/library/cc296254(VS.95).aspx  

• Configuring IIS 7 to work with WCF Web Services for Silverlight 2 http://blogs.msdn.com/nikola/archive/2008/03/06/configuring‐iis‐7‐to‐work‐with‐wcf‐web‐services‐for‐silverlight‐2‐beta‐1‐scenario.aspx   

• Visual Studio 2008 Walkthrough: Creating, Hosting and Using WCF Services with Silverlight 2 http://blogs.msdn.com/nikola/archive/2008/03/12/visual‐studio‐2008‐walkthrough‐creating‐hosting‐and‐using‐wcf‐services‐with‐silverlight‐2‐beta‐1.aspx   

• Calling Web Services and Accessing UI from Timer Event in Silverlight http://blogs.msdn.com/nikola/archive/2008/03/13/calling‐web‐services‐and‐accessing‐ui‐from‐timer‐event‐in‐silverlight.aspx   

• Silverlight: How to Make Your WCF Web Service Work for All Users http://blogs.msdn.com/nikola/archive/tags/Web+Service/default.aspx  

Shock’s source code does not have all the tweaks above applied. It works only in limited network scenarios. The project on http://www.nokola.com/SampleService/ServiceClientAppTestPage.aspx and the docs above have enough information to get a service up and running in many web and local host debugging environments. 

Please spend the time to read about web services! It will make your life much easier! 

Score I assume that you already have a basic project that transfers a string from Silverlight to a server and back. Once you have that, the hard part is done, now we can party! 

26  

As long as it works, you don’t have to be very creative when implementing the high‐score back end data storage. I use a plain text file to store Shock’s score and it looks like this: 

 

The file contains the name (alias) and score of each player, and is capped to 10000 players max. 

It works well so far. In the latest version of Shock I also store date and reflexes rating for each player in order to create the daily, weekly and monthly stats. These get re‐created from scratch every time when requested: the web service loads the whole file, parses it and extracts the data. At the beginning I thought this is bad (slow) and resource‐consuming approach, but it works fine even today and there is no need of database yet. 

The high score implementation on the client side is using a Silverlight UserControl. It contains all code to connect to the web service, display itself (using a fade‐in animation) and signal events back to the main page (such as when the “New Game” button is clicked on the highscore UI after game over). 

Scores stored in a text file on the server, Source Code: App_Data/highscore.txt 

monster 973553 monster 349174 Nokola! 45512 monster 38895 Milen Zafirov 28855 Dan 23676 ...

27  

 

The highscore control also shows UI to allow the player to enter their name if they make it on the top players list in the highscore table. 

In Shock, the high‐score table is also displayed briefly when a game starts. To make this experience smooth, I had to add a function to preload the high‐score and make them available before the start of the game: otherwise there would be a small delay (the time to connect to the server) and the score would be displayed some time after the player started playing. 

 

Since Silverlight access to WCF web services is always asynchronous, the control should be aware of what is currently going on. This is best tracked by assigning states to the control: 

Function to preload the score, Source Code: Highscore.xaml.cs 

public partial class Highscore : UserControl { ... public void PreloadScore() { SetPaneState(ScorePaneState.Preloading); InitEvents(); Globals.ShockService.GetHighscoreTableAsync(true); // get the high score } ... }

Highscore control, Source Code: Highscore.xaml.cs 

public partial class Highscore : UserControl { ... /// Start the highscore UI public void ShowHighscore(int currentScore) { Visibility = Visibility.Visible; SetPaneState(ScorePaneState.Loading); InitEvents(); _currScore = currentScore; Globals.ShockService.GetHighscoreTableAsync(); // get the high score and determine which UI to show to the user } ... private void btnStartNewGame_Click(object sender, RoutedEventArgs e) { if (HighscoreEntryAndDisplayCompleted != null) { HighscoreEntryAndDisplayCompleted(false); } } ... }

28  

 

Chat and Multiplayer Here is a very brief section on chat and multiplayer with the intention to add more detailed information in the next release of this document, and the next game coming up. 

By now you should be well‐familiar with network communication in Silverlight. Implementing chat will not be a hard task depending on how much you want the chat to scale. Is it going to be between only the two players playing each game or all players online? 

To implement chat and multiplayer for a non‐realtime game (Chess) the server has to store information about the current players online, and redirect messages from one player to the other. 

For a real‐time game (e.g. collaborative space shooter, or a game where players play against each other), communication can get more tricky. All users playing simultaneously must have their games “synchronized”: if Josh (player 1) sees the ship firing a missile at a given time, Sherri (player 2) should see the same ship, firing the same missile and the same time. You have to take the network lag between the server and the players’ machines into account.  

I will leave the real‐time multiplayer discussion here, as I want to create and publish an example first, before writing about it. 

Network Speed Optimizations Maybe you’re expecting your users to have a fast connection to the Internet. Even though you can still make very easy optimizations that can significantly enhance the game experience. They can also save you money from reduced traffic, if you are using a hosting provider that charges per‐megabyte or caps your transfer per month. 

States of the highscore control, Source Code: Highscore.xaml.cs 

enum ScorePaneState { /// Loading highscore to show after game over Loading, /// Loading highscore to show at level start LoadingForSlide, /// Preloading highscore to use later Preloading, /// Player is entering name EnterName, /// Showing scores that are loaded ShowScore }

29  

The first obvious optimization is delay‐loading of music and videos. Don’t include big music and videos in your XAP file. Instead, add them on the web and point to them from within your MediaElements. 

The second optimization is delay‐loading of images: these can get quite big sometimes and it’s a good idea to load them only when needed. 

There’s one problem with delay‐loading of images: since you load them at display time, your game will look “choppy” – the pictures load and will appear after the text and other elements are displayed into view. To mitigate the issue you can silently preload the images somewhere after the main XAP is loaded. Or, if you don’t want to do that and truly save network traffic, you can use the SmoothImage control from the MoreControls project in Shock’s source.  

The SmoothImage control will make images fade into view as they are loaded, and if you change its Source property, it will keep the old image on screen until the new image is ready to be displayed. The end result is smooth transition between images instead of having images suddenly appear or disappear on screen. I use this control for changing the background image in the latest Shock version. 

Some things are not worth optimizing: if you have a lot of small images that get displayed on the first screen of your game, it’s better to leave them in your main XAP file. Optimizing those may cost you too much effort without much benefit in return (the player will have to wait for them anyway).  

When delay loading, consider the possibility of not being able to access the delay loaded resource. For example, if the connection to the Internet suddenly breaks, or the resource download fails (which can happen if you try too many simultaneous connections to a web site), your game should still operate normally. In Shock I have a small, low‐quality version of my background image for this purpose. The low quality background is used as a fallback and until the higher quality background loads 

The below XAML shows how to delay load an image and have a low‐quality fallback resource for cases where the network connection drops: 

 

Last thoughts on network bandwidth optimization: Silverlight allows you to dynamically load assemblies. You can use this to cache parts of your game, including compiled sources if your game file is big. The example at http://nokola.com/TryCSharp and short tutorial at http://www.nokola.com/trycsharp/HowToBuild.aspx show how to compile C# code and dynamically download and execute Silverlight assemblies at runtime.  

Delay loading an image with low‐quality fallback, XAML 

<Image x:Name="imgBackFallback" Source="Images/shockLord_lowquality.jpg" Stretch="UniformToFill" /> <more:SmoothImage x:Name="imgBack" xmlns:more="clr-namespace:MoreControls;assembly=MoreControls" Source="http://www.nokola.com/clientbin/Shock/Images/Backgrounds/shockLord.jpg" /> 

30  

6. Host Integration Silverlight applications can access information from the host browser they are running in. You can manipulate the underlying HTML from your game to make it “aware” of objects embedded in the page, such as music players, or comment fields. 

In Shock, I use a <div /> element named divMedia to embed objects (e.g. to play music) in the underlying HTML. 

Here’s how the HTML may look like: 

 

To update the HTML correctly, the Silverlight game will check first if it’s running in a localhost or web environment: 

HTML containing a div element to be updated from Silverlight, Source Code: http://www.nokola.com/shock, select Page | View Source from Internet Explorer 

<div id="divMedia"> <object width="300" height="290"> <param name="movie" value="http://media.imeem.com/pl/gNB9qDjVbC/aus=false/"></param> <param name="wmmode" value="transparent"></param> <embed src="http://media.imeem.com/pl/gNB9qDjVbC/aus=false/" type="application/x-shockwave-flash" width="300" height="290" wmode="transparent"></embed> </object> </div> 

31  

 

Once we have our HTML elements, we can just use their DOM properties to set the value from the txtMedia box into the divMedia element at runtime: 

 

 

Changing HTML at runtime from within Silverlight, Source Code: Page.xaml.cs 

private void EmbedMusicOnPage() { if ((_doc == null) || (!_mediaTextChanged)) { return; } string textToEmbed = _txtMedia.GetAttribute("value"); _divMedia.SetAttribute("innerHTML", textToEmbed); _mediaTextChanged = false; } 

Checking if running from the web or at localhost, Source Code: Page.xaml.cs 

/// <summary> /// The html document containing our text data and such /// null if the sl control is not hosted in the correct html /// </summary> private HtmlDocument _doc; private HtmlElement _txtMedia; private HtmlElement _divMedia; public Page() { InitializeComponent(); ... _doc = HtmlPage.Document; if (_doc.DocumentUri.AbsoluteUri.EndsWith("/TestPage.html")) { // if in test mode we don't have the ID tags for music in the HTML, // so we won't be playing it _doc = null; } else {

// get the elements we want to update from the HTML _txtMedia = _doc.GetElementById("txtMedia"); _divMedia = _doc.GetElementById("divMedia"); _txtMedia.AttachEvent("onchange", new EventHandler<HtmlEventArgs>(this.OnEmbeddedMediaTextChanged)); } 

32  

7. Cheat Protection Whenever you publish even the simplest online game with high‐score table there will be someone who will want to cheat their way to the top. On the second day Shock was released, there were 4 entries with amazingly high numbers in the score table. One of the aliases actually said “Hacked”. 

How can you protect yourself from such situations? 

Do you really have to spend a lot of time taking complex security measures in order to prevent malicious or just interested people to break your high‐score table? 

I think you don’t, for these reasons: 

• Basic WCF services (such as the one I use) publish all their APIs. Anyone who used VS and knows a little about programming can create a VS project and download your WCF service APIs and figure out what to do with the AddHighScoreEntry(name, score) function 

• You will have more time to make more features, or just time to spend on something else 

Back on the question: “how to protect from attacks”?  

Since cheating a game created by a single author or a team of few people is ultimately lame and even more, not challenging, I decided to make it obvious: 

Instead of naming my WCF functions AddHighScoreEntry(name, score), I just named it AddHighScoreEntryCheatingSimpleGameIsLame(name, score) to convey the message. It worked! The cheaters, who found the obvious way to add an entry to the highscore table, stopped bugging the game and I had more time to implement version 2! 

8. Tips and Tricks • Make the high score daily, weekly, monthly, or all of these. 

This small change alone doubled the monthly traffic to Shock. It also made possible for even beginner players to enter the high‐score table, increasing their satisfaction, and made it interesting for hardcore players too: they have to come back every month in order to keep themselves on the monthly high‐score list.  

• Measure different elements, not just score Same as above: after I added the Ranks and Reflexes rating to Shock (see latest online version), the traffic doubled again! Note that although Rank is linked directly to score, Reflexes isn’t – this is very important. Having truly different metrics makes the game much more interesting – now you can have high score and Turtle reflexes or low score and God reflexes. The different metric allows players to compete on more than one dimension and opens the door to dominate the high‐score list in more ways.  I also made it intentionally very hard to reach God Reflexes – adding some challenge for the long‐term players who are on top of the score lists. 

33  

 • Use Avatars 

People like associating themselves with “something”. Give them the possibility to leave their mark, feel happy, and they will come back to play again. The ability to express oneself is very important: this is exactly what avatars enable.  

• Cut, cut, and cut Do not be afraid to cut features. A typical mistake that even advanced game developers make is to add and add features to their game, and never complete it. If something seems like a great idea, but it doesn’t quite fit and you have other, more important things to implement, cut it! Once you have completed a v1 of your game, it is much easier to re‐evaluate and decide what to add. In Shock I cut about 90% of all the initial features that I wanted to do, and it turns out that I didn’t need most of them anyway after looking at what to do post v1. 

9. Summary In short time, we explored the following topics: 

• What makes up a Silverlight game 

• Screen layout  

• Common game classes • Sound and music 

• Mouse and keyboard 

• Full screen support 

• Networking • Host integration 

• Tips and tricks 

I hope you found this writing useful; and I would very much like to receive your feedback. It will help shape the next version of this document. 

Please contact me at [email protected] or [email protected] should you have any suggestions or questions! I appreciate hearing from you!  

Remember to regularly check http://www.nokola.com for the latest Silverlight samples and tutorials. 

Last but not least: I would love to play your game sometime! 

With Respect: Nikola