How to create mobile games for different screen sizes and resolutions

Usually the first question our users ask is this one: "How can you design a game for multiple platforms with all the different devices and screen sizes?". So I will now explain how we achieved an equal gaming experience on all ranges of devices for our games by using V-Play. I will cover the basic concepts how to design your game graphics in the first part and then show how it can be implemented with V-Play.

Content Scaling

As a developer, you do not want to rewrite your code for different screen sizes, but expect to implement the game code once and then give the users an equal gaming experience. The major problem is that your game should work on many different devices with a wide range of different screen sizes and aspect ratios.

Take an iPhone 3GS for instance: it has a resolution of 480x320, which equals an aspect ratio of 3:2. The iPhone 4 and iPhone 4S have a resolution of 960x640, so doubled the size with still the same aspect ratio of 3:2. If you now want to share your game logic, one could just use the smaller size and then scale up the graphics as the aspect ratio stays the same. The drawback, however, with scaling graphics up is the lost image quality.

Another approach is to use higher resolution graphics (in fact the one with the highest resolution of the device you want to target) and scale it down on all devices. However, this is not a good idea because you effectively need much more memory and will lose performance on low-end devices.

The best approach is to use a different image with the higher resolution and use this image version on the iPhone 4 and the low-res version on an iPhone 3GS, which is effectively what Apple is doing by using images with a @2x suffix for the file name.

In a similar way, you can create all your graphics in ultra-high-resolution needed for the iPad 3 for instance and append another suffix, and load the right image based on the screen resolution the device has. This is called content scaling, as the game was written only for a single "logical" scene size, and all the images & fonts are scaled to the device resolution.

However, this approach is not sufficient when you want to target devices with different aspect ratios. There is a plethora of devices out there, but if you have a look at their resolutions and aspect ratios you can limit it to this list:

Aspect ratio Resolutions Example Devices
4:3 320x240 Android devices
1024x768 iPad 1, iPad 2
2048x1536 iPad 3
3:2 480x320 iPhone 3GS and lower, Android devices
960x640 iPhone 4, iPhone 4S
16:10 800x480 Android devices, WindowsPhone7
1280x800 Android tablets like Google Nexus 7, Samsung Galaxy Tab 10.1, Motorola Xoom, Asus Eee Pad Transformer
17:10 1024x600 Android tablets like Samsung Galaxy Tab 7
16:9 640x360 Symbian3 devices like Nokia C7
854x480 Android devices, MeeGo N9
1136x640 iPhone 5

To fit the logical scene size into the display resolution, you can set different scale modes in V-Play:

letterbox

This is the most common setting. The content is scaled uniformly (i.e. with the same value for x and y scale) so the smaller side fits into the display. This setting results in remaining space on the borders depending on the aspect ratio of the device. If the logical scene size is 480x320 for instance and the device resolution is 1024x640 (ratio 16:10), the used xScale and yScale is 2 and there are 64 pixels left on the left and right side together.

A background image with 3:2 ratio will have black borders on different ratios.

Instead of just letting this spare space black, it can be used for background images to display additional content that is outside of the logical area and thus only visible on devices that have a different aspect ratio. Mention to only put graphics in the spare space that are not game-relevant, because they are not visible on devices with different ratios! So instead of creating a background in 3:2 ratio, rather create one to fit the "worst-case" ratios 4:3 and 16:9. This results in the following sizes for background images:

Image type Unmodified 3:2 ratio size Suggested Background Size
sd 480x320 570x360
hd 960x640 1140x720
hd2 1920x1280 2280x1440

So with these background sizes, your game will work on all devices and all screen resolutions.

The above image shows a background image with 1140x720 pixels for the hd versions used for the iPhone 4 for instance.

If you are wondering how these magic numbers for the background images were calculated: Starting from a 3:2 ratio, the worst case for the horizontal stretch will be the 16:9 ratio. Thus the 16:9 ratio is 1.185185 times bigger than the 3:2 ratio for the xScale. A multiplication of 480x1.185185 equals 568.8 which is rounded up to 569px - however, to avoid 1px off calculations e.g. at centering the minimum size is 570px. The worst caste for the vertical stretch is the 4:3 ratio, which is 1.125 times bigger for the yScale and 320x1.125 equals 360 pixels. That is the starting point for the sd graphics, for the hd versions it is simply doubled each side and hd2 4 times the sd size. I recommend creating the game with a logical scene size with 3:2 ratio, because it is in the middle of the extremes. If we would start with a 16:9 logical scene size for instance, there would be a lot of wasted space for a 4:3 ratio, whereas with the suggested 3:2 ratio the remaining space is equally distributed for all other ratios.

So to sum this all up, this is how you can support all screen sizes:

  • Set your Scene size to either 480x320 if your game is in landscape mode, or 320x480 for portrait games.
  • Design your background image for the highest resolution 2280x1440. In this background, the safe zone is 1920x1280 which is shown on all devices. The remaining areas (the blue and red rectangles in the image below) are only shown on devices with an aspect ratio different than 480x320.

Note: You can download a Photoshop template for your background and the safe zone here. This is how it looks like:

zoomToBiggerSide

This mode scales uniformly to the bigger value of the calculated xScale and yScale settings. Parts of the logical scene will be outside of the screen when the device has a different aspect ratio than the logical scene. Mention that this is not suitable for games that require the whole logical scene to be on-screen like tower defense games, because then you would not be able to build towers on the edges and thus have an unfair situation for players with different aspect ratios! If the logical scene size is 480x320 for instance and the device resolution is 1024x640 (ratio 16:10), the used xScale and yScale is 2.13 because 1024/480=2.13 which is bigger than 640/320=2.

zoomNonUniform

With this scaleMode, your logical scene will be scaled to exactly match the screen, which leads to unequal scale factors for x and y if the screen has a different aspect ratio than the logical scene. The result is that the background image and the content get distorted which will be visually distracting. In some rare cases, the distortion is not obvious (e.g. when only a gradient image is used as the background), but most of the time you want to avoid this situation and rather use letterbox or zoomToBiggerSide scaleModes.

Visual distortions from scaling non-uniformly from an image with an original ratio of 3:2, scaled to a 4:3 and 16:9 ratio.

none

This mode does not perform any content scaling. So the displayed images and fonts will always be the size of the logical scene and will not be scaled to the screen size. This can be used if you want to roll your own scale settings or load different layouts depending on the given screen size.

Scene alignment

There are cases, when you don't want to position the background in the center of the device. For that cases, the scene alignment property can be used, both with the default value center:

  • sceneAlignmentX can have one of the values center, left or right
  • sceneAlignmentY can have one of the values center, top, or bottom

Position relative by screen position

Although the logical scene and all the entities should be positioned within the logical scene borders, you will want to place HUD elements containing labels, menus or thumb based on the absolute screen position and not relative to the logical scene. So for instance the score or lives text should always be on the edge of the screen and not anchored to the logical scene. The following image show a bottom menu and score and lives label positioned (or anchored) relative to the logical scene (the bright area). The second image shows the same, but relative to the screen with a 4:3 ratio.

The bottom menu, score and lives label anchored relative to the scene. The bright area is the size of the logical scene having a 3:2 ratio, and the screen having a 4:3 ratio.

The bottom menu, score and lives label anchored relative to the screen which is the best approach for HUD elements.

For this use-case, you can easily position your items relative to the screen and not to the logical scene in V-Play, but still enjoy the advantage of content getting scaled automatically (so fonts are getting scaled device-independently and the ideal-size image is taken).

Example of positioning relative to the screen & content scaling by using V-Play

The above example can be implemented with the following code in V-Play:

 import QtQuick 2.0
 import VPlay 2.0

 GameWindow {
     // this is the size when starting the game on the desktop
     //on mobile devices the size gets set to the full screen automatically
     screenWidth: 1024
     screenHeight: 768

     Scene {
         width: 480
         height: 320

         property int score: 0
         property int lives: 50

         Text {
             text: "Score " + score
             anchors {
                 top: gameWindowAnchorItem.top
                 left: gameWindowAnchorItem.left
                 leftMargin: 5
             }
         }

         Text {
             text: "Lives " + lives
             anchors {
                 top: gameWindowAnchorItem.top
                 right: gameWindowAnchorItem.right
                 rightMargin: 5
             }
         }

         BottomMenu {
             anchors {
                 bottom: gameWindowAnchorItem.bottom
                 left: gameWindowAnchorItem.left
                 right: gameWindowAnchorItem.right
             }
         }
     }
 }

Dynamic Image Switching Support

V-Play adds support for dynamic image switching based on the screen size. This allows you to:

  • Save graphics memory: based on the screen size, the best matching image is selected to avoid upscaled and blurry images, and to save memory compared to an approach where always the highest resolution images are used.
  • Improve loading times: as the best-sized image is selected, you get an ideal loading time of the used image.
  • Work with the logical size of the image in your GameWindow and Scene to simplify multi-resolution positioning and to use Content Scaling.

See the V-Play File Selectors documentation for more details about dynamic image switching.

The V-Play Script for Multi-Resolution Asset Generation alllows you to create sprite sheets from single sprite frames and scale them down automatically.

Other useful V-Play components for multi-resolution handling

The following is a list of useful V-Play components for handling different screen sizes and a quick explanation of them.

GameWindow Component

The GameWindow component allows switching resolutions and aspect ratios while testing on the desktop during runtime. This makes it great for testing how the game will look like on different devices. The various resolutions can be toggled by pressing the keyboard buttons ctrl(cmd)+1-7. Fullscreen can be changed by pressing the keyboard button ctrl(cmd)+F.

Scene Component

The Scene component represents the logical scene, which gets scaled to the screen based on the scaleMode (letterbox is the default setting).

MultiResolutionImage Component

For the MultiResolutionImage component, the correct V-Play File Selectors are automatically selected based on the scene scale factor. It will either be the default folder, +hd or +hd2.

Sprite Components

The components AnimatedSpriteVPlay and SpriteSequenceVPlay support using the correct V-Play File Selectors.

References

This topic has been covered by others as well, and I want to share some valuable references with you if you want to dig deeper into this topic:

Where to go from here

You can put the learned concepts from this tutorial into action by making a real game.

See these tutorials to learn how to make a V-Play game:

For another tutorial on density independence & multi-screen support, see Supporting Multiple Screen Sizes & Screen Densities with Qt & V-Play.