Susan IbachTechnical Evangelist
In parts 1 and 2 of this series, we setup a multiplatform XNA solution that deploys to the PC, Xbox 360 and Windows Phone 7 devices seamlessly. In this 3rd and final part of the series, we’ll implement platform-specific behavior within the same codebase. And we’ll finally make our ship do something!
Conditional compilation symbols
When you created the three projects, Visual Studio set project-specific Conditional compilation symbols. These flags can be used with preprocessing directives to create conditions in the compilation process.
To view and edit these symbols, Right-click on a game project, select Properties, and go to the Build tab.
By default, Visual Studio added the WINDOWS symbol for the Windows project, XBOX and XBOX360 symbols for the Xbox project and WINDOWS_PHONE symbol the Windows Phone 7 project. In this article, we’ll use these to set certain platform-specific properties and capture hardware-specific input.
Settings up graphics properties
We’ll use the GraphicsDeviceManager to setup the screen properties for each platform. In the Initialize() method of the Game1 class, add the three #if preprocessor directives:
protected override void Initialize()
// TODO: Add your initialization logic here
For the purpose of this tutorial, we’ll run all three platform builds in full-screen. However, we’ll need to set an appropriate resolution for each one:
// TODO: Add your initialization logic here
graphics.PreferredBackBufferWidth = GraphicsDevice.DisplayMode.Width;
graphics.PreferredBackBufferHeight = GraphicsDevice.DisplayMode.Height;
graphics.PreferredBackBufferWidth = 1280;
graphics.PreferredBackBufferHeight = 720;
graphics.PreferredBackBufferWidth = 800;
graphics.PreferredBackBufferHeight = 480;
graphics.IsFullScreen = true;
For the PC, we retrieve the desktop resolution and set our back-buffer (the viewport) to match it. For the Xbox, we use its native 720p high-definition output by setting the back-buffer bounds to 1280 by 720 pixels. For the phone, we simply set the resolution to the maximum resolution dictated by the Windows Phone 7 platform. Finally, we set the IsFullScreen property to true and call the ApplyChanges() method to commit the above changes. Note that these 2 lines of code are outside of any platform-specific preprocessor directives, since we want these two things to apply to all three of our builds.
When building the solution, depending on the target project, each flag in the processing directive will be checked. If it is set, the code inside the #if-#endif pair will be built. This means that you must be careful about fragmenting your code. For example, if you declare a field in a #if-#endif directive, but assign to it outside of the same condition, you will get an error for a specific platform (or a specific condition) about a missing declaration.
At this point, if you were to run the project on any platform, the resolution will be automatically adjusted and you should see the ship in platform’s native full-screen resolution, without any scaling or stretching!
Note: IsFullScreen is not strictly needed for the Xbox version, as all XNA games on the Xbox run in full-screen by default.
Capturing platform-specific input
Let’s make things a bit more interesting and challenging, by rotating the ship with a platform specific input device. On the PC, the input comes primarily from the mouse/keyboard combination; on the Xbox 360 from the Xbox controller; on the Windows Phone 7 from the touch panel. The Xbox controller can also be used as a gamepad in Windows. A keyboard can be used on the Xbox 360, but you should avoid this scenario, since most Xbox 360 owners don’t have a keyboard connected to their console. Windows Phone 7 devices also have additional buttons such as the “back” button, which can be read in XNA.
First, we’ll add platform independent code that will rotate the ship around the y-axis (also known as “Yaw”). Add a float to hold the yaw angle:
public class Game1 : Microsoft.Xna.Framework.Game
float yawAngle = 0.0f;
To rotate the ship, we’ll set the world matrix to the rotation about the y-axis matrix that is constructed with the yawAngle, which we set with an input device.
protected override void Update(GameTime gameTime)
world = Matrix.CreateRotationY(yawAngle);
Next we will capture input from the keyboard to rotate the ship with the arrow keys. Remember that keyboard input should be captured on Windows only; we check if WINDOWS is set.
yawAngle += 0.05f;
yawAngle -= 0.05f;
We’ll use the Xbox controller’s left thumb-stick to rotate the ship left and right as well.
yawAngle += GamePad.GetState(PlayerIndex.One).ThumbSticks.Left.X;
If you were to test this code now, you’ll notice a little quirk. On Windows we’re incrementing/decrementing the angle by a constant of 0.05 radians every update. But on the Xbox the angle depends on the X position of the thumb-stick, which can result in a large value. The easiest solution is to simply dampen the value by a constant:
yawAngle += GamePad.GetState(PlayerIndex.One).ThumbSticks.Left.X * 0.05f;
On Windows Phone 7, input is not as simple as keyboard strokes and thumb-stick positions. The phone captures input by recording touches. Touch points and displacement between them can be determined from raw touch data. Common higher level motions – known as gestures – are already provided by the XNA framework, so you don’t have to write your own. We’ll use the horizontal drag gesture to rotate the ship. Before we go any further, however, we need to include a reference to the Microsoft.Xna.Framework.Input.Touch assembly. It wasn’t included because our Windows Phone 7 project was created from the Windows project.
Expand the Windows Phone Copy of XNAIntro project, Right-click on References and select Add Reference. Under the .NET tab select Microsoft.Xna.Framework.Input.Touch.
We can now use the namespace in Game1. Since it is to be used for the phone only, be sure to place it in a proper compilation condition:
/// This is the main type for your game
public class Game1 : Microsoft.Xna.Framework.Game
Before we can detect the horizontal drag gesture, we need to let the touch panel know that this gesture needs to be enabled.
TouchPanel.EnabledGestures = GestureType.HorizontalDrag;
Once the gesture is enabled, you can access the gesture with the TouchPanel.ReadGesture() method:
GestureSample gesture = TouchPanel.ReadGesture();
yawAngle += gesture.Delta.X * 0.005f;
We first check whether or not a gesture is available with the TouchPanel.IsGestureAvailable property. Failure to check for this condition will result in an exception thrown by the first TouchPanel.ReadGesture() call. We then read the gesture from the touch panel, which will return the next available gesture. This means that when you have multiple gestures enabled you would need to check the gesture.GestureType property to determine which gesture this is. In this case, the check is not required because the horizontal drag gesture is the only one we enabled. Also note that since the input feedback is different between all devices, we use a different dampening value.
Ready, Steady, Go!
We’re done! Select any platform and run the little “game” to enjoy a truly breathtaking experience. Using a single codebase, you effectively created not one or two, but three game versions. All three are identical, and yet all three run on different hardware architectures and accept platform-specific input.
Although this is the conclusion of the series, you can find plenty of resources to get you going further on the App Hub at http://create.msdn.com. Enjoy!
Did you know that as a student, you have access to lots of freebies on http://www.dreamspark.com/? Need more development power than Visual Studio 2010 Express can offer? Want to get access to the full Microsoft Expression Studio suite? DreamSpark is the solution!
DreamSpark provides students with various development and design tools at no charge. Additionally, various offers such as Microsoft Certification and AppHub Marketplace registration fees are waived for students through DreamSpark registration.
To access all the goodies on DreamSpark, simply verify your identity through your school email. If your email is not on the school list, email firstname.lastname@example.org to receive a redemption code.
It is sometimes difficult to make mock up or to prototype your mobile concepts. Coding out certain features might be easy when you are familiar with the platform and tools but time to produce a function application might be long and with lots of growing pains.
Imagine developing an app in less than 30 minutes with no coding required. Creating a Windows Phone App has never been easier! Microsoft is excited to announce the relationship with AppMakr—get the tools and resources you need to develop an awesome Windows Phone 7 App. Watch the Demo »
A few weeks ago, having connected my Samsung Focus to my desktop for syncing, I was greeted with a pleasant message from Zune notifying me that a Windows Phone 7 update was available. The NoDo update included fine-tuned performance and app start-up time tweaks, as well as the much awaited copy and paste feature, among other things. Features aside, the performance optimizations alone gave the OS a fresh and brand new feel. So needless to say, I am really excited about Mango – the next WP7 update. Mango’s list of features is so immense, that the update might as well be described as an intermediate OS release between the current version of WP7 and Windows 8.
For starters, Mango will include the mobile version of IE9, along with some of its most important features. In-browser Silverlight, HTML5 and hardware acceleration support are all slated to be included in the mobile cousin of the desktop browser. With HTML5, a music site with an audio playlist, for instance, will let you play music directly from the browser. While GPU accelerated Silverlight will give you direct access to interactive multimedia, once again, directly from your browser. And yes, that includes games. These features are impressive on their own, but I am even more eager to make use of them simultaneously, as Mango will include true multitasking. In the MIX2011 showcase, this was presented by playing music on a website using HTML5 and returning to the home screen with the music continuing to play. If you enjoy habitual game-playing but quickly grow tired of in-game music and would rather stream an online audio stream, then Mango has a treat for you!
Mango opens the doors wide-open to developers with an ocean of new APIs. Included in the list is support for TCP/IP sockets, finally paving the way to direct communication, instant messaging, multiplayer gaming, and more. Raw access to camera stream along with a motion sensor library and gyroscope support will allow for development of augmented reality apps and games. One particular API that is near and dear to my heart, XNA, will benefit from Silverlight/XNA integration, allowing for Silverlight’s UI components to be used natively in 3D accelerated games.
Along with these features, the already gorgeous Metro UI also gets a facelift. One particular feature that I think will become both handy and aesthetically pleasing to everyone is the alphabetical categorization of apps. The new layout is identical to the way your contact list behaves, allowing you to navigate to an app by name by selecting the first letter. Additionally, live tiles will be updateable with push notifications. In fact, apps will be able to take advantage of double-sided tiles and even multiple tiles.
With all that said, allow me to leave you with something to think about. Although the enormity of Mango makes it look like a major OS release, it is still bound to be just an update for WP7. However, now that we know that Windows 8 will be heading to SoC and will natively support ARM, it sure does make you think about what the next evolution of the PC and subsequently Windows 8-based tablets will be like. No speculation though, just food for thought :)
This combination video and text tutorial set teaches basic 2D game development on Windows, Xbox 360, and Windows Phone 7 using XNA Game Studio 4.0 my be found here
Learn the following lessons in our easy-to-follow chapters:
On this new Game Development Page