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

Tech

Scaling For HTML5

Posted by Mark Alexander on 19 September 2014

After the previous two tech blogs about scaling for devices, there have been a few requests for an extra article on how to scale games for the HTML5 target. So, in this tech blog we are going to cover scaling for this platform, although it should be noted that before continuing we recommend that you read through the Scaling For Devices tech blogs (Part 1, and Part 2) as we will be using the techniques that have previously been explained there in more depth.

When scaling your game on the HTML5 and JS targets, it is important to realise that there are some fundamental differences between these targets and the desktop/device targets. The game window is now the canvas element of the page, and the display becomes the browser. This tech blog will take you through three steps to show how to scale a single room to a required size, how to scale a room that uses views to a required size, and finally how to scale a room with views to fill the browser window.

NOTE: For this tutorial, you should have the Global Game Settings set to not be centered (since we will do that in out code), and the scaling option should be set to full scale since we will be dealing with aspect ratio as well.

Scaling A Single Room

Scaling the game canvas to the browser is actually very simple and can be done with a single short script. The only complication is that the browser can be resized to be taller than it is wider (unlike the average desktop PC display) at any time and this possibility has to be taken into account. So to start with you will need some controller object that is placed in your room, and it should have a Create Event with the following:

base_width = room_width;
base_height = room_height;
width = base_width;
height = base_height;

The base width and height variables are the base values that we want our canvas element to be set to (as we did in the previous tech blogs), and in this case it's the room width and height (note that you could make the base width and height as Macros, which means that they will be highlighted in the script editor and also compile faster). We also need two extra variables that will be used to detect when the browser width changes. We initialise these to the size of the game room as the code you will add next will then set them to the correct size for the current browser state.

We are going to make the following code a script as unlike previous scaling options, we will be re-using this one if the player re-sizes their canvas, so you should create a script and call it scale_canvas() or something and add the following:

/// scale_canvas(base width, base height, current width, current height, center);
//argument0 = base width;
//argument1 = base height;
//argument2 = current width
//argument3 = current height
//argument4 = center window (true, false);

var aspect = (argument0 / argument1);

if ((argument2 / aspect) > argument3)
    {
    window_set_size((argument3 * aspect), argument3);
    }
else
    {
    window_set_size(argument2, (argument2 / aspect));
    }

if (argument4) window_center();

surface_resize(application_surface, min(window_get_width(), argument0), min(window_get_height(), argument1));

As you can see from this code, we are geting the base aspect ratio and then using that to scale the window (the game canvas). We also scale the application surface to fit, much like we do for devices. Now, when you run your game, no matter what the user sets their browser size to be, the game will be scaled to a "best fit" along the horizontal or vertical axis.

NOTE: You can see that there is an argument to center the game window. This is optional, and it's only included here to show that it is possible to position the canvas within the browser using this function (the other windows position functions will work too). You should be aware however that these functions will do nothing on the other JS targets. 

So, we have our script, now what to do with it? We need to call it in the Step Event so that it is checked and run every time the browser window changes size, so to do that we would use something like this:

if (browser_width != width || browser_height != height)
    {
    width = min(base_width, browser_width);
    height = min(base_height, browser_height);
    scale_canvas(base_width, base_height, width, height, true);
    }

You could even use the median() function instead of the min() function to set a minimum and maximum scale for the game canvas. Play around with different values here in this object and for the room size, then test the game while dragging the browser edges to different sizes to see how all this works together.

NOTE: This object will work perfectly fine on the Windows 8 (JS) target platform to scale the canvas, however, instead of using the Step Event to control scaling, you should simply call it from the special Resize sub-event that you can find in the Draw event category of the object. This will be triggered whenever the game window is "snapped" in the Windows 8 interface.

Scaling With Views

We have seen that it is a simple procedure to scale the game canvas to the browser width and height, so that no matter how the user resizes the browser, the game room will still be visible. However, what about when using views? Assuming that you are only using one view, this is a relatively simple thing to deal with, and you can build on top of the code previously given for scaling the room.

To start with we would need to change the create event code slightly to look like this:

base_width = 640;
base_height = 480;
width = base_width;
height = base_height;

Here the base width is now set to the size of the view (as set in the room editor, in this case it's 640x480). We can then use the room scaling code given above in the step event as normal for setting the window size, and to get the correct view port size, we add a little extra into the scaling script so it now looks like this:

/// scale_canvas(base width, base height, current width, current height, center);
//argument0 = base width; //argument1 = base height; //argument2 = current width //argument3 = current height //argument4 = center window (true, false); var aspect = argument0 / argument1; if ((argument2 / aspect) > argument3) { window_set_size((argument3 * aspect), argument3); } else { window_set_size(argument2, (argument2 / aspect)); } if (argument4) window_center();
view_wport[0] = window_get_width(); view_hport[0] = window_get_height();

surface_resize(application_surface, min(window_get_width(), argument0), min(window_get_height(), argument1));

That about covers all you need to know for scaling the game canvas to a fixed size, with or without views. However that is not the end of our article as we have one final scaling trick up our sleeves for HTML5... Scaling the game to fit the full browser window!

Fullscreen Scaling

This final section of the tech blog dedicated to the HTML5 target covers one further way to scale the game canvas... Fullscreen! Now, you cannot set fullscreen mode directly through GameMaker:Studio as this is browser dependant and requires implicit user input. However you can scale the canvas to fill the browser, and so simulate a fullscreen.

Before getting started it's important to realise that the minimum view width and height cannot be fixed like they were previously. All we can do is set a value whereby the view will not get any smaller, but start to be cropped. Think about it like this... the browser can be stretched to fit any proportion from a very narrow rectangle to a perfect square, and so we have to take this into account and create a "best fit".

To get this working correctly, we have to choose a single value that will be the minimum width or height that the view will be scaled to. To see why, take a look at this diagram:

To set this up requires another  script, which we'll call canvas_fullscreen(). As you will see, it's remarkably similar to previous scripts in that it is all down to the aspect ratio that we use. However, for this we need the aspect ratio of the browser, as that is what will determine whether the view is scaled to the base size along its width or its height. The necessary code to add to the script is:

/// canvas_fullscreen(base, browser_width, browser_height)
// argument0 = base value for scaling
// argument1 = the current browser width
// argument2 = the current browser height

view_wport[0] = argument1;
view_hport[0] = argument2;

window_set_size(argument1, argument2);
window_center();

var aspect = (argument1 / argument2);
if (aspect < 1)
    {
    view_hview[0] = argument0;
    view_wview[0] = (argument0 * aspect);
    }
else
    {
    view_hview[0] = (argument0 / aspect);
    view_wview[0] = argument0;
    }

surface_resize(application_surface, view_wview[0], view_hview[0]);

The argument0 here will be the base size that we set for either the horizontal or vertical axis, and to use the script we'd have a Create Event like this:

base_size = 512;
width = browser_width;
height = browser_height;
canvas_fullscreen(base_size, width, height);

And then in the Step Event:

if (browser_width != width || browser_height != height)
    {
    width = browser_width;
    height = browser_height;
    canvas_fullscreen(base_size, width, height);
    }

And that's about it! With these codes your game will occupy the full browser width and height, cropping and scaling to suit the the current aspect ratio of the browser itself. If you'd like to see how all this hangs together, you can download a test app here.

Back to Top