Sunday, January 30, 2011

The main differences when porting a game from Windows Phone 7 to Xbox360

Since the Xbox360 version of my game Jigsaw Guru was released on the marketplace a week ago, I thought I could write a post about the main changes I had to make to go from a mobile device to a living room console. Those changes basically fall under 3 categories: screen, input, and storage.


A TV screen is obviously bigger than the screen of a phone, but more importantly it has a different resolution and aspect ratio. The difference can actually be huge, if the game runs in portrait mode on the phone:

Jigsaw Guru on Xbox360, 1280*720
Jigsaw Guru Free on WP7, 480*800

Fortunately for me, the initial paid version of Jigsaw Guru runs in landscape mode on the phone, but going from 800*480 to 1280*720 still means all the graphics elements have to be scaled and positioned according to the width and height of the screen, which I do with code looking like this:

successRect.X = (int)(Renderer.Instance.DeviceWidth * 0.1f);
successRect.Width = (int)(Renderer.Instance.DeviceWidth * 0.8f);
successRect.Y = (int)(Renderer.Instance.DeviceHeight * 0.4f);
successRect.Height = (int)(successRect.Width * completedText.Height / completedText.Width);
spriteBatch.Draw(completedText, successRect, Color.White);

These lines are used to display the "Puzzle Completed" texture; successRect is an XNA Rectangle, Renderer.Instance is a singleton I use for all my rendering code, and as you can see all the dimensions I need are expressed as a percentage of the width or height of the screen. This is a pretty convenient system, for example tweaking the value returned by the DeviceHeight property was enough to make room at the bottom of the screen for the ad banner of the free version, and force the game to only use the top 90%. This won't solve every single case though, sometimes scaling the UI is not enough and a different layout needs to be used; but even if you're only working on 1 platform, it's better to not hardcode your sizes and positions in pixels, in case you want to change the resolution or support several aspect ratios (such as 4/3 versus widescreen) later on.

Televisions have a very annoying property: they don't display the whole image your console sends them. Depending on the model, up to 10% of the screen can be missing on each side, and you should therefore only draw important information in the remaining 80% zone in the middle, which is known as the "title safe area" (this is a certification requirement, if you don't follow it your game will not be approved on Xbox360). This actually took a big portion of the time I spent porting Jigsaw Guru to the console: I couldn't use the previous trick to make the game fit in the title safe area, because 1) you don't want to have a big black border on televisions that can display the whole image or most of it, 2) you don't want to only use 80% of a phone screen that's small enough already.

For this particular problem, I still tried to avoid having too much platform specific code everywhere I draw text and icons, by using a mix of small functions and constants like the following ones:

#if XBOX
        public const float textTop = 0.10f;
        public const float textBottom = 0.90f;
        public const float textTop = 0.07f;
        public const float textBottom = 0.93f;

For example, the "Select Game to Load" title in the previous screenshots is positioned like this:

textPosition.Y = Renderer.Instance.DeviceHeight * textTop;

instead of directly using DeviceHeight * 0.07f like I could do it if I was only developing for the phone. This makes sure the text is low enough to be entirely contained in the title safe area on the Xbox360. Also, to verify everything is correct on all the screens, I have a boolean I can toggle in debug mode to draw the title safe area limit as a red line:


Playing with a gamepad is of course totally different than playing with a touch screen, no surprise here. Therefore, the main input related change in the Xbox360 game is that the player moves a cursor on the screen to drag and drop puzzle pieces, instead of moving her finger. Also, some icons became unnecessary: for example, you don't tap a pause icon to go to the pause menu, you just press the Start button on the gamepad. But the modifications don't stop here.

The console can have up to 4 controllers connected to it, and a player must be able to pick any of them to play. That's why every Xbox360 game has a "start screen" before its main menu, where the controller used to press Start is detected, and remembered for the rest of the session (changing controller mid-game doesn't have to be supported, it's not a requirement).

In menus, you have to keep track of a "currently selected" item: on the phone, any icon can be tapped at any time, but on the console the player can only navigate to the previous or next item one step at a time.

Finally, games usually have a "controls screen" like the following one, and I didn't have anything like it on the WP7:


Saving settings and games to isolated storage and reloading them is fairly easy on WP7. On Xbox360 however, this is a different story: players may or may not have memory units, if they do they need to be able to select which storage device (including the hard drive) they want to use, and the game should never crash even if the selected device is removed at any time (while playing, loading, saving, you name it). In my opinion, this is the most annoying requirement to fulfill, it's not particularly difficult to implement it, but it's hard to think about all the different cases and places where something might go wrong and test them. Here are two things you can do to make your life easier, and hopefully avoid failing during peer review.

Use the EasyStorage library. Lots of Xbox Live Indie Games developers do it, and that's what I did too, even if I wouldn't have needed it for the WP7 version. I don't use the asynchronous functions because the files I read and write are very small and don't require any kind of progress bar, but I know they're here in case I want them in a future project.

Protect all your file accesses with try/catch blocks. Even checking if a file exists can fail if the storage device was removed, so don't be shy, and better be safe than sorry. Try to give some feedback to the players if you can, so that they don't assume their game was saved if it wasn't, they would hate you for that the next time they play (I know I would).

The other way around

What about going the other way around, and porting an Xbox360 game to the WP7 platform? Well, I haven't done that so I don't have much experience with it, but from the top of my head there are two phone specific things you'll have to pay attention to, in addition to what I have mentioned in this article: tombstoning, and the use of the Back button. Those are actually 2 of the main reasons for failing submission on the WP7, even when you're writing a game directly for that platform, so don't wait until the last minute to take care of them, the earlier you know what modifications they will require in your project the better.

No comments:

Post a Comment