550 likes | 684 Views
009. Rob Miles. University of Hull rob@robmiles.com twitter.com/RobMiles robmiles.com. Building Games for Windows Phone 7. Agenda. Introducing the Windows Phone The platform and the development tools Writing games for Windows Phone Game Development Options Useful code samples
E N D
009 Rob Miles University of Hull rob@robmiles.com twitter.com/RobMiles robmiles.com Building Games for Windows Phone 7
Agenda • Introducing the Windows Phone • The platform and the development tools • Writing games for Windows Phone • Game Development Options • Useful code samples • What to do now • How to Get Started
Windows Phone 7 series • Windows Phone 7 series is a significant advance on previous generations • It provides a whole new way of interacting with mobile devices • You will find out more about this tomorrow at the keynote • For us it provides a compelling new platform to make great new applications and games
Development Options • You write in C# using managed code • You create your programs using Visual Studio 2010 • You can write Silverlight and XNA Apps • There is also an emulator you can use for testing
Windows Phone for Applications • The phone is a very capable application platform • It is very easy to create quick line of business applications • Silverlight provides some very useful features for game Developers
DatabindinginDamageCalc • We can use Silverlight data binding to connect the Price and Damage elements to the underlying code • You can also use this to manage the position and content of game objects
Databound Price Property set { if (priceChangeActive) return; priceChangeActive = true; latestPrice = value; Damage = twoDecimalPlaces((value / exchangeRate) * taxRate); if (PropertyChanged != null) { PropertyChanged(this, newPropertyChangedEventArgs("Damage")); } priceChangeActive = false; } • This event is fired when the user changes the price
Databound Price Property set { if (priceChangeActive) return; priceChangeActive = true; latestPrice = value; Damage = twoDecimalPlaces((value / exchangeRate) * taxRate); if (PropertyChanged != null) { PropertyChanged(this, newPropertyChangedEventArgs("Damage")); } priceChangeActive = false; } • It calculates the new value of the Damage property
Databound Price Property set { if (priceChangeActive) return; priceChangeActive = true; latestPrice = value; Damage = twoDecimalPlaces((value / exchangeRate) * taxRate); if (PropertyChanged != null) { PropertyChanged(this, newPropertyChangedEventArgs("Damage")); } priceChangeActive = false; } • It fires a property changed event to update the Damage display
Databound Price Property set { if (priceChangeActive) return; priceChangeActive = true; latestPrice = value; Damage = twoDecimalPlaces((value / exchangeRate) * taxRate); if (PropertyChanged != null) { PropertyChanged(this, newPropertyChangedEventArgs("Damage")); } priceChangeActive = false; } • I use an interlock to stop updates from repeating
Damage Calc Extensions • It would be easy to make the program automatically update the exchange rates • It could also use location based services to determine the local tax rate
Writing Games in Silverlight • XNA is a great place to write games • But some kinds of games are a bit hard to write in XNA • Sometimes you end up writing your own user interface • Silverlight makes “form based” games really easy to create
Getting Game Events • An XNA game has Draw and Update methods which are called regularly by the game framework • Silverlight does not provide game events • You need to create your own game clock • The CompositionTarget.Rendering event can be used for this
Catching the Rendering Event • The Rendering event fires each time the form is rendered • This can be used as our game “tick” CompositionTarget.Rendering += newEventHandler(CompositionTarget_Rendering);
Creating an Update behaviour voidCompositionTarget_Rendering(object sender, EventArgs e) { gameTick(); } privateDateTimelastTick; privatevoidgameTick() { DateTime now = DateTime.Now; TimeSpaninterVal = now - lastTick; lastTick = now; Update(interVal); }
The Draw method • The Draw method implements my game state machine • It has a case for each game state
Updating Gameplay in Silverlight • Unlike an XNA game, the Update method will not be called at fixed intervals • Instead the game will need to use the TimeSpan value provided to the Update call to perform game timing
Using the timestamps private intcurrentWait = 0; privatebooltestUpdateTime(TimeSpantimeStamp, intupdateDelay) { currentWait += timeStamp.Milliseconds; if (currentWait < updateDelay) { returnfalse; } currentWait -= updateDelay; returntrue; } • The method returns true if the delay time has passed
Flashing the Buttons private intflashInterval = 800; ... if (testUpdateTime(interval, flashInterval)) { // Update randomly flashing buttons intoldLitButton = litButtonNo; while (oldLitButton == litButtonNo) { litButtonNo = attractRand.Next(gameButtons.Length); } } • This update code changes the lit button every 800 ms
Persisting State • Your games must automatically persist state information so that they resume where they left off • Windows Phone provides local storage to make this possible • Each application has its own area of isolated storage
Storing a High Score private void saveHighScore() { IsolatedStorageFilemyStorage = IsolatedStorageFile.GetUserStoreForApplication(); IsolatedStorageFileStreamoutputStream =myStorage.OpenFile("HiScore",FileMode.CreateNew); StreamWriter output = newStreamWriter(outputStream); output.WriteLine(highScore.ToString()); output.Close(); myStorage.Dispose(); } • Each application has its own storage area
Storing a High Score private void saveHighScore() { IsolatedStorageFilemyStorage = IsolatedStorageFile.GetUserStoreForApplication(); IsolatedStorageFileStreamoutputStream =myStorage.OpenFile("HiScore",FileMode.CreateNew); StreamWriter output = newStreamWriter(outputStream); output.WriteLine(highScore.ToString()); output.Close(); myStorage.Dispose(); } • The game can create files and store values in them
Loading a High Score IsolatedStorageFilemyStorage = IsolatedStorageFile.GetUserStoreForApplication(); IsolatedStorageFileStreaminputStream = myStorage.OpenFile("HiScore", FileMode.Open); StreamReader input = newStreamReader(inputStream); stringhighScoreText = input.ReadLine(); highScore = int.Parse(highScoreText); highscorTextBlock.Text = "Score: " + highScore.ToString(); input.Close(); myStorage.Dispose(); • The storage can be read when the game starts
Windows Phone Navigation • The user never stops a program: • The back button takes you “up” a level in an application or back to the previous application • The Start button takes you to the Start Screen • As far as our game is concerned, in either of these situations the program ends
Handling the Back Button • Your program can bind to the BackKeyPress event and respond appropriately • It can absorb the back key event if it is sensible to do this
Handling the Exit Event Application.Current.Exit += newEventHandler(Current_Exit); • You can also bind an event handler to the Exit event to detect when your program is being stopped • this doesn’t seem to work quite right in the present emulator though..
Moving into XNA • XNA games will run very well on Windows Phone • Support is provided for 2D and 3D games • Games can use multi-touch and the accelerometer
Accelerometer Input • Unlike the Zune HD, the accelerometer input for XNA games is presently via the Sensor library • However, it is easy to create an emulation of the AccellerometerState class for XNA games
An Accelerometer Server • Windows Phone programs can consume web services and read web pages • This is a very powerful feature • I connect the Windows Phone program to an XNA program that serves out X, Y and Z values read from the Gamepad
Reading a Web Page • The Update method requests a page from the Accelerometer server public void Update() { Uriuri = new Uri("http://127.0.0.1:8080/Accelerometer"); WebClient client = newWebClient(); client.DownloadStringCompleted += newDownloadStringCompletedEventHandler(client_DownloadCompleted); client.DownloadStringAsync(uri); }
Reading a Web Page • Get the response and build the acceleration data static void client_DownloadCompleted (object sender, DownloadStringCompletedEventArgs e) { if (e.Error == null) { string[] numbers = e.Result.Split(new char[] { ',' }); state.Acceleration.X = float.Parse(numbers[0]); state.Acceleration.Y = float.Parse(numbers[1]); state.Acceleration.Z = float.Parse(numbers[2]); } }
Working with the Accelerometer • There is no emulation support • Although you can fake it as shown above • There are also emulations that use the Nintendo Wii remote
Multi-Touch • XNA provides support for multi-touch input • Up to four touch events can be tracked at once • Each event is uniquely identified • You get touch down, up and moved events
Processing Touch Events • This gets a the current touch events TouchCollectiontouchState = TouchPanel.GetState(); foreach (TouchLocation touch intouchState) { PointtouchPoint = new Point((int)touch.Position.X, (int)touch.Position.Y); foreach (keyDetails key innoteKeys) { if (key.keyRectangle.Contains(touchPoint) && touch.State == TouchLocationState.Pressed) { key.keySound.Play(); break; } } }
Processing Touch Events • We then work through each event in turn TouchCollectiontouchState = TouchPanel.GetState(); foreach (TouchLocation touch intouchState) { PointtouchPoint = new Point((int)touch.Position.X, (int)touch.Position.Y); foreach (keyDetails key innoteKeys) { if (key.keyRectangle.Contains(touchPoint) && touch.State == TouchLocationState.Pressed) { key.keySound.Play(); break; } } }
Processing Touch Events • I use a keyDetails class which holds the key position as a Rectangle and the soundeffect to play when the key is pressed TouchCollectiontouchState = TouchPanel.GetState(); foreach (TouchLocation touch intouchState) { PointtouchPoint = new Point((int)touch.Position.X, (int)touch.Position.Y); foreach (keyDetails key innoteKeys) { if (key.keyRectangle.Contains(touchPoint) && touch.State == TouchLocationState.Pressed) { key.keySound.Play(); break; } } }
Working with Multi-Touch • If you want to emulate multi-touch you can get a multi-touch monitor • Windows 7 multi-touch is used directly the emulator • There are some multi-touch emulators that use multiple mice
XNA in 3D • XNA supports 3D • Windows phones contain hardware acceleration • There is shader support, but you can’t write your own shader code
XNA 4.0 Changes • The way that you specify Vertices has changed in XNA 4.0 • Do not be surprised if sample code for earlier versions of XNA fail to work • The new design is much easier to understand though • Samples are now available on the web
Measuring Performance • The Windows Phone update rate is set to 30Hz • This is sensible given the type of display in use • You can use a frame counter to measure the actual update rate
XNA Performance Counter public override void Update(GameTimegameTime) { elapsedTime += gameTime.ElapsedGameTime; if (elapsedTime > TimeSpan.FromSeconds(1)) { elapsedTime -= TimeSpan.FromSeconds(1); frameRate = frameCounter; frameCounter = 0; } } • This Update method clears the frame counter every second • The counter is increased each time Draw is called
Sliverlight Performance • It is easy to get a frame rate counter in Silverlight • Setting the above property in your program will display one Application.Current.Host.Settings.EnableFrameRateCounter= true;
Using the Zune HD • One way to get experience of Windows Phone XNA development is to get hold of a Zune HD • You can write XNA 3.1 games in 2D for this platform • It provides multi-touch and accelerometer support