GML Advanced resolution manager (very mobile friendly)

gkri

Member
I wrote this (hopefully) handy script and I would love to share it with this wonderful community.

The scripts has two primary uses:
  • To help developers handling multi-resolution easier.
  • To offer to mobile developers a couple of quality of life features.
This script is heavily based on the Resolution and Aspect Ratio Management for Game Maker tutorial series by @Pixelated_Pope. Thank you @Pixelated_Pope! And no need to mention that It is absolutely free (MIT License)!


What the script does and how to use it

The script accepts 4 mandatory and 2 optional arguments (total of 6):

Code:
set_resolution (design_value, is_design_vertical, is_orientation_vertical, resize_all_rooms, scale (optional), overide_other_value (optional))
  • @arg design_value (real) One of the most important decisions must be taken, is the ideal resolution of the game. The first argument is very flexible; you can pass either the width or the height of your ideal resolution the remaining one will be calculated by the script.
  • @arg is_design_value_vertical (boolean) Here you specify if the first argument is referring to width (false) or height (true) of your ideal resolution.
  • @arg is_orientation_vertical (boolean) Here you specify if the orientation of the game is landscape (false) or portrait (true). The most obvious reason to set it as true, is for mobile games but I suppose it could be useful to html5 games with unique design or ported from mobile platforms.
  • @resize_all_rooms (boolean) It will resize all rooms except the 0 indexed one, to the resulted resolution from the previous arguments, if true. Some games have fixed room dimensions (eg break out clones, card games) while others not (rpgs, platformers); pass true or false accordingly.
  • @arg scale (real) Optional argument. Nowadays most mobile devices have bigger screen resolution than a desktop or laptop screen. This may be inconvenient, especially if the mobile game that is being developed has portrait orientation. You can pass a custom scale to fit the game window within your monitor. The scale only effects builds on os_windows and os_macosx (usually you build Test->VM on them) and is ignored on device or emulator builds.
  • @arg overide_other_value (real) Optional argument. You can pass the other ideal dimension than the one you passed on first argument to make a customized screen ratio for a quick sneak peek without using real device or emulator. If you passed the ideal width on first argument, you can pass a height value here and vice versa. Like scale argument, it will ignored on device or emulator builds.

The most common place to call the script, should be inside your init room, which should be on top of the room list. Unless you want to change the resolution again inside the game, you will not need to call this script again. When the script is executed, it will store its results to the global variables:
Code:
global.ideal_width
global.ideal_height

Here is a quick example of how to use those values:

Code:
//Room Start Event

view_enabled = true;
view_visible[0] = true;
view_wport[0] = global.ideal_width;
view_hport[0] = global.ideal_height;
camera_set_view_size(view_camera[0], view_wport[0], view_hport[0]);


(I might upload a demo project If I see some demand)



The source code of the script (GMS2.2)

GML:
///@func set_resolution(design_value, is_design_vertical, is_orientation_vertical, resize_all_rooms, scale (optional), overide_other_value (optional))
///@arg design_value - real - Width or height of ideal resolution
///@arg is_design_value_vertical  - boolean -  When true, the design_value is condidered as height; when false, as width
///@arg is_orientation_vertical - boolean -  When true, the screen orientation is considered as portrait; when false, as landscape
///@arg resize_all_rooms - boolean - When true: Rooms (except room index 0), will be resized to resulting value
///@arg scale(optional) - real - (Optional) Scale the game window to better fit the monitor. Will ommited on any non windows and non macos builds
///@arg overide_other_value(optional) - real - (Optional) Overides the value other than the design_value arg for a custom aspect ratio. Will ommited like scale arg

///Written by George Kritikos (Harpwood studio) - Based on code written by Pixelated_Pope
///@License MIT License https://opensource.org/licenses/MIT


// arguments evaluation
if argument_count < 4 or argument_count > 6 then show_error("Error set_resolution script: Incorect number of arguments. Expected number of arguments are minimum of 4 to maximum of 6.", true);

var _arg = [];

for (var i = 0; i < 6; i++;)
{
    if argument_count > i then _arg[i] = argument[i] else _arg[i] = undefined;
}


// assigning _arg[] values for readability
var _design_value = _arg[0];
var _is_design_value_vertical = _arg[1];
var _is_orientation_vertical = _arg[2];
var _resize_all_rooms = _arg[3];
var _scale = _arg[4] == undefined ? 1 : _arg[4]; // default scale = 1
var _overide_other_value  = _arg[5];

//detect os_type only if is GMS2 IDE approprate
_os_type = os_type == os_windows ? os_windows : os_macosx;

// The design value is either the design width or height. Every calculation in build with Test -> VM get a temporary scaling
var _desing_width = os_type == _os_type ? _design_value * _scale : _design_value;
var _desing_height = os_type == _os_type ? _design_value * _scale : _design_value;

var _real_width, _real_height, _aspect_ratio, _ideal_width, _ideal_height;

if _is_orientation_vertical
{
    //dirty way to get portait orientation for os_windows/os_macosx
    _real_width = os_type == _os_type ? display_get_height()  * _scale : display_get_width();
    _real_height = os_type == _os_type ? display_get_width()    * _scale : display_get_height();
    _aspect_ratio  = _real_width >= _real_height ? _real_height / _real_width : _real_width / _real_height;

    if _is_design_value_vertical    //The design value is reffering to vertical so we calculate the horizontal
    {
        _ideal_height = _desing_height;
        if os_type == _os_type then _ideal_width = _overide_other_value == undefined ? round(_ideal_height * _aspect_ratio) : _overide_other_value * _scale;
        else _ideal_width = round(_ideal_height * _aspect_ratio);
    }
    else                            //and vice versa
    {
        _ideal_width = _desing_width;
        if os_type == _os_type then _ideal_height = _overide_other_value == undefined ? round(_ideal_width / _aspect_ratio) : _overide_other_value * _scale;
        else _ideal_height = round(_ideal_width / _aspect_ratio);
    }

}
else
{
    _real_width = os_type == _os_type ? display_get_width()  * _scale : display_get_width();
    _real_height = os_type == _os_type ? display_get_height() * _scale : display_get_height();
    _aspect_ratio = _real_width >= _real_height ? _real_height / _real_width : _real_width / _real_height;


    if _is_design_value_vertical    //The design value is reffering to vertical so we calculate the horizontal
    {
        _ideal_height = _desing_height;
        if os_type == _os_type then _ideal_width = _overide_other_value == undefined ?  round(_ideal_height / _aspect_ratio) : _overide_other_value * _scale;
        else _ideal_width =  round(_ideal_height / _aspect_ratio);
    }
    else                            //and vice versa
    {
        _ideal_width = _desing_width;
        if os_type == _os_type then _ideal_height = _overide_other_value == undefined ? round(_ideal_width * _aspect_ratio) : _overide_other_value * _scale;
        else _ideal_height = round(_ideal_width * _aspect_ratio);
    }
}

//make the results more pixel perfect friendly
if _ideal_width & 1 then _ideal_width++;
if _ideal_height & 1 then _ideal_height++;

if _resize_all_rooms //apply resolution results to all rooms?
{
    for (var i = 1; i < room_last; i++) //all rooms except room with index 0, which usually is the init room
    {
        if room_exists(i)
        {
            room_set_width(i, _ideal_width);
            room_set_height(i, _ideal_height);
        }
    }
}

application_surface_enable(false);  // false as default behaviour
window_set_size(_ideal_width, _ideal_height);
surface_resize(application_surface, _real_width, _real_height);

//remove the temporary scaling if building with Test -> VM and apply results in global vars for further use
global.ideal_width = os_type == _os_type ? _ideal_width / _scale : _ideal_width;
global.ideal_height = os_type == _os_type ? _ideal_height / _scale : _ideal_height;



To make the script compatible with GMS2.3:

Code:
function set_resolution()
{

    [PASTE THE GMS2.2 SOURCE CODE HERE]

}
EDIT : Added GMS2.3 version of the script

GML:
function set_resolution(_design_value, _is_design_value_vertical, _is_orientation_vertical, _resize_all_rooms, _scale, _overide_other_value) {
///@func set_resolution(design_value, is_design_vertical, is_orientation_vertical, resize_all_rooms, [scale], overide_other_value [optional])
///@arg _design_value                  real        width or height of ideal resolution
///@arg _is_design_value_vertical      boolean    When true, the design_value is condidered as height; when false, as width
///@arg _is_orientation_vertical      boolean    When true, the screen orientation is considered as portrait; when false, as landscape
///@arg _resize_all_rooms              boolean    When true: Rooms (except room index 0), will be resized to resulting value
///@arg _scale(optional)              real        (Optional) Scale the game window to better fit the monitor. Will ommited on any non windows and non macos builds
///@arg _overide_other_value(optional) real        (Optional) Overides the value other than the design_value arg for a custom aspect ratio. Will ommited like scale arg

    ///Written by George Kritikos (Harpwood studio) - Based on code written by Pixelated_Pope
    ///@License MIT License https://opensource.org/licenses/MIT
   
    //arguments evaluation
    if _design_value == undefined or _is_design_value_vertical == undefined or _is_orientation_vertical == undefined or _resize_all_rooms == undefined
    then show_error("Error set_resolution script: Incorect number of arguments. Expected number of arguments are minimum of 4 to maximum of 6.", true);
   
    if 0 then return argument[0]; //A workaround to avoid warnings if you do not pass the optional arguments
   
    if _scale == undefined then _scale = 1;
   
    //detect os_type only if is GMS2 IDE approprate
    _os_type = os_type == os_windows ? os_windows : os_macosx;

    // The design value is either the design width or height. Every calculation in build with Test -> VM get a temporary scaling
    var _desing_width    = os_type == _os_type ? _design_value * _scale : _design_value;
    var _desing_height    = os_type == _os_type ? _design_value * _scale : _design_value;

    var _real_width, _real_height, _aspect_ratio, _ideal_width, _ideal_height;

    if _is_orientation_vertical
    {
        //dirty way to get portait orientation for os_windows/os_macosx
        _real_width        = os_type == _os_type ? display_get_height()  * _scale : display_get_width();
        _real_height    = os_type == _os_type ? display_get_width()    * _scale : display_get_height();
        _aspect_ratio    = _real_width >= _real_height ? _real_height / _real_width : _real_width / _real_height;
   
        if _is_design_value_vertical    //The design value is reffering to vertical so we calculate the horizontal
        {
            _ideal_height = _desing_height;
            if os_type == _os_type then _ideal_width = _overide_other_value == undefined ? round(_ideal_height * _aspect_ratio) : _overide_other_value * _scale;
            else _ideal_width = round(_ideal_height * _aspect_ratio);
        }
        else                            //and vice versa
        {
            _ideal_width = _desing_width;
            if os_type == _os_type then _ideal_height = _overide_other_value == undefined ? round(_ideal_width / _aspect_ratio) : _overide_other_value * _scale;
            else _ideal_height = round(_ideal_width / _aspect_ratio);
        }
   
    }
    else
    {
        _real_width        = os_type == _os_type ? display_get_width()  * _scale : display_get_width();
        _real_height    = os_type == _os_type ? display_get_height() * _scale : display_get_height();
        _aspect_ratio    = _real_width >= _real_height ? _real_height / _real_width : _real_width / _real_height;
   
   
        if _is_design_value_vertical    //The design value is reffering to vertical so we calculate the horizontal
        {
            _ideal_height = _desing_height;
            if os_type == _os_type then _ideal_width = _overide_other_value == undefined ?  round(_ideal_height / _aspect_ratio) : _overide_other_value * _scale;
            else _ideal_width =  round(_ideal_height / _aspect_ratio);
        }
        else                            //and vice versa
        {
            _ideal_width = _desing_width;
            if os_type == _os_type then _ideal_height = _overide_other_value == undefined ? round(_ideal_width * _aspect_ratio) : _overide_other_value * _scale;
            else _ideal_height = round(_ideal_width * _aspect_ratio);
        }
    }
   
    //make the results more pixel perfect friendly
    if _ideal_width & 1 then _ideal_width++;
    if _ideal_height & 1 then _ideal_height++;

    if _resize_all_rooms //apply resolution results to all rooms?
    {
        for (var i = 1; i < room_last; i++) //all rooms except room with index 0, which usually is the init room
        {
            if room_exists(i)
            {
                room_set_width(i, _ideal_width);
                room_set_height(i, _ideal_height);
            }
        }
    }

    application_surface_enable(false);  // false as default behaviour
    window_set_size(_ideal_width, _ideal_height);
    surface_resize(application_surface, _real_width, _real_height);

    //remove the temporary scaling if building with Test -> VM and apply results in global vars for further use
    global.ideal_width = os_type == _os_type ? _ideal_width / _scale : _ideal_width;
    global.ideal_height = os_type == _os_type ? _ideal_height / _scale : _ideal_height;

   
}


What's the catch?

I have tested the script with any way I could come up with. As long as the values I pass are appropriate for the assets I am using everything looks fine. I have even used an early version of this script in production without any problems. But I am just a culinary chef and I am developing games and animation as a hobbyist. My coding experience is limited to about 2-2 1/2 years. Soooo do not trust my coding skills (I wouldn't trust my coding skills). Maybe my inexperience is tricking me and the script is nothing more than a few worthless lines of code. So I need your help. If you are willing to help me, take the script and test the s**t out of it, even improve it, or adapt it to your needs and if you want post your improved code here and I will credit you. Or help me by giving feedback or reporting bugs. Please help me foolproof it.



Thank you for you time

George Kritikos
 
Last edited:

gkri

Member
Updated the script to be more pixel perfect friendly.
Added:
GML:
//make the results more pixel perfect friendly
if _ideal_width & 1 then _ideal_width++;
if _ideal_height & 1 then _ideal_height++;
 

gkri

Member
EDIT : Added GMS2.3 version of the script

GML:
function set_resolution(_design_value, _is_design_value_vertical, _is_orientation_vertical, _resize_all_rooms, _scale, _overide_other_value) {
///@func set_resolution(design_value, is_design_vertical, is_orientation_vertical, resize_all_rooms, [scale], overide_other_value [optional])
///@arg _design_value                  real        width or height of ideal resolution
///@arg _is_design_value_vertical      boolean    When true, the design_value is condidered as height; when false, as width
///@arg _is_orientation_vertical      boolean    When true, the screen orientation is considered as portrait; when false, as landscape
///@arg _resize_all_rooms              boolean    When true: Rooms (except room index 0), will be resized to resulting value
///@arg _scale(optional)              real        (Optional) Scale the game window to better fit the monitor. Will ommited on any non windows and non macos builds
///@arg _overide_other_value(optional) real        (Optional) Overides the value other than the design_value arg for a custom aspect ratio. Will ommited like scale arg

    ///Written by George Kritikos (Harpwood studio) - Based on code written by Pixelated_Pope
    ///@License MIT License https://opensource.org/licenses/MIT
   
    //arguments evaluation
    if _design_value == undefined or _is_design_value_vertical == undefined or _is_orientation_vertical == undefined or _resize_all_rooms == undefined
    then show_error("Error set_resolution script: Incorect number of arguments. Expected number of arguments are minimum of 4 to maximum of 6.", true);
   
    if 0 then return argument[0]; //A workaround to avoid warnings if you do not pass the optional arguments
   
    if _scale == undefined then _scale = 1;
   
    //detect os_type only if is GMS2 IDE approprate
    _os_type = os_type == os_windows ? os_windows : os_macosx;

    // The design value is either the design width or height. Every calculation in build with Test -> VM get a temporary scaling
    var _desing_width    = os_type == _os_type ? _design_value * _scale : _design_value;
    var _desing_height    = os_type == _os_type ? _design_value * _scale : _design_value;

    var _real_width, _real_height, _aspect_ratio, _ideal_width, _ideal_height;

    if _is_orientation_vertical
    {
        //dirty way to get portait orientation for os_windows/os_macosx
        _real_width        = os_type == _os_type ? display_get_height()  * _scale : display_get_width();
        _real_height    = os_type == _os_type ? display_get_width()    * _scale : display_get_height();
        _aspect_ratio    = _real_width >= _real_height ? _real_height / _real_width : _real_width / _real_height;
   
        if _is_design_value_vertical    //The design value is reffering to vertical so we calculate the horizontal
        {
            _ideal_height = _desing_height;
            if os_type == _os_type then _ideal_width = _overide_other_value == undefined ? round(_ideal_height * _aspect_ratio) : _overide_other_value * _scale;
            else _ideal_width = round(_ideal_height * _aspect_ratio);
        }
        else                            //and vice versa
        {
            _ideal_width = _desing_width;
            if os_type == _os_type then _ideal_height = _overide_other_value == undefined ? round(_ideal_width / _aspect_ratio) : _overide_other_value * _scale;
            else _ideal_height = round(_ideal_width / _aspect_ratio);
        }
   
    }
    else
    {
        _real_width        = os_type == _os_type ? display_get_width()  * _scale : display_get_width();
        _real_height    = os_type == _os_type ? display_get_height() * _scale : display_get_height();
        _aspect_ratio    = _real_width >= _real_height ? _real_height / _real_width : _real_width / _real_height;
   
   
        if _is_design_value_vertical    //The design value is reffering to vertical so we calculate the horizontal
        {
            _ideal_height = _desing_height;
            if os_type == _os_type then _ideal_width = _overide_other_value == undefined ?  round(_ideal_height / _aspect_ratio) : _overide_other_value * _scale;
            else _ideal_width =  round(_ideal_height / _aspect_ratio);
        }
        else                            //and vice versa
        {
            _ideal_width = _desing_width;
            if os_type == _os_type then _ideal_height = _overide_other_value == undefined ? round(_ideal_width * _aspect_ratio) : _overide_other_value * _scale;
            else _ideal_height = round(_ideal_width * _aspect_ratio);
        }
    }
   
    //make the results more pixel perfect friendly
    if _ideal_width & 1 then _ideal_width++;
    if _ideal_height & 1 then _ideal_height++;

    if _resize_all_rooms //apply resolution results to all rooms?
    {
        for (var i = 1; i < room_last; i++) //all rooms except room with index 0, which usually is the init room
        {
            if room_exists(i)
            {
                room_set_width(i, _ideal_width);
                room_set_height(i, _ideal_height);
            }
        }
    }

    application_surface_enable(false);  // false as default behaviour
    window_set_size(_ideal_width, _ideal_height);
    surface_resize(application_surface, _real_width, _real_height);

    //remove the temporary scaling if building with Test -> VM and apply results in global vars for further use
    global.ideal_width = os_type == _os_type ? _ideal_width / _scale : _ideal_width;
    global.ideal_height = os_type == _os_type ? _ideal_height / _scale : _ideal_height;

   
}
 
Top