GameMaker How to make Fixed Scale (100%) Full Screen switching on Windows?

F

FB-Productions

Guest
Hello everyone,

I have been having some problems achieving a certain Full Screen look in Game Maker Studio 2.
The look I am trying to achieve when Full Screening my game is called FIXED Scale on 100% (NOT Full Scale!).
This was an option available in the Graphics tab of the Global Game Settings in legacy Game Maker versions (like 8.1), but was removed since the release of Studio 1.
What it basically does is it makes the game's size remain the same as Windowed Mode, while the game is in Full Screen, which makes the rest of the screen have a black colour as it is not needed.
So if a Game/Window/View size is, for example, 800x600, then every display would show the pixels crispy clear in Full Screen, like an immobile borderless window of a size 800x600 was centered on a black canvas that is the size of the full display (completely stretched out).
You can also check the images below to see the differences that I mean:
gmc2_fixedscale.pnggmc2_normalstretchfull.png gmc2_windowed.png

So, up to this point, I have made my whole game look the way it should in Fixed Scale.
Also, instead of just a solid colour (black) background, I added sprites and some other stuff to make the unplayable/unused canvas in Fixed Scale full screen look better.
And have also done what I wanted to make the game switchable from Fixed Full Screen to Normal Stretch Fullscreen to Windowed Mode.

However, even though the game looked well drawn in Fixed Scale Full Screen, it still acted as though the whole view was stretched to the edges of the screen/display.
So, for example, all the buttons on the screen weren't clickable as intended, because their masks were stretched and repositioned as though the game was still in Normal Full Screen mode.
This is the part I could not fix - the part I need help with!

CODE:

I am using Game Maker Studio 2 (version: IDE 2.2.2.413, Runtime 2.2.2.326) on Windows 7 (SP1).
I have a persistent object added in the initialization room called obj_fullscale which has the following code:

Create Event:

Code:
full_scale = 0; //The FIXED scale boolean variable (accidentally named it full_scale in my project - sorry)
//This variable exists so that when the game is in Full Screen, it can always be changed between Fixed Scale and Normal Stretch Full Screens
End Step Event:
Code:
if (window_get_fullscreen() == 1) //If the game is set to Full Screen
{
   if ((display_get_width()/1280) > 1) //The game's room/view size is 1280x720, so the FIXED scale full screen is on if the display width is larger than 1280
   {
       full_scale = 1;
   }
   else //Otherwise normal full screen stretching is used
   {
       full_scale = 0;
   }
}
else //If the game is in Windowed Mode
{
   full_scale = 0;
  
   //This just checks the display size and makes the window smaller if needed.
   //This causes no problems as far as I know, but I included it anyways.
   if ((display_get_width()) < 960)
   {
       //Write an error to the game errors log and abort the game
       scr_error("Your screen resolution is lower than the smallest allowed window size of 960x540. You cannot play this game with a resolution that small.");
       game_end();
       exit;
   }
   else if ((display_get_width()) <= 1024)
   {
       window_set_size(960,540);
   }
   else if ((display_get_width()) <= 1152)
   {
       window_set_size(1024,576);
   }
   else if ((display_get_width()) <= 1280)
   {
       window_set_size(1152,648);
   }
   else
   {
       window_set_size(1280,720);
   }
}
Post-Draw Event:
Code:
//DRAWING THE APPLICATION SURFACE IF THE GAME IS IN FIXED SCALE MODE ON FULL SCREEN
if (full_scale == 1) //If we are using FIXED SCALE
{
   //This big part before the manual drawing of the application surface is the background and decoration that covers the display parts that are unused
   draw_set_colour(c_black);
   draw_set_alpha(1);
   draw_rectangle(0,0,display_get_width(),display_get_height(),0);
   draw_set_colour(c_white);
   draw_sprite_tiled(bg_menu_gray_big,0,0,0);
   draw_sprite_stretched(bg_menu_shade,0,0,0,display_get_width(),display_get_height());
   draw_set_colour(c_black);
   draw_set_alpha(0.1);
   draw_roundrect_ext((display_get_width() div 2) - (surface_get_width(application_surface) div 2) - 44, (display_get_height() div 2) - (surface_get_height(application_surface) div 2) - 24, (display_get_width() div 2) + (surface_get_width(application_surface) div 2) + 44, (display_get_height() div 2) + (surface_get_height(application_surface) div 2) + 24, 32, 32, 0);
   draw_roundrect_ext((display_get_width() div 2) - (surface_get_width(application_surface) div 2) - 40, (display_get_height() div 2) - (surface_get_height(application_surface) div 2) - 22, (display_get_width() div 2) + (surface_get_width(application_surface) div 2) + 40, (display_get_height() div 2) + (surface_get_height(application_surface) div 2) + 22, 32, 32, 0);
   draw_roundrect_ext((display_get_width() div 2) - (surface_get_width(application_surface) div 2) - 36, (display_get_height() div 2) - (surface_get_height(application_surface) div 2) - 20, (display_get_width() div 2) + (surface_get_width(application_surface) div 2) + 36, (display_get_height() div 2) + (surface_get_height(application_surface) div 2) + 20, 32, 32, 0);
   draw_set_alpha(0.2);
   draw_roundrect_ext((display_get_width() div 2) - (surface_get_width(application_surface) div 2) - 32, (display_get_height() div 2) - (surface_get_height(application_surface) div 2) - 18, (display_get_width() div 2) + (surface_get_width(application_surface) div 2) + 32, (display_get_height() div 2) + (surface_get_height(application_surface) div 2) + 18, 32, 32, 0);
   draw_roundrect_ext((display_get_width() div 2) - (surface_get_width(application_surface) div 2) - 28, (display_get_height() div 2) - (surface_get_height(application_surface) div 2) - 16, (display_get_width() div 2) + (surface_get_width(application_surface) div 2) + 28, (display_get_height() div 2) + (surface_get_height(application_surface) div 2) + 16, 32, 32, 0);
   draw_roundrect_ext((display_get_width() div 2) - (surface_get_width(application_surface) div 2) - 24, (display_get_height() div 2) - (surface_get_height(application_surface) div 2) - 14, (display_get_width() div 2) + (surface_get_width(application_surface) div 2) + 24, (display_get_height() div 2) + (surface_get_height(application_surface) div 2) + 14, 32, 32, 0);
   draw_roundrect_ext((display_get_width() div 2) - (surface_get_width(application_surface) div 2) - 16, (display_get_height() div 2) - (surface_get_height(application_surface) div 2) - 9, (display_get_width() div 2) + (surface_get_width(application_surface) div 2) + 16, (display_get_height() div 2) + (surface_get_height(application_surface) div 2) + 9, 32, 32, 0);
   draw_roundrect_ext((display_get_width() div 2) - (surface_get_width(application_surface) div 2) - 8, (display_get_height() div 2) - (surface_get_height(application_surface) div 2) - 4, (display_get_width() div 2) + (surface_get_width(application_surface) div 2) + 8, (display_get_height() div 2) + (surface_get_height(application_surface) div 2) + 4, 32, 32, 0);
   draw_set_alpha(1);
   draw_set_colour(c_white);
  
   //This part is what draws the application surface manually, so it will end up in the center of the screen
   application_surface_draw_enable(false);
   gpu_set_blendenable(false);
   draw_surface(application_surface, (display_get_width() div 2) - (surface_get_width(application_surface) div 2), (display_get_height() div 2) - (surface_get_height(application_surface) div 2));
   gpu_set_blendenable(true);
}
else //If we are using Stretch Full Screen or Windowed Mode
{
   application_surface_draw_enable(true); //The application surface can draw itself
}
//--------------------------------------------------------------------------------
Please note that all my rooms are the same size (1280x720) and all have views enabled just in case (but none end up moving).
All my rooms also have Clear Display Buffer turned ON and Clear Viewport Background turned ON.

----------------------------------------------------------------------------------------------------------
EDIT: One more thing: should I be using the Full Scale or Keep Aspect Ratio global game setting in my game for this?
I don't know if it will have any difference with the Fixed scale's look or mask behaviour.
I am currently sticking with Keep Aspect Ratio, because I want the game to look "letterboxed" in 16:9 aspect ratio in Normal Scale Full Screen mode.
----------------------------------------------------------------------------------------------------------

MY QUESTION (summing up):

I have no idea where my mistake could be. I have tried resizing/using view_port functions, using surface_resize, but nothing. All still looks good, but the masks of everything are still stretched as a view in Full Screen. How do I resize the "physical" parts of the game aswell, not just the visual parts, on Fixed Scale (100%) full screen mode?
 
Last edited by a moderator:
F

FB-Productions

Guest
I have scowered the entire community and beyond, and I could not find a working solution to this.
Please, can anyone assist me?
 

NightFrost

Member
You mention clickables. I've never tried doing unscaled fullscreen thing like yours, but I suspect mouse position has something to do with this. GMS gives mouse_x and mouse_y as room positions, and what you're doing there is just changing how and where stuff is drawn, so room [0,0] point is likely still in the upper left corner of your display. Not sure what would cause the stretch though, if what you draw is 1:1 scale to room then it should just appear offset to up and left, not stretched.
 
F

FB-Productions

Guest
You mention clickables. I've never tried doing unscaled fullscreen thing like yours, but I suspect mouse position has something to do with this. GMS gives mouse_x and mouse_y as room positions, and what you're doing there is just changing how and where stuff is drawn, so room [0,0] point is likely still in the upper left corner of your display. Not sure what would cause the stretch though, if what you draw is 1:1 scale to room then it should just appear offset to up and left, not stretched.
But the end result is drawn 100% correctly. It is just the clicking (masks) that still acts as the stretched full screen. I honestly do not know where to go from this point. I've tried basically everything. :/
If you have an idea, could you please tweak the code?
 

RangerX

Member
What you could do is simply handle the application surface all by yourself and disabling all automatic stuff GM Studio does to it.
There's a function for that which is "application_surface_draw_enable()".
This means you will have to draw the application surface yourself every step in a draw or post draw (I personally use post draw for this) and you will be able to size it any size you want and draw it any size and position you want. (in the case here, centered on the screen).

Obviously this means your game needs to be drawn on the application surface and if you use the gui layer, you need to resize it accordingly.
 

NightFrost

Member
The provided code already disables automatic draw and draw_surface centers the app surface on screen. But as I said, this is of course just a draw operation and will not change how mouse position is translated to room position. I've never used anything beyond window or fullscreen where content fills them entirely, so I don't know what procedures the mouse position goes through when its room position is decided. But, seeing how scaling never affects it in my projects and how OP describes the problem, I suppose it might just get screen position and then add view offset if there's any. (I've attached an image how I see the problem being described.) Using view ports seems like the solution that should be used, but since I've never tried them myself I don't know how they affect mouse position.

the problem.png
 
F

FB-Productions

Guest
What you could do is simply handle the application surface all by yourself and disabling all automatic stuff GM Studio does to it.
There's a function for that which is "application_surface_draw_enable()".
This means you will have to draw the application surface yourself every step in a draw or post draw (I personally use post draw for this) and you will be able to size it any size you want and draw it any size and position you want. (in the case here, centered on the screen).

Obviously this means your game needs to be drawn on the application surface and if you use the gui layer, you need to resize it accordingly.
But didn't you check my code and my post? I have already done/tried all that. That is what lets the game look the way it should. But it still won't act the way it should (with mouse presses).
And just for extra info: I have no Draw GUI events in my game and I wouldn't have problems configuring them. :)

The provided code already disables automatic draw and draw_surface centers the app surface on screen. But as I said, this is of course just a draw operation and will not change how mouse position is translated to room position. I've never used anything beyond window or fullscreen where content fills them entirely, so I don't know what procedures the mouse position goes through when its room position is decided. But, seeing how scaling never affects it in my projects and how OP describes the problem, I suppose it might just get screen position and then add view offset if there's any. (I've attached an image how I see the problem being described.) Using view ports seems like the solution that should be used, but since I've never tried them myself I don't know how they affect mouse position.

View attachment 24140
I have tried to alter my code so it uses the view_port[0] variables (I think I mentioned it in my first post). When I did that, the clicking was working perfectly, but resizing a view port (using view_wport[0] and view_hport[0]) did absolutely nothing.
The game would still stretch the application surface out through the full display, so basically I did nothing except I succeeded in moving my view port with view_xport[0] and view_yport[0].
However (in the fixed full screen), the view did not move correctly, remained the same size as the display and also the background didn't draw on the display, so it was just blank blackness:
gmc2_viewporttrouble.png

EDIT:
For a moment, I was thinking about using the code that successfully drew the application surface itself and got me my display background shown and combining it with the view port code that successfully moved my application surface, ie view. But, I figured there was no point, because when I used the view port, it still didnt descale it, so I'd just be moving the "invisible", stretched, fullscreened clickable mask canvas over the screen and doing nothing right. :/
 
Last edited by a moderator:
Top