GML Stretching the game contents down (without application_surface)

Samuel Venable

Time Killer
Hey guys.

With the following code, in the "Draw GUI" event, of a persistent, top-most object, created in the first room of your game, you can make your game contents stay the same resolution on your screen, regardless of whether the game is in fullscreen, and regardless of the window's size. Be sure to have "Full Scale" as your scaling type, under Global Game Settings (GMS1.4) / Options (GMS2.X):
Code:
var game_width, game_height;
game_width = 960; // example width ...
game_height = 540; // example height ...

display_set_gui_size(window_get_width(),window_get_height());

draw_set_color(c_black);
draw_rectangle(0,0,window_get_width(),window_get_height(),0);

draw_set_color(c_white);
draw_surface_stretched(application_surface,(window_get_width()/2)-(game_width/2),
(window_get_height()/2)-(game_height/2),game_width,game_height);
You may also need to do this in the create event, if the window is to be resizeable:
Code:
var game_width, game_height;
game_width = 960; // example width ...
game_height = 540; // example height ...

window_set_min_width(game_width);
window_set_min_height(game_height);
My question is that, is it possible to do this, or something similar, using some other method, without the application_surface enabled? I need the application_surface disabled for a game I need better performance on, (Android / OUYA game). Like first example that comes to mind is I could make a surface from the screen every step and then draw it stretched to the specified coordinates, but 1) I don't know how to do that and 2) it seems like that would run even slower. I need a way to do this that works in both GMS1.4 and GMS2.X...

Any help or suggestions are greatly appreciated.
Samuel
 
W

Wraithious

Guest
You could use a view with zoom effect, which results in everything being scaled according to the zoom amount, a typical code setup might look like:
Code:
if fullscreenon=true view_zoom=0.75;
if fullscreenon=false view_zoom=1;
view_wview=global.idlwth/view_zoom;
view_hview=global.idlht/view_zoom;
//Center on player
view_xview=global.camx-view_wview/2;
view_yview=global.camy-view_hview/2;
 

RangerX

Member
If you don't have the application surface, the only thing you can do is to stretch the game with the view port.
 
R

renex

Guest
disabling the app surface also removes the ability to letterbox the game easily, since it will stretch to fit the backbuffer.
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
If you don't have the application surface, the only thing you can do is to stretch the game with the view port.
This is exactly what you do. SImply set the view port to the size you need then adjust the view itself to match (or at least have the same aspect ratio). You'll also need to call the window_set_size function to set the window to the size of the view port as it will be set to the size of the first room in the game which may be different to what you set in code.
 

Samuel Venable

Time Killer
But here's the problem, this has been an issue from ever since the beginning of GMS (I never had this problem in GM81)

So basically, I can't set the viewport at runtime, only in the room editor's text fields, I can. If I try to do it anywhere in my GML, the code is pretty much ignored and does nothing, for example:

Code:
//This code doesn't do anything in GMS even though in GM81 it works

view_enabled = 1;
view_visible[0] = 1;
view_xporr[0]=32;
view_yport[0]=32;
view_wport[0]=window_get_width()-64;
view_hport[0]=window_get_height()-64;
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
If you do not resize the window to match the new viewport then of course it appears that nothing has happened. The viewports and the window are linked... GMS will set the game window to the correct size for the room, OR for the enabled viewports in the FIRST room of the game. If you require something else, then you need to set the view, view ports, window and applications surface yourself. They all work together. Did you even try the window_set_size function that I explained in my previous post?
 

Samuel Venable

Time Killer
window_set_size is completely irrelevent fot fullscreen games, yes? Also, I don't want to resize the window when it's in windowed mode, because in windowed mode I want it to always be 960x540.

It looks like you misread something, but I'm not sure.

I want the viewport to be the size of the window when in fullscreen, which is essentially the same as the display size, which varies from device/monitor to device/monitor. It sounds like all I have to work with is whatever is preset in the settings for the first room, which means what I'm after doesn't seem to be possible.

At least not without the application_surface...
 
Last edited:

Nocturne

Friendly Tyrant
Forum Staff
Admin
If you want the window to be 960x540 then the combined view port has to be 960x540 too... As for misreading something, well, maybe! I confess I haven't worked without the App Surface for a long time, so it may be that when it's disabled something has changed. BUT I don't think so, tbh, as the scaling method I use for my games hasn't changed since before the app surface was introduced (okay, yeah, a little to use the app surface but the fundamentals are the same). You've piqued my curiosity now, so I'm going to go play with this and see what's what. :)
 

RangerX

Member
When I wasn't having the application surface (why is it that you don't use it again?) we had a function called "windows_set_region_scale" which been deemed useless but would have been useful in this particular case.
Anyhow, what you might want to try is, when you start the game, have a "setting room" the player will never see and set the views and ports of all the other rooms with "room_set_view" function. After that you "room_go_to" your titlescreen and voila, your game starts at the right size, windowed or not.

Now if you want to have an in-game option passing from fullscreen to windowed of whatever changing the size of the game, you could try (this is untested) "room_set_view" and then use "room_reset" to apply the changes. The downside is that their will be a flash on screen because of the reset, much like when we use "display_reset".
 

Samuel Venable

Time Killer
@RangerX windows_set_region_scale no longer exists but you're right that sounds like it would've been what I could've used. Also you said "room_reset"? "room_reset" doesn't exist in GMS. I'll try out room_set_view and get back to you with my results.
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
OKay... so... this is interesting... I was being obtuse previously, and for that I apologise. What you want to do CAN be done, but not the way I was thinking it would work. :(

However, hopefully I've redeemed myself somewhat by creating for you an example file that DOES work. It uses the view_surface_id variable, and yes, it's pretty much as you suspected, you need to use a surface and draw everything to it. This was how it was done before the app surface was introduced...

http://s000.tinyupload.com/index.php?file_id=92381611008323536054

As for performance, I have to say that it's been some time since I've seen people complain of issues with the app surface on Android, and 'm not entirely sure that this would be any quicker (it is, essentially, what the app surface does anyway).

So, yeah, sorry for being silly before and I hope this helps somewhat.
 
R

renex

Guest
it's been some time since I've seen people complain of issues with the app surface on Android
I like to run my games on a specific test tablet, and while my phone can do multipass rendering with complex shaders, this specific tablet still represents a large part of the market where I live and it can't handle a single surface before dropping down below 30 fps. Their main issue being they barely have enough fill rate to update the screen once every 20 ms.
 

RangerX

Member
@RangerX windows_set_region_scale no longer exists but you're right that sounds like it would've been what I could've used. Also you said "room_reset"? "room_reset" doesn't exist in GMS. I'll try out room_set_view and get back to you with my results.
Sorry, am telling you all this from memory. The function I meant if probably "room_restart"
 
R

renex

Guest
Also to contribute to the discussion on viewports, the way I solved letterboxing without surfaces for my game on Android is that I render the entire screen then cover excess sides with black rectangles. Not the best solution but the game required a fixed screen size and this is how I solved it.

Nowadays I always go with a cleaner approach, where I have a blank room that calls all game initialization and one of the reasons for it to be a separate room is that it also contaisn the desired aspect ratio and window size I want in desktop exports, while on mobile and web exports it also probes the environment to decide the best resolution to work in then changes the viewports on the other rooms. This makes it quick and portable, with slight variations of the same init script spanning dozens of projects.
 

Samuel Venable

Time Killer
@RangerX I tried your suggestion on the Windows port of my game, and it worked great. I'm considering to scrap the idea of using F11 to toggle fullscreen.

@Nocturne Thanks for the example! (And your time)! I'll try that out after I test RangerX's idea on my OUYA, and I'll say in this topic which worked better :)

@renex Interesting ideas... As for your "cleaner" approach, you could make that a marketplace asset (a lot of people would find it useful)

Edit:

Ok so I tried both ideas and the one using room_set_view ran slower. I think it's because I'm drawing two views at once. Thanks for the help guys!
 
Last edited:
Top