Working with multi-resolutions assets

When we’re making mobile apps we have to support lots of resolution from 480 x 320 to 2048 x 1536 if you only target iOS. Adding Android support you have to extend it to 2560 x 1600 (for the Nexus 10)!

If your graphic designer made its design into a vector format, it will be easy to fit exactly to your screen size, and you will only fight with the different ratios format.
However if your design is made with bitmaps, you have to, firstly, be sure they have been made for the highest resolution you would like to support! When this is done, you will use a SpriteSheet to have all of your assets in one (or a little more) place.

In this blog post we will see how to manage multi-resolutions assets based on a Starling app.

When you’re building a game with Starling you have several way to handle the multi-resolution management and the Citrus Engine offers more. In this example, we will just fit Starling’ stage to always have the size of the device. And we will use our own scale factor!

I will override the CitrusEngine findScaleFactor with my custom one. Note it should be more or less the same even if you don’t use the Citrus Engine.

override protected function findScaleFactor(assetSizes:Array):Number {
 
	var minValue:Number = Math.min(screenWidth, screenHeight);
 
	if (minValue < 400) // iPhone3GS
		return 1; // 0.25 in TexturePacker
	else if (minValue < 640) // Lots of Android devices
		return 1.5; // 0.375 in TexturePacker
	else if (minValue < 1536) // iPhone4, iPhone5, iPad non retina
		return 2; // 0.5 in TexturePacker
	else  // iPad retina
		return 4; // 1 in TexturePacker
}

In my app I will support 4 sets of texture, we don’t want to create a lots more because it will request extra space. Also I don’t extend it to the Nexus 10, since the one provided by the iPad retina should be ok.

Now that I’ve my scaleFactor, I will load the correct set using Starling’s AssetManager:

Assets.assets.enqueue(File.applicationDirectory.resolvePath(formatString("assets/{0}x", scaleFactor)));
 
Assets.assets.loadQueue(function(ratio:Number):void {
	if (ratio == 1) {
		state = new GameState();
	}
});

Bonus: you can easily combine it with DragonBones! Here you should export your design into the awesome .dbswf format, it will save you lots of space! Also if you’ve designed your DragonBones assets at the maximum resolution you will supported, it’s perfect you can easily resize the future spritesheet:

Assets.factoryDB = new StarlingFactory();
Assets.factoryDB.scaleForTexture = scaleFactor / 4; // models designed for 4X.
 
Assets.factoryDB.parseData(new Assets.DragonBonesAssets());

Ok, so this is great but how could I automate my way to generate SpriteSheets?
Firstly, you have to use the best SpriteSheets generator on the market: TexturePacker. Put all your bitmap assets at one place, and drag and drop them in TexturePacker. When you’ve selected the different options save it as a .tps file!
You could manually generate SpriteSheets one by one just changing the scale and it will do the job. But it will be very annoying to do it each time you change one asset.
TexturePacker provides a command line tool, so let’s use it with a bash script:

#!/bin/sh
#!/usr/bin/env bash
 
DIR="$( cd "$( dirname "$0" )" && pwd )"
 
for i in 1 1.5 2 4
do
        TexturePacker --sheet "$DIR"/../bin/assets/"$i"x/assets.png --data "$DIR"/../bin/assets/"$i"x/assets.xml --scale $(echo "scale=3; $i/4" | bc) --format sparrow "$DIR"/assets.tps
        echo "pngquant image" "$i"x
        pngquant -f --ext .png "$DIR"/../bin/assets/"$i"x/assets.png
done
 
echo "TexturePacker and pngquant tasks done."
 
exit 0

Latest script version and instruction to run it.

It will generate you all the resolutions needed and applied the awesome pngquant! So it will greatly improve your final SpriteSheets weight!

Bonus: you will probably also use BitmapFonts into your game. I used to deal with the great GlyphDesigner, however I’m facing a strong issue: I’m not able to export a downscale BitmapFonts spritesheets (updated: in fact it’s only available via the command line). They all have characters to a different place. And I would enjoy to add this png generated to my main SpriteSheets… so how could I do that?

I switched to bmGlyph, and it enables me to downscale a BitmapFonts SpriteSheets. So thanks to this downscale, I generate them all (you will certainly don’t have to update this bitmap fonts often), add the 4x sizes to my bitmap assets folder, and remove all the others generated pngs. And then in the same repository than the future global SpriteSheet, I add the .fnt file. Now when Starling parse the SpriteSheet, it will also add the bitmap font. Powerful, isn’t it?

2 thoughts on “Working with multi-resolutions assets

  1. Hi Aymeric
    If i want to target ipad retina display what my background game image size will be (if we have include scalefactor in our calculation ) ?
    and if i want to resize my asset without something like texture packer is there any table that show me the last size(width height) of my game

Leave a Reply

Your email address will not be published. Required fields are marked *