When developing games for mobile devices the first challenge you will encounter is the difference in screen resolutions. You will want to use the full screen on your device, while maintaining correct aspect ratios.

There are many ways to solve this, in this blog post I will present a simple one. One that works for games that do not use views. One that does not go into depth on camera views etc.

First let’s look at what happens when you set your game to Full Screen.

Gamemaker will size the width and height of your room to match the width and height of your device.

If, for example, your device has a resolution of 1440×900 (like the Samsung Galaxy Tab A 2016), Gamemaker will stretch/shrink the width and height of your room to match this. When you want to get the screen width and height in Gamemaker, it will return the device width and height: 1440×900. This will always be the case, no matter what size your room is, and no matter how you try to retrieve is. So:

display_get_gui_width() will return 1440
display_get_gui_height(
) will return 900

And also:

display_get_width() will return 1440
display_get_height() will return 900

When designing your game, you will have to choose a resolution to work with. E.g. 900 x 600. To do so, make your room dimensions 900 x 600.

Now what happens? The width of the device is divided into 900 pixels, the height of the device is divided into 600 pixels. Even when your device has a completely different resolution. With our example of a device with a resolution of 1440 x 900 that means:

The width of 900 in GameMaker = 1440 in reality. So one (1) pixel in gamemaker = 1.6 pixels on your device horizontally.

The height of 600 in GameMaker = 900 in reality, so one pixel in gamemaker = 1.5 pixels on your device vertically.

If you have a sprite of a perfect square of 100×100, that square will look perfect on a device with the same (900×600) resolution. In our example device it will have the following dimensions:

width: 100×1.6 = 160
height: 100×1.5 = 150

So the prefect square wil be 160 x 150 on your device: it is no longer a perfect square, it is a rectangle.

a square will be resized to a rectangle

How to solve this?

In your code you must apply a correction factor. To find that factor, you need to know the difference between the horizontal and vertical ratios.

In our example the horizontal ratio is 1.6, the vertical is 1.5.

You will want to multiply the height of your objects in such way that the 1.5 becomes 1.6.

To get this factor, use the following formula:

designWidth = 900; (your design width and height)
designHeight = 600;

factor_height =
(display_get_width()/designWidth) /  (display_get_height()/designHeigh
t);

So factor_height will be (1440/900) / (900/600) = 1.067

To make your square perfect again, you will need to multiply the height by 1.067. You can do this by setting the image_yscale property.

The way I do this: at the start of the game I calculate the height_factor.

Next, I make a parent object that sets the image_yscale to this factor. All objects in the game inherit from this parent object.

A new game build in GameMaker Studio 2

Square This! is both relaxing as well as challenging. There is no time pressure. You can sit back, relax, and solve the puzzles. The game has many levels. Solving a puzzle unlocks a new one. The goal is to swap tiles in a logical order. To unlock a new level the puzzle needs to be solved in a maximum number of turns. Enjoy tapping tiles, enjoy solving the puzzles, enjoy playing this game!

“Square This!” is now available on Google Play.

Get it on Google Play

Google Play and the Google Play logo are trademarks of Google LLC.

Code snippet for saving a key-value pair in gamemaker. Data is saved in the file data.dat. Works for all platforms.

Saving:

mKey="myKey";
mValue="myValue";
mMap = ds_map_secure_load("data.dat");
if (mMap==-1){
   mMap=ds_map_create();
} 

if (!ds_map_exists(mMap, mKey)){
   // add the key-value 
   ds_map_add(mMap, mKey, mValue);
} else {
   // replace the value for the key
   ds_map_replace(mMap, mKey, mValue);
}

ds_map_secure_save(mMap, "data.dat");
ds_map_destroy(mMap);

Loading:

mKey="myKey";
mValue="default value";

mMap = ds_map_secure_load("data.dat"); 
if (mMap==-1){
mMap=ds_map_create();
}
if (ds_map_exists(mMap, key)){ mValue=ds_map_find_value(mMap, key); } ds_map_destroy(mMap);