Renoki: Making An Android Game (part 3)
Dealing with Multiple Resolutions
Something that had originally confused me was how I was going to set the game board to support multiple resolutions. As of Android 1.6, you can basically have any resolution you want, ranging from the original Android G1 phone 480×320 to my Thunderbolt with 800×480. The way Renoki is going to be made is to have a static background image (the game board) and the monsters, doors and hammer swings would be sprites I animate on top of it. The question is: How do I take a static back ground image and make it look right on two phones, where one is almost double the resolution of the other?
Turns out Android handles this by just lumping everything into small, medium and large categories (and extra large categories for tablets). They also use two terms to describe this: “size” and “pixel density”.
Size is the physical dimensions of your device, across the diagonal. So anything that is less than maybe 2-3 inches is small, 4-5 is medium, 5-7 is large, anything bigger is extra large. Even if two phones have slightly different physical dimensions, they would still get lumped into the same category. Thus, most phones tend to fall into the medium size, and since I’m developing Renoki only for phones, I don’t need to really concern myself with size.
Pixel density is the number of pixels per inch. Now the Thunderbolt has absolute pixel (px) dimensions of 800×480, but Android has another unit called density pixels (px). If you query the screen height and width from within your app on the Thunderbolt, it will return 533x320dp. If you did the same for the G1, you get 480x320dp. The reason is that the Thunderbolt has a high pixel density while the G1 only has a medium pixel density. On the Thunderbolt, 1 density pixel is the equivalent of 1.5 absolute pixels. On the G1, 1 density pixel is 1 absolute pixel.
Thus, you can pretend the Thunderbolt has a 533×320 resolution when specifying the X and Y coordinate of the sprites. As long as you always use dp for your units, Android will automatically rescale everything for you. Therefore, putting a sprite at position (50,50) will be the same relative location on both the G1 and the Thunderbolt. If there are other phones with other strange resolutions, 1 dp might equal 1.33 px and so on.
There are still 2 different things to worry about. Firstly, although Android will automatically rescale everything for you, this does not prevent them from becoming warped or distorted when scaling. Just like when you blow up a tiny image it looks blurry, the same thing would happen if you provided an image for a mdpi phone and viewed it on a hdpi phone (enhance…enhance…enhance). Android solves this problem by allowing you to provide multiple versions of the same images, resized for different pixel densities. In the ‘res/drawable’ directories, there is a ‘res/drawable-ldpi’, a ‘res/drawable-mdpi’ and a ‘res/drawable-hdpi’. You might put a 48x48px image for mdpi, and a 72x72px image for hdpi. You give all the images the same name and place them in the appropriate directory in your Eclipse project. Android will automatically pick the image depending on the device you are running your app on.
The last thing to take into account is when you have screens with different aspect ratios. The G1 is 480×320 or 1.5. The Thunderbolt is 533×320 or 1.66 (repeating of course). This means the Thunderbolt screen is a little bit longer (or taller, depending on how you want to say it) than the G1. When I display an image like the game board, you will see “more” of the image on the Thunderbolt than the G1. The only way to really handle this is to design for the smallest aspect ratio and to only put non-essential things outside of that.
I will make my main game board (the doors, the score, your hammer, your gold, etc) all fit into a 480×320 box. I will then extend the image another 53 pixels underneath with some non-essential image or just plain color. On the G1, everything under that red line won’t even show up. On the Thunderbolt, maybe I would put an image of a monster waving at you or something else stupid. Regardless, the game board is the same size and nothing essential is cut off. Unfortunately, I don’t think there is a better solution than this other than just not supporting certain aspect ratios.