Learn what Felgo offers to help your business succeed. Start your free evaluation today! Felgo for Your Business

How to create mobile games for different screen sizes and resolutions

How to create mobile games for different screen sizes and resolutions

With all the different device form factors today, cross-platform developers are facing the challenge of delivering an equal user experience to every user. This includes different resolutions as well as different aspect ratios, especially when it comes to the countless Android phone manufacturers.

The main questions to take care of are:

I will show you how to master this challenge with ease, using Felgo. The theory behind the solutions I present might also be useful if you are using any other framework, so I suggest you read through this guide anyway!

Download Felgo now and Create Games and Apps For Any Mobile Screen Resolution.

Let's have a closer look at the questions above, one by one.

Content Scaling

Our first question was how to make sure the game logic and mechanics are equal and fair on any device.

Well, we could re-write our code from scratch for any different screen sizes. Or we could re-calculate any x, y, width, height, velocity etc. values depending on the screen size at runtime.

How about no?

Yeah this does sound like a lot of work. We want to have a single code-base, that is easy to read and maintain. Thus instead we can make use of a neat principle called Content Scaling.

It pretty much means that you design your game once for the lowest resolution that you want to support (called the logical resolution), and just scale it up as a whole on larger resolutions, to offer an equal gaming experience. With Felgo, the default logical resolution is 480x320 (for landscape mode). E.g. an iPhone 4 has a resolution of 960x640, that's exactly double the resolution, so it's easy to scale the game up and it will perfectly fit in the device screen.

With Felgo, the Scene component takes care of that scaling mechanism automatically.

 import Felgo 4.0
 import QtQuick 2.0

 GameWindow {
   // The size of the GameWindow will match the physical size of the device, e.g. 960x640

   Scene {
     // The Scene and all it's content will automatically be scaled up if needed
     // You can access the scale factor with xScaleForScene and yScaleForScene, just in case you need it

     // This is the logical size you use to design your game, setting this is optional
     // Depending on the orientation, the scene size defaults to 480x320 or 320x480
     //width: 480
     //height: 320

     Image {
       anchors.centerIn: parent
       width: 50
       height: 50
       source: "https://felgo.com/web-assets/balloon.png"
     }
   }
 }

Scale SD to HD

Alright, that one was easy. However what happens if you take an image with 40x40 and scale it up to e.g. double its size? Right, it will get blurry. The next chapter deals with this issue (don't worry, it's easy as well).

Smart Asset Selection

We want to avoid images getting blurry when scaling up the scene. An easy solution would be to use a really big image, so effectively it will be scaled down on lower resolution devices. E.g. for our 40x40 image in the game, we use a 160x160 source image, then we can easily scale up the scene to 4 times its logical size. But is this solution ideal? Of course not, this chapter would be way too short that way!

What happens with using only big images, is that we might run out of memory very fast, especially on lower-end devices. We are loading all those big images, even though we are displaying them very small, that is a huge waste of precious memory. A really good solution is to load a different version of your image, depending on the size it is needed on the current device. This technique is very common in mobile development, and Felgo supports this in an elegant way, with the MultiResolutionImage component.

 import Felgo 4.0
 import QtQuick 2.0

 GameWindow {
   // The size of the GameWindow will match the physical size of the device, e.g. 960x640

   Scene {
     // The Scene and all it's content will automatically be scaled up if needed
     // You can access the scale factor with xScaleForScene and yScaleForScene, just in case you need it

     //width: 480
     //height: 320

     Row {
       spacing: 10
       anchors.centerIn: parent

       Image {
         width: 50
         height: 50
         source: "https://felgo.com/web-assets/balloon.png"
       }
       // The MultiResolutionImage will automatically select the ideal image size depending on the device
       MultiResolutionImage {
         width: 50
         height: 50
         source: "https://felgo.com/web-assets/balloon-multi.png"
       }
     }
   }
 }

All that is left for you to do is to provide images with different sizes to select from, typically 3 versions, for SD, HD and HD2 resolutions.

  • SD: The image with the logical size used in your game
  • HD: Double the size of the SD image
  • HD2: Double the size of the HD image (-> 4 times SD)

In your assets folder, next to your normal (SD) images, you can make a +hd folder and a +hd2 folder, and put your images there, so the MultiResolutionImage can find them.

File selectors balloon

If you do not provide an asset in hd or hd2 resolution, the next folder is chosen automatically. So you can start prototyping during development with just a single image version and create the other resolutions later.

Dynamic Image Switching Support & Density Independence

To summarize this, Felgo adds support for dynamic image switching based on the screen density and 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.

So far so good, now let's move on to devices with different aspect ratios, as so far we only had a look at 3:2 (480x320, 960x640, ...).

Dealing with Aspect Ratios

Today, especially on Android, we have a huge variety of device ratios, from 4:3 to 16:9 and anything in between. Here are some examples:

Aspect ratio Resolutions Example Devices
4:3 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
1136x640 iPhone 5
1280x720 HTC One Mini, Samsung Galaxy S3
1334x750 iPhone 6/6S, iPhone 7/7S
1920x1080 iPhone 6 Plus, iPhone 7 Plus, Google Nexus 5, Samsung Galaxy S5
2560x1440 Samsung Galaxy S7

Your logical scene has a constant aspect ratio, which by default is 3:2 (480x320). Now first we have to decide how we want to fit this scene into another aspect ratio. There are different kind of scale modes that I want to show you, although there is only one which is of real interest to us.

letterbox Scale Mode

This is the most common scaleMode. 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 1024 - (480 * 2) = 64 pixels of border on the left and right side together.

Squaby different devices extended black borders

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

We can easily take care of the black borders, which I will show you in a minute. But let me just quickly mention the other possible scale modes, that we however don't recommend to use in most cases.

Other Scale Modes

zoomToBiggerSide Scale Mode

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. 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.

Squaby different devices zoomtobiggerside

Parts of our logical scene are cropped (e.g. the path on the top), the game becomes unplayable.

zoomNonUniform Scale Mode

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.

Squaby scene aspect ratios

Visual distortions by streching the original 3:2 scene non-uniformly, to 4:3 or 16:9 aspect ratios.

none Scale Mode

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.

Using letterbox Scale Mode to Cover the Whole Screen

Alright, back to our scale mode of choice. As we remember, we make the whole scene fit in the device, with possible borders on different aspect ratios.

Squaby different devices extended black borders

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 scene and thus only visible on devices that have a different aspect ratio. Keep in mind to only put graphics in the spare space that are not game-relevant, because they might not be visible on devices with different ratios!

So instead of creating a background in 3:2 ratio, rather create one to fit all the "worst-case" ratios 4:3 and 16:9 as well.

Squaby different devices extended background

Modern devices with edge-to-edge screens even have a wider ratio than 16:9. For example, the iPhone X comes with a resolution of 2436x1125 pixels for landscape mode. This results in the following sizes for background images:

Image type Unmodified 3:2 ratio size Suggested Background Size
sd 480x320 694x360
hd 960x640 1388x720
hd2 1920x1280 2776x1440

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

 import QtQuick 2.0
 import Felgo 4.0

 GameWindow {

   Scene {
     // The larger an image becomes, the more important it is to use asset selection for different resolutions!
     MultiResolutionImage {
       // Make sure to just center the image, and let its optimized source size fill the screen automatically
       anchors.centerIn: parent
       source: "https://felgo.com/web-assets/background-multi.jpg"
     }
   }
 }

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 2436:1125 ratio of iPhone X. Thus the wide iPhone X ratio is 1.443555 times bigger than the 3:2 ratio for the xScale. A multiplication of 480x1.443555 equals 692.9 which is rounded up to 693px - however, to avoid 1px off calculations e.g. at centering the minimum size is 694px. 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.

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

Felgo background template

We also prepared a small code example to inspect the aspect ratio and borders on your mobile phone:

 import QtQuick 2.0
 import Felgo 4.0

 GameWindow {

   Scene {
     id: scene
     // the scene size defaults to 480x320 or 320x480 depending on the orientation

     //fills the width of the scene and the height of the whole screen with blue
     Rectangle {
       anchors.centerIn: scene
       width: scene.width
       height: scene.gameWindowAnchorItem.height
       color: "blue"
     }
     // fills the width of the whole screen and the height of the scene with red
     Rectangle {
       anchors.centerIn: scene
       width: scene.gameWindowAnchorItem.width
       height: scene.height
       color: "red"
     }
     // fills the scene with cyan
     Rectangle {
       anchors.fill: scene
       color: "cyan"
     }
   }
 }

Optimize Your UI to Use the Available Screen Space

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 or menus 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.

Squaby anchored to scene

Squaby anchored to screen

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

Felgo offers the Scene::gameWindowAnchorItem property of the Scene to accomplish this. The following example shows how to use anchors with the gameWindowAnchorItem, to position your HUD along the screen edges.

Example of Positioning Relative to the Screen & Content Scaling by Using Felgo

The above example can be implemented with the following code in Felgo:

 import QtQuick 2.0
 import Felgo 4.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 {
     id: scene

     //width: 480
     //height: 320

     property int score: 0
     property int lives: 50

     Rectangle {
       anchors.fill: parent.gameWindowAnchorItem
       color: "white"
     }

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

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

     Rectangle {
       color: "grey"
       height: 40
       anchors {
         bottom: scene.gameWindowAnchorItem.bottom
         left: scene.gameWindowAnchorItem.left
         right: scene.gameWindowAnchorItem.right
       }
     }
   }
 }

Scene Alignment

By default, the logical scene is centered in the screen, distributing possible borders equal to the left and right, or top and bottom. However there are cases where you might want to change this, and e.g. align the scene to the bottom of the screen, having vertical borders at the top only.

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

Download Felgo now and Create Games and Apps For Any Mobile Screen Resolution.

Multi-Resolution Handling Components of Felgo

The following is a list of useful Felgo 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 Felgo 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 GameAnimatedSprite and GameSpriteSequence support using the correct Felgo 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 Felgo game:

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

Qt_Technology_Partner_RGB_475 Qt_Service_Partner_RGB_475_padded