Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more

Tech

Scaling For Devices: Part 2 - The Game View

Posted by Mark Alexander on 12 September 2014

In Part 1 of this tech blog, we looked at different methods to scale the GUI layer so that it can be adapted to the different screen sizes and aspect ratios of any given device. This was a relatively simple thing to do, since the GUI layer permits resizing and doesn't require views nor surfaces to work. But what about scaling the game itself? Making your game fill the whole device display is easy, but making it fill the display and look correct (ie: no blurring or stretching) is not, so in this tech blog we will cover various different methods that you can choose from to scale the game properly.

Before continuing, it is worth noting that there is no "one size fits all" solution to this problem, and a lot will depend on how your game is created and what features it uses. However we hope that the following information gives you at least the basics to be able to create your own scaling solutions without too much pain!

Initial Sizes

Before we get to the scaling part, it is worth noting that your game will be initialised to the size of the first room in your game if you are not using views, and if you are using them it will be scaled to the first view port size, or if you are using more than one view, the size of the bounding box of all views. So, if you have an initial game room that is 640x480 then all further rooms will be scaled to fit that area, and the same is true for views, with each room being squashed or stretched to fit the initial room's view port settings. The image below shows a game where the initial room was a different size to the required view port:

 

This is important to note as for this article we are assuming that the rooms (or view ports) in your game are always the same size, and in general you should always try to design your game around a fixed width and height as changing window sizes does not give a pleasant user experience and is more complex to code for.

This gives you a quick way to scale things to a different size, as you can simply create an empty first room that is 1290x720, and then all further rooms can be 256x144 and the game will be drawn at this new size automatically. The same for views. In your first room you can set the view port to a fixed size and all further rooms will be scaled to fit. However, this is far from optimal for a number of reasons, not least of which is that the application surface for each room will also be set to this larger size, which means you may be forcing the game to draw a larger surface than necessary. This method can also distort your graphics and is not really adaptable. So let's move on and see what else we can do...

Keep Aspect Ratio

As with our article on the GUI layer, for the actual game we are going to start by exploring the Keep Aspect Ratio option in the Global Game Settings. This adds black bars to "pad" the game and make it fit the display while maintaining the game's aspect ratio with respect to the device aspect ratio (if you are not familar with the term "aspect ratio", please read the previous article on scaling).

When using this option you could simply go no further and leave GameMaker: Studio to do all the work for you, but this is not the most efficient option, since GameMaker cannot decide for you how things should be done and must go with a solution that will work for most people on most platforms. So, what can we do here? Well, the main issue will be the size of the application surface (if you are not familiar with the application surface, you can find out more from the tech blog here, or from the manual).

Basically, you want to have the application surface at a 1:1 resolution with the display size, or have it scaled up to fit. Why up and not down? In general scaling up is faster for GPUs. So, for example, say your game is designed around 1024x768, and it's being played on a device with a resolution of 800x480. GameMaker. Studio will default to creating the application surface at the original size, which will then be scaled down for drawing to the display, which we don't want. We can get around this by using the following code in the room creation code:

var base_w = 1024;
var base_h = 768;
var aspect = base_w / base_h ; // get the GAME aspect ratio
if (display_get_width() < display_get_height()) { //portrait
var ww = min(base_w, display_get_width()); var hh = ww / aspect; } else { //landscape var hh = min(base_h, display_get_height()); var ww = hh * aspect; } surface_resize(application_surface, ww, hh);

Now, with aspect ratio correction on in the Global Game Settings, our application surface will be set to the correct width and height up to a maximum of 1024x768, which is our base resolution. If the display is larger than this, then we let GameMaker: Studio scale it up automatically as we don't want to resize the apllication surface to be greater than it needs to be (drawing more pixels than necessary). Note that the application surface hasn't actually been rendered yet, but you can call the resize function in the room start or create events of an instance without issues, and in the first render drame it will be the size you set.

Full Scale

Ideally you want your game to scale to use the full display dimensions on the users device, as this makes the most of the available space and gives a much better playing experience for them. However, simply checking the Full Scale option in the Global Game Settings is not enough since all it does is stretch the game to fit the screen, ignoring the aspect ratio of the device, which leads to stretched and ugly graphics, as well as possible pixel doubling if the applictaion surface is created at a higher resolution than required.

In general, all solutions to this issue will rely on the use of views to create a cropped (or expanded) view of the room, and then you will resize the application surface to be the size of the view itself. Even if your game is a series of single rooms with no views active you will need to do this, as the only other solution would be to resize your rooms dynamically to fit the screen, which would also require dynamic object placement etc... It's not impossible, and indeed for some games it may be an ideal solution, but in general the best method is simply to switch on views and let them do the scaling for you.

So, we need to do two things to get this working correctly:

  • Set up the views to adapt to the display aspect ratio.
  • Set the application surface to be the correct size required for our game, based on the view.

To do this you will need to get the aspect ratio of the BASE game size and the aspect ratio of the device screen. The base game size is the ideal height and width that you want your game to be shown at, but we are calling it the "base" size because the final width and height will actually vary depending on the device aspect ratio. Why is this? Because what we want to do is take one of the values for width and height and maintain it, while we crop or expand the other value to fit the screen.

For example, take our 1024x768 game on an 800x480 device. We will set the view height to be 768, and then multiply that by the aspect ratio of the device screen (800/480 = 1.66 = 5:3) so that our resulting width is actually (800/480) * 768 = 1280. That's an extra 128 pixels on either side of the view, and so you will have to take this into consideration when designing the game. The opposite will also be true and if our example game was run on an SXGA resolution device (1280x1024) then we would have (1280/1024) * 768 = 960, so we are losing 32 pixels from either side.

   TIP: To prevent too much extra view space being added to your game, you can set the base width and height to be less than the designed width and height. For example, our 1024x768 game could have a base width and height of 960x640. This means that the view could be cropped a little along the height, but expanded a little along the width and so the overall view area doesn't change too much, only it's proportions.

Let's have a look at some code for this:

var base_w = 1024;
var base_h = 768;
var max_w = display_get_width(); var max_h = display_get_height(); var aspect = display_get_width() / display_get_height(); if (max_w < max_h)
{ // portait
var VIEW_WIDTH = min(base_w, max_w);
var VIEW_HEIGHT = VIEW_WIDTH / aspect; } else { // landscape
var VIEW_HEIGHT = min(base_h, max_h);
var VIEW_WIDTH = VIEW_HEIGHT * aspect; } view_wview[0] = floor(VIEW_WIDTH); view_hview[0] = floor(VIEW_HEIGHT); view_wport[0] = max_w; view_hport[0] = max_h; surface_resize(application_surface, view_wview[0], view_hview[0]);

If you've folowed this and the previous tech blog fully, then you'll notice that this code is pretty much the same as we used when we kept the aspect ratio in the GGS and when we set the GUI aspect ratio, only now we have expanded it a bit to set the views for the game. The view size is set to maintain the aspect ratio and the view port is set to the display size, and then finally the application surface is resized to get a 1:1 ratio with what is drawn (it will be stretched to fit the view port automatically, always scaling up).

Summary

As you can see, scaling your game is completly dependant on the aspect ratio of the device being used, and there is no way you can make a "one-size-fits-all" solution, due to the fragmented state of device screens (especially on Android). This scaling solution gives a "best fit", and can easily be adpated to suit your own base game resolution. Note that you can call this code in a script so that you can simply call the script at the start of each room. You can even add a final piece of code to have this automatically set all the views in all your rooms, so that you only need to call it once at the start of the game:

var i = true;
var rm = room_next(room);

while (i)
{
room_set_view(rm, 0, true, 0, 0, view_wview[0], view_hview[0], 0, 0, view_wport[0], view_hport[0], 0, 0, -1, -1, -1);
room_set_view_enabled(rm,true);
if (rm == room_last)
    {
    i = false;
    }
else
    {
    rm = room_next(rm);
    }
}

Hopefully this tech blog has cleared up a bit of the mystery behind scaling for mobile devices and enables you to get your games looking as they were designed on all platforms!

 

 

Back to Top