580 likes | 700 Views
Windows Phone and XNA for Fun, Games, Profit and Physics. Rob Miles| Microsoft MVP | University of Hull www.robmiles.com Twitter: @robmiles. Agenda. Getting started with XNA Sorting out orientation Using the touch panel gesture support
E N D
Windows Phone and XNA for Fun, Games, Profit and Physics Rob Miles| Microsoft MVP | University of Hullwww.robmiles.com Twitter: @robmiles
Agenda • Getting started with XNA • Sorting out orientation • Using the touch panel gesture support • Adding a touch of Physics with the Farseer Physics Engine • Using the Windows Phone accelerometer • The Windows Phone Marketplace
Quick Overview of XNA • The XNA Framework provides everything you need to get started writing games: • Full Content Management (integrated into Visual Studio) • Support for 2D Sprite-based gameplay • Support for 3D games • Common behaviours across the Windows PC, Xbox 360 and Windows Phone • One game engine can run on all platforms • Well factored object model
How Games Work • Every game that has ever been written has these fundamental behaviours: • Initialise all the resources at the start • fetch all textures, models, scripts etc • Repeatedly run the game loop: • Update the game world • read the controllers, update the state and position of game elements • Draw the game world • render the game elements on the viewing device
Methods in an XNA game • The XNA Game class contains methods that will provide these behaviours • Initialise all the resources at the start • The Initialize and LoadContent methods • Repeatedly run the game loop: • Update the game world • The Update method • Draw the game world • The Draw method
Getting Started with XNA • When you create a new XNA game project you are provided with empty versions of the game methods • Creating an XNA game is a matter of filling in these methods to get the game behaviours that are required • We are going to start by getting some cheese moving around the display • Then we are going to start rolling it around to score points • This is the latest cheese game in a long running series: • Behold CHEESE ROLLER!
Windows Phone and Orientation • By default a Windows Phone XNA game assumes it is running in “landscape” mode with the screen on the left of the controls • I want to change this, because I want to send the cheese down the long axis of the phone when it is rolled • I can select orientation when the game starts
Orientation and display • // Tell XNA we can only support Portrait orientation • // Can support a range of orientations by ORing • // together orientation values • graphics.SupportedOrientations = DisplayOrientation.Portrait; • // Set up hardware scaling of the display area • graphics.PreferredBackBufferWidth = 480; • graphics.PreferredBackBufferHeight = 800;// Want a full screen display • graphics.IsFullScreen = true;
Orientation management • An XNA game can specify the orientations it can support • The game can bind a method to the event which is fired when the orientation changes • Games can animate the transition to the new orientation if they wish • When orientation changes the origin for the draw position is moved to the top left hand corner of the viewport • The frame of reference for accelerometer readings (of which more later) is always as for the phone held in portrait mode
Size and the Scaler • An XNA game can also request a specific size of back buffer for the display • The game will be given this resolution irrespective of the actual device • The Graphics Processor (GPU) performs this scaling automatically and interpolates to remove any jagged edges • This is a great way to get performance boost by rendering to a lower resolution than the screen itself • In a fast moving game the lower resolution is not noticeable
Creating a Game World • An XNA game uses a number of variables to represent the state of the game itself • The Update method will update their values • The Draw method will produce a display that reflects their value • In the case of Cheese Roller the game must manage the position and movement of the cheese on the screen • We use a Texture2D value and a Rectangle to hold the position and a Vector2 to give the direction of movement • We also have a Friction value to slow the velocity over time
Using Gestures • We are going to use the touch panel to allow the player to “flick” the cheese around • For the ultimate in control you can get direct access to touch events from the panel • Up to four events can be tracked at one time • Each event is uniquely identified throughout its lifetime • However, XNA games can also use built in gesture recognition • Register an interest in a particular gesture type and then get notification when one has been performed
Supported Gestures • The touch panel can detect a number of different gestures including • Tap • DoubleTap • Hold • HorizontalDrag, VerticalDrag and FreeDrag • Pinch • Flick • The Cheese Roller game is going to use the Flick gesture
Registering an interest in a gesture • The game must select those gestures that it wants to use • This can be done once at the start of the game • I do it in the XNA Initialise method • A game can also query the TouchPanel about the number of points it can track simultaneously • TouchPanel.EnabledGestures = GestureType.Flick;
Retrieving Gestures • The Flick gesture returns a Delta value which gives the speed of the flick • The divide factor of 100 is something I came up with by playtesting • The smaller the value, the more powerful the effect of the flick • while (TouchPanel.IsGestureAvailable) • { • GestureSample gesture = TouchPanel.ReadGesture(); • if (gesture.GestureType == GestureType.Flick) • cheeseSpeed = Vector2.Divide(gesture.Delta, 100); • }
Improving Cheese Roller • The obvious improvement to Cheese Roller is to add more cheese • If we do this the physics becomes more complicated • Our simple model can no longer cope with all the collisions • Fortunately there are a lot of engines out there that can help • One of these is the Farseer engine • It is a 2D physics engine that is very easy to use and works well on Windows Phone
The FarSeer Physics Engine • The FarSeer Physics Engine is a Codeplex based project you can download from here: http://farseerphysics.codeplex.com/ • Version 3.0 has just been released but there is not a version of this that is suitable for Windows Phone just yet • I have used Version 2.0 for my Windows Phone “Destruction Golf” game
Farseer Objects • Objects in the Farseer 2.n universe are made up of a Body and a Geometry • We create instances of these and add them to the Farseer simulator • When the XNA game updates we also update the simulator so that it moves the objects around • We create the simulator at the start of the program
The Simulator • When we create the simulator we also give it a vector that indicates the direction of gravity • A vector is a way of expressing a direction • We can create it by giving it x and y direction values • We can change this to make gravity work in any direction we like, or with any amount of strength, which might be fun //The physics simulator is always needed. // We supply a gravity of 250 units PhysicsSimulator simulator = newPhysicsSimulator(newVector2(0, 250));
The shelf data • The shelf is the simplest object on the screen • It has a texture that is used to draw it, a Farseer body and a Farseer geometry • It also has an origin value, which is the “centre” of the object ///<summary> /// Texture of the shelf the target sits on ///</summary> Texture2DshelfTexture; BodyshelfBody; GeomshelfGeom; Vector2shelfOrigin;
The shelf body • This creates a shelf body and places it in the world • Note that I’ve scaled the texture to fit the display world • I have also made the shelf static, so that it can’t move around in the world shelfTexture = Content.Load<Texture2D>(@"images\shelf"); shelfOrigin = newVector2(shelfTexture.Width / 2.0f, shelfTexture.Height / 2.0f); shelfBody = BodyFactory.Instance.CreateRectangleBody( shelfTexture.Width, shelfTexture.Height, 1); shelfBody.IsStatic = true; shelfBody.Position = newVector2(550, 400); simulator.Add(shelfBody);
The shelf geometry • This creates a shelf geometry and places it in the world • This sets out how much bounce (RestitutionCoefficient) we get from the shelf and how slippery (FrictionCoefficient) we want it to be • Playing with these values is fun shelfGeom = GeomFactory.Instance.CreateRectangleGeom(shelfBody,shelfTexture.Width, shelfTexture.Height); shelfGeom.RestitutionCoefficient = 0.3f; shelfGeom.FrictionCoefficient = 0.5f; simulator.Add(shelfGeom);
Drawing the shelf • We use a more advanced version of the Draw method that lets us specify a rotation value for the texture • The shelf won’t rotate, but other objects will • Note that we get these values out of the geometry for the shape • The draw operations for all the game objects look the same spriteBatch.Draw(shelfTexture, shelfGeom.Position, null,Color.White, shelfGeom.Rotation, shelfOrigin, 1, SpriteEffects.None, 1);
The Target data • The target is the house we are aiming at • It has the same information stored about it as the shelf • We will place the target on the shelf when the game starts • The only difference between the target and the shelf is that the target is allowed to move • The aim of the game is to knock the target off the shelf
The Target mass • Bodies in Farseer are given mass • The higher the mass the harder they are to get moving, and the more damage they do when they hit • The mass of the shelf is not an issue, since it is fixed in position • I’ve given the target a mass of 3 • This is a value you might want to fine tune targetBody = BodyFactory.Instance.CreateRectangleBody(targetTexture.Width, targetTexture.Height, 3);
Ball Position • The ball geometry is based on a circle rather than a rectangle • When create a circle you give the radius and the number of edges • This is because the circle is actually an approximation • The more edges, the more accurate the approximation but the more work it is to calculate ballGeom = GeomFactory.Instance.CreateCircleGeom(ballBody,ballTexture.Width/2, 50); ballGeom.RestitutionCoefficient= 0.3f; ballGeom.FrictionCoefficient = 0.5f;
Ball Launching • We use Windows Phone gesture support to fire the ball • The Flick gesture provides a Delta vector that we apply as an impulse to the ball object while (TouchPanel.IsGestureAvailable) { GestureSample gesture = TouchPanel.ReadGesture(); if (gesture.GestureType == GestureType.Flick) { ballBody.ApplyImpulse(Vector2.Divide(gesture.Delta, 1.5f)); } }
Detecting Collisions • Farseer will detect collisions for us • We can bind an event handler to the collision event • When the collision occurs the handler method is called automatically • The above code binds a method to the collision event ballGeom.OnCollision += newCollisionEventHandler(ballHits);
Collision handler • Called whenever a collision is detected • Checks to see if the ball has hit the shelf or the target boolballHits(Geom geometry1, Geom geometry2, ContactListcontactList) { if (ballSoundActive) returntrue;if (geometry1 == shelfGeom || geometry2 == shelfGeom) returntrue; ballSoundActive = true; bangSound.Play(); returntrue; }
Collision handler sound management • Only plays the sound if the ball has hit the house • Only plays the sound once boolballHits(Geom geometry1, Geom geometry2, ContactListcontactList) { if (ballSoundActive) returntrue;if (geometry1 == shelfGeom || geometry2 == shelfGeom) returntrue; ballSoundActive = true; bangSound.Play(); returntrue; }
Updating Farseer • We need to add this method call to the Update method to keep the Farseer simulation running • The time factor controls the rate at which the engine updates • You can tune this if you have problems with items moving so fast they go inside or through each other • For the purpose of my program the value above works fine simulator.Update(gameTime.ElapsedGameTime.Milliseconds * .0005f);
Scrolling Background • We use a transformation matrix for the draw operation so that we can scroll the screen to follow the ball • We can get the position out of the ball geometry so our program can tell where the ball is if (ballGeom.Position.X + scrollMargin > width) { // need to scroll the screen xOffset = width - (ballGeom.Position.X + scrollMargin); }
Transformation Matrix • A transformation matrix is a lump of maths that can be applied to a drawing operation to change the way it looks • Scaling • Rotation • Translation • We just want to translate our view when we draw it • XNA will create a translation matrix for us Matrix transformation;transformation = Matrix.CreateTranslation(xOffset, 0, 0);
Drawing with a Transformation Matrix • We can ask SpriteBatch to use this matrix to transform the drawing operation • All the drawing performed will be moved according to the matrix supplied • We can follow this with an “untransformed” draw if we wish spriteBatch.Begin(SpriteSortMode.Immediate, null, null, null, null, null, transformation); // transformed drawing spriteBatch.End();
Using the phone accelerometer • You can also use the accelerometer to control the behaviour of objects in your game • The Accelerometer can measure acceleration in X, Y and Z • You can use just the X and Y values to turn it into a replacement for a gamepad • The values that are returned are in the same range • -1 to +1 in each axis
Adding the Sensors library • The reason why the accelerometer is event driven is that XNA actually uses the same sensor interface as Silverlight • This means that you need to include the appropriate sensor library into your program to obtain accelerometer readings • You need to add Microsoft.Devices.Sensors to your solution to bring in the library
XNA 4.0 Accelerometer • Unlike other XNA input devices the accelerometer in XNA 4.0 is event driven • The accelerometer generates events when new readings are available • You must bind a method to the event • The method can store the settings for later use
Creating an Accelerometer • The above code runs in the Initialise method to set up the accelerometer • It creates a new Accelerometer, binds an event handler to it and then starts it running • Accelerometer accel = newAccelerometer(); • accel.ReadingChanged += • newEventHandler<AccelerometerReadingEventArgs> • (accel_ReadingChanged); • accel.Start();
Reading The Accelerometer • objectaccelLock = newobject(); • voidaccel_ReadingChanged(object sender,AccelerometerReadingEventArgs e) • { • lock (accelLock) • { • accelReading.X = (float)e.X; • accelReading.Y = (float)e.Y; • accelReading.Z = (float)e.Z; • } • }
Using The Accelerometer • lock (accelLock) • { • cheeseAcceleration.X = accelReading.X * acceleratorPower; • cheeseAcceleration.Y = -accelReading.Y * acceleratorPower; • } • This code uses the accelerometer values stored by the event handler to manage the cheese movement • Note that I use a lock to stop the event handler and the Update method from fighting over the values
“Tipping” games • The accelerometer makes it very easy to create “tipping” games, which simulate gravity moving items around the screen • The further you tip the device the greater the force acting on the object • We could use the accelerometer values as forces that drive the Farseer physics engine directly
Games and Applications • Programs are loaded onto the phone from the Marketplace over the air (WiFi or 3G) or via the Zune application • This is the only way to put programs on a “locked” device • Registered developers can unlock a device for testing
Joining the Marketplace • If you want to take your games to market you will need to join the Windows Phone Marketplace as a developer • This is managed via your Windows Live identity • It costs $99 per year • Students can get free membership via DreamSpark • Joining the Marketplace lets you publish games and unlock Windows Phone devices for testing • Developers can unlock up to three devices • Students can unlock just one
Free and Trial Applications • You can give away up to 100 applications each year you are member of the Marketplace • Any further free applications will cost $20 each for validation • You can also make available “trial” versions of a game or application • Customers can purchase an upgrade from within the application
Submitting Applications • You are guided through the submission process for your application • The application itself is submitted as a single “xap” file • This is an archive with a manifest which is generated by Visual Studio when the game is built • It contains all the game content and resources