Monday, 22 November 2010

Shrinking Dysnomia

In my last post, I teased Dysnomia running on Windows Phone 7. It's an interesting challenge, shrinking the game down to run on the phone. I did a lot of optimization on the 360 version, mostly around garbage collection and memory management while the gameplay was running.

What I did not optimize at all was RAM usage. I chose to load all game assets up-front, even before the title screen appeared. For the 360, the amount of overall RAM used was trivial, and the load times were fast. I loaded all animation spritesheets, all sounds, all music and all popup screen content before the first level was started.

The only items I chose to load per-level were the tilesheets, as they were by far the largest textures used in the game, and I needed to be able to free up the RAM they used between levels.

On the phone however, the RAM usage story is completely different. Microsoft recommends that an application shall not exceed 90mb of total RAM usage, that is to say peak usage. It's a simple matter to check how much memory your app is using:

var curuse = (long)DeviceExtendedProperties.GetValue("ApplicationCurrentMemoryUsage");
var memuse = (long)DeviceExtendedProperties.GetValue("ApplicationPeakMemoryUsage");
var maxmem = (long)DeviceExtendedProperties.GetValue("DeviceTotalMemory");
curuse /= 1024 * 1024;
memuse /= 1024 * 1024;
maxmem /= 1024 * 1024;

Will return current memory usage, peak memory usage, and total RAM available (in MB) respectively.

So when I hooked up a debug method to output the RAM usage to the screen, I discovered that Dysnomia was using 190MB at peak (with the map screen open), and 170MB during normal gameplay. That's twice the usage limit for passing app certification!

I began by simply cutting down on front-loaded assets. Later on, I'll implement per-level loading of required spritesheets, but for now I've simply eliminated loading of everything not needed for the first level. That alone got me down to around 110MB peak usage.

Next up, I began resizing all of the sprite and tilesheet textures. An across-the-board resize of 75% got me down to around 80MB peak. Several larger spritesheets could be downsized even further. Next up, I stopped loading variations of HUD and player sprites for different player colour options and for player two, as there will be only one player on the phone.

After all that, I'm currently down to 75MB in-game, and 80MB or so on the map screen. I'm still investigating further reductions, including using DXT compression for spritesheets. My target is 65MB in-game usage before reinstating sound effects and boss fights, which will require a good 10-15MB of RAM per level on top of what's used already.

I'm not going to officially confirm Dysnomia for WP7 until I'm sure I can make it work, but so far I'm impressed with the virtual sticks (emulating left/right thumbsticks via the touchscreen) I've implemented, so I'm sure it will control quite nicely if I can just get everything squeezed into RAM.

Game 4

Can't wrap up this post without a quick update on Game 4. I've resumed work on the next Team Mango game, working on it alongside Dysnomia for WP7 and Run! for XBLIG. It's an RPG, and the next job I needed to complete was getting an enemy manager up and running. The manager controls all of the enemies loaded on a map, including their spawn points.

As the game is based upon my XNA Tile Engine solution, I'm using the Tiled editor to lay out the area maps. To depict enemy spawns, I'm using an Object layer. The screenshot below shows a typical map layout with spawns. Each rectangle represents one enemy's patrol area, with the spawn point in the center. When the enemy is loaded, a point within its rectangle is chosen at random, and the enemy begins to move toward that point. When it reaches its destination (or collides with a wall), it chooses a new destination point from within its rectangle.

And the result, Squirrels!

No comments: