Android Scaling For God's Sake!!!

Mehdi

Member
Hello fellow game makers,
I have read through all articles and posts related to proper scaling for different devices so far. But nothing seems to work.
I want to disable application surface (or at least disable its drawing) to gain some fps. Also I want to have letterboxing (black bars) around my screen. Is there anyone to show a way that works? For God's sake?
 

samspade

Member
Hello fellow game makers,
I have read through all articles and posts related to proper scaling for different devices so far. But nothing seems to work.
I want to disable application surface (or at least disable its drawing) to gain some fps. Also I want to have letterboxing (black bars) around my screen. Is there anyone to show a way that works? For God's sake?
Why a better description of the issues you are having would go a long way towards providing a solution, taking a shoot at it, the only way to get letter boxing is to manually draw the application surface to the screen. You can't do it with a single view as gms 2 will always scale a single view to full screen. So disable the automatic drawing of the application surface to the screen and in the post draw or draw gui event draw it yourself using the surface commands scaling how you want.

see my old post on this if for more if this is the issue you're dealing with: https://forum.yoyogames.com/index.php?threads/camera-and-view-port-size.54277/#post-330288
 
Samespade is right, you will need to draw the application surface manually. Unfortunately what your trying to do may cause some other headaches for you as well, such as the GUI. If you want to keep it in the application surface area and not get overlayed into the black bars you will need to calculate the applications surface area into the GUI. Also, keep in mind that those black bars will change size depending on the device size the user is playing it on.
 

Mehdi

Member
what exactly is your problem? your scaling isnt pixel perfect?
My problem is that whatever approach I take does not completely solve the problem of scaling on different resolutions. I have used any method found in the internet. Sometimes I feel: yeah,finally that's it! But very soon when i test on the next device resolution I get disappointed again.

Why a better description of the issues you are having would go a long way towards providing a solution, taking a shoot at it, the only way to get letter boxing is to manually draw the application surface to the screen. You can't do it with a single view as gms 2 will always scale a single view to full screen. So disable the automatic drawing of the application surface to the screen and in the post draw or draw gui event draw it yourself using the surface commands scaling how you want.

see my old post on this if for more if this is the issue you're dealing with: https://forum.yoyogames.com/index.php?threads/camera-and-view-port-size.54277/#post-330288
Exactly I do the same. I disable Application Surface drawing and manually draw it in Post Draw Event. But the main problem is the calculations. I have taken almost all the methods but the result is frustrating.

For God's sake, isn't there a single method, by which I can be sure that for any screen resolution out there, it makes the perfect scaling with those lovely black bars, without squishing, without stretching? :( Of course with application surface disabled.
 
Last edited by a moderator:
When you run your code, what is happening? Are the black bars off, or is the application surface not centered, or is it being stretched, skewed, or what exactly? The best thing you can probably do is to simply post the code you are having issues with.
 

Mehdi

Member
are you setting the views manually in the rooms??? for christssake
I use the code as said by game maker tech blog :i.e. as the game starts loop through every room and set the view ports.

When you run your code, what is happening? Are the black bars off, or is the application surface not centered, or is it being stretched, skewed, or what exactly? The best thing you can probably do is to simply post the code you are having issues with.
the black bars show correctly on the right place. But for some resolutions it gets stretched, still for others it gets squished. for some others it works correctly.

I decided to write down here the code which I use. This is what i have reached after 10 days of searching and thinking and wondering and ....
first I create a room of 16*16 size and in Room Creation Code put the following script:

application_surface_draw_enable(0);

base_w = 800;
base_h = 450;
base_aspect = base_w/base_h;

max_w = display_get_width();
max_h = display_get_height();
max_aspect = max_w/max_h;

if max_aspect >= base_aspect
{
hh = base_h;
ww = hh * base_aspect;

var size_factor = max_h/hh;
global.xoffset = abs((size_factor*ww)-max_w)/2
global.yoffset = abs((size_factor*hh)-max_h)/2;
}
else
{
ww = base_w;
hh = ww/base_aspect;
var size_factor = max_w/ww;
global.xoffset = abs((size_factor*ww)-max_w)/2
global.yoffset = abs((size_factor*hh)-max_h)/2;
}

////Looping through all rooms and setting the view ports
var _check = true;
var _rm = room_next(room);
var _rprev = _rm;

while (_check = true)
{
var _cam = room_get_camera(_rm, 0);
camera_destroy(_cam);
var _newcam = camera_create_view(0, 0, 1280, 720);
room_set_camera(_rm, 0, _newcam);
room_set_viewport(_rm, 0, true, 0, 0, 1280,720);
room_set_view_enabled(_rm, true);
if _rm = room_last
{
_check = false;
}
else
{
_rprev = _rm;
_rm = room_next(_rprev);
}
}

surface_resize(application_surface,ww*max_aspect,hh*max_aspect);

room_goto_next();
]

and then in an object which is persistent in all the rooms I draw the application surface manually:
gpu_set_blendenable(false);
draw_surface_ext(application_surface,global.xoffset,global.yoffset,1,1,0,c_white,1);
gpu_set_blendenable(true);

I hope you wont get confused. But it is the best code which did best for me. yet for resolutions such as :1280*600 , 1024*768 , 800*600
it didn't work. Just to remind you, I am creating my game for Android.

Please ,for all the holy ones' sake, ...
 
Last edited by a moderator:

Ido-f

Member
Here's my code for drawing only whole-number scaled view (x1, x2, x3), filling the rest of the screen with black bars.
Haven't used it yet in a project that's too advanced, but for now it works well.

Create:
Code:
window_set_fullscreen(true);
application_surface_draw_enable(false);
view_dimensions = [640, 360];
UpdateDisplayData();
DelayScript(id, 2, UpdateDisplayData, []);
(delay script calls UpdateDisplayData 2 steps after the create event. Needed to allow the built in variables for the game window to update after a fullscreen switch. UpdateDisplayData Is still called straight away to initialize the variables and prevent an error for the first 2 post-draw events)

UpdateDisplayData:
Code:
app_surf_scale = min(window_get_width() div view_dimensions[0], window_get_height() div view_dimensions[1]);
app_surf_dimensions = [    app_surf_scale * view_dimensions[0],
                        app_surf_scale * view_dimensions[1]    ];
app_surf_coords = [    (window_get_width() - app_surf_dimensions[0]) / 2,
                    (window_get_height() - app_surf_dimensions[1]) / 2]
app_surf_coords[@ 2] = app_surf_coords[0] + app_surf_dimensions[0];
app_surf_coords[@ 3] = app_surf_coords[1] + app_surf_dimensions[1];

surface_resize(application_surface, app_surf_dimensions[0], app_surf_dimensions[1]);

//match the gui-layer to the application surface's size and offset 
display_set_gui_size(app_surf_dimensions[0], app_surf_dimensions[1]);
display_set_gui_maximize(1, 1, app_surf_coords[0], app_surf_coords[1]);
Post-Draw :
Code:
var _as_coords = app_surf_coords;

//Black bars
draw_set_color(c_black);

    draw_rectangle(0, 0, _as_coords[2], _as_coords[1], false); //top-left
    draw_rectangle(_as_coords[2], 0, window_get_width(), _as_coords[3], false); //right-top
    draw_rectangle(_as_coords[0], _as_coords[3], _as_coords[2], window_get_height(), false); //bottom-right
    draw_rectangle(0, _as_coords[1], _as_coords[0], window_get_height(), false); //left-bottom

draw_set_color(c_white);

draw_surface(application_surface, _as_coords[0], _as_coords[1]);
 

Mehdi

Member
Here's my code for drawing only whole-number scaled view (x1, x2, x3), filling the rest of the screen with black bars.
Haven't used it yet in a project that's too advanced, but for now it works well.

Create:
Code:
window_set_fullscreen(true);
application_surface_draw_enable(false);
view_dimensions = [640, 360];
UpdateDisplayData();
DelayScript(id, 2, UpdateDisplayData, []);
(delay script calls UpdateDisplayData 2 steps after the create event. Needed to allow the built in variables for the game window to update after a fullscreen switch. UpdateDisplayData Is still called straight away to initialize the variables and prevent an error for the first 2 post-draw events)

UpdateDisplayData:
Code:
app_surf_scale = min(window_get_width() div view_dimensions[0], window_get_height() div view_dimensions[1]);
app_surf_dimensions = [    app_surf_scale * view_dimensions[0],
                        app_surf_scale * view_dimensions[1]    ];
app_surf_coords = [    (window_get_width() - app_surf_dimensions[0]) / 2,
                    (window_get_height() - app_surf_dimensions[1]) / 2]
app_surf_coords[@ 2] = app_surf_coords[0] + app_surf_dimensions[0];
app_surf_coords[@ 3] = app_surf_coords[1] + app_surf_dimensions[1];

surface_resize(application_surface, app_surf_dimensions[0], app_surf_dimensions[1]);

//match the gui-layer to the application surface's size and offset
display_set_gui_size(app_surf_dimensions[0], app_surf_dimensions[1]);
display_set_gui_maximize(1, 1, app_surf_coords[0], app_surf_coords[1]);
Post-Draw :
Code:
var _as_coords = app_surf_coords;

//Black bars
draw_set_color(c_black);

    draw_rectangle(0, 0, _as_coords[2], _as_coords[1], false); //top-left
    draw_rectangle(_as_coords[2], 0, window_get_width(), _as_coords[3], false); //right-top
    draw_rectangle(_as_coords[0], _as_coords[3], _as_coords[2], window_get_height(), false); //bottom-right
    draw_rectangle(0, _as_coords[1], _as_coords[0], window_get_height(), false); //left-bottom

draw_set_color(c_white);

draw_surface(application_surface, _as_coords[0], _as_coords[1]);
Hi , thank you for your so-professional-looking code. I tried it.Still the same problem exists: for smaller resolutions such as 800*600 , 1280*600 , 1024*768 it becomes deformed. Also when i try bigger numbers for view_dimensions it shows an error. Not the least for some resolutions the black squares take up almost half the screen.
 

Ido-f

Member
Hi , thank you for your so-professional-looking code. I tried it.Still the same problem exists: for smaller resolutions such as 800*600 , 1280*600 , 1024*768 it becomes deformed. Also when i try bigger numbers for view_dimensions it shows an error. Not the least for some resolutions the black squares take up almost half the screen.
1. Make sure to call UpdateDisplayData at a delay of at least 1 step after any window-size change. Alarms are helpful for that.

2. I noticed in your code you were setting the view in all of the rooms to be 720 wide. I don't think it's possible to fit a view into a display that has less pixels than it. That's probably the source of the error you mentioned, as even x1 size didn't fit in the window.

3. About black bars taking a lot of the screen, I think that's again because of the 720p view. The smaller the view, the better it can fit into a display. If you had a 360p view, for example, it could fit a 1080p display without blackbars. Beyond that, you can consider increasing the view size for different displays, effecting gameplay, or add something visual instead of the black bars.

Note that a 360p view doesn't have to mean 360p resolution. If the application is stretched into 1080p, sprites's subpixels when moving or rotated will actually be drawn, and you can draw a 1080p surface stretched into a 360p view, and it will still be 1080p when stretched back to the application surface.
 
Last edited:

Mehdi

Member
1. Make sure to call UpdateDisplayData at a delay of at least 1 step after any window-size change. Alarms are helpful for that.

2. I noticed in your code you were setting the view in all of the rooms to be 720 wide. I don't think it's possible to fit a view into a display that has less pixels than it. That's probably the source of the error you mentioned, as even x1 size didn't fit in the window.

3. About black bars taking a lot of the screen, I think that's again because of the 720p view. The smaller the view, the better it can fit into a display. If you had a 360p view, for example, it could fit a 1080p display without blackbars. Beyond that, you can consider increasing the view size for different displays, effecting gameplay, or add something visual instead of the black bars.

Note that a 360p view doesn't have to mean 360p resolution. If the application is stretched into 1080p, sprites's subpixels when moving or rotated will actually be drawn, and you can draw a 1080p surface stretched into a 360p view, and it will still be 1080p when stretched back to the application surface.
Thanks for your kindness.
In fact I used the your code and didn't use 720 in it. I wrote exactly what you have posted.However i think you're right. My problem have been something very ridiculous so far.
I have made the dimensions of my game beforehand and after 1 year of development, now I have started coding the scales. It is too late, since the view sizes have been set to 1280 * 720 and if i change it to something like 640*360 just a small portion of game would be visible to the player .The other way would be to try to making all the art smaller to fit, but it is so stupid right now. Therefore I have to use the already established size of 1280*720 as my base dimensions. And THIS fact had caused me so much trouble for the last 2 weeks.

Thank you again. My problem is now solved. although not the way I liked.
 
If it is at all possible I would suggest reducing the resolution of your art and game. Are you doing a pixel art style with the actual image assets scaled up? Or, do you actually have high resolution art? Your art assets should be scaled at their base size and then scaled up in game through the scaling of the application surface. If you have high resolution art though your options are somewhat limited by how detailed you want your sprites to appear. In my opinion I would do whatever possible to reduce the size of the sprites and game to be a lot smaller, specifically as small as whatever the base size you want to support is and scale up, scaling down is not recommended.

So, if you do have pixel art scaled up you can use free tools online to resize all the images quickly. However, I'm not sure how difficult it will be to put the updated art back into the game. You could replace the existing art in the game folder with the resized art, but that may not automatically update corresponding data in GM. You may need to reopen each sprite and reset it's origin and mask for example. You should also be sure to backup the game before doing any of this obviously. Apart from getting the game to fit like you want, it will also make the game run much better and more efficient. The smaller the better.
 

Mehdi

Member
If it is at all possible I would suggest reducing the resolution of your art and game. Are you doing a pixel art style with the actual image assets scaled up? Or, do you actually have high resolution art? Your art assets should be scaled at their base size and then scaled up in game through the scaling of the application surface. If you have high resolution art though your options are somewhat limited by how detailed you want your sprites to appear. In my opinion I would do whatever possible to reduce the size of the sprites and game to be a lot smaller, specifically as small as whatever the base size you want to support is and scale up, scaling down is not recommended.

So, if you do have pixel art scaled up you can use free tools online to resize all the images quickly. However, I'm not sure how difficult it will be to put the updated art back into the game. You could replace the existing art in the game folder with the resized art, but that may not automatically update corresponding data in GM. You may need to reopen each sprite and reset it's origin and mask for example. You should also be sure to backup the game before doing any of this obviously. Apart from getting the game to fit like you want, it will also make the game run much better and more efficient. The smaller the better.
You're completely right. However my game is neither pixel art, nor the details are small. Yet more sad to say we have finished 70 percent of the game. So I think there's no chance left to make big changes.:( For next project I will hold the scaling in early priority. Thanks every one.

PS: By the way is 1280*720 too large as the base size?
 
Last edited:

sylvain_l

Member
PS: By the way is 1280*720 too large as the base size?
just a note: pc 1080p is nowdays the most common ( using steam as ref https://store.steampowered.com/hwsurvey ) meaning with a 720p base your are in trouble because it's a 1.5x scaling; kinda the worst situation if you want pixel perfect scaling. (don't now for smartphone where it stands).

There is no magic "fit them all" solution that's perfect, thinking from the start on what your target audience have (stats!!! marketing isn't something you do only when the game is finished :p), what you'll compromise on too, and test early is the best way. I know you do accept to have the blackbar and play with those (but even with that it's still not that simple). Even just on pc you aren't limited to 3:4, 16:9, 16:10; there are more and more variety of native resolution (not to speak also with some screen to be rotated; and feels like even the smartphone genra of borderless with camera into the screen could be too)
 

Mehdi

Member
Thank you friend. My game is to be released for Android devices. And as far as i know 1280*720 is pretty common on mobile sets nowadays. There ARE higher resolutions of course, but lower ones are rare. And the ratio 4:3 is not very uncommon. So far I have tested my scaling code on the following resolutions:
800*600
1024*768
1280*600
1280*720
1280*768
1360*768
1366*768
1440*720
and it works fine. My only despair is the fact that I COULD set my base scales to lower dimensions at the outset of project. the numbers as small as 800*450 or ... . It could perhaps help me a lot in further optimizing my game. But ignorantly, I chose 1280*720 and made all my game around that up.
 
Top