Resolution and Aspect Ratio Management for Game Maker - Part 3

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey game makers pixelated Pope here and welcome to part 3 the final part of my tutorial on dealing with resolution and scaling and game maker in this part we are finally going to put PowerPoint away and dig into some actual code and as you probably already notice this part is a lot longer than the other ones but stick with me because we're going to build a simple display manager that will automatically remove black bars resize the window and some other awesome features I promise it will be worth the investment so let's get to it I have a basic project here a single room and a character that runs around the character also has some code in it the forces of you to follow for now I've disabled views so you can see the room is currently deciding the resolution of the game which we obviously don't want I've also got the views disabled because with this solution you will never need to go into the views tab of any room you create in your project ever again I don't know about you but I got so tired of having to reset up my views every time I added a new room to my game after this those days are gone let's set up our manager object and get started on tackling problem number one dynamically setting the resolution for the game based on the current displays aspect ratio and automatically eliminate in the black bars let's create a new object and give it a name like object display manager set him to persistent now the next question is which room do we put them in we're actually going to give him his very own room and we'll make sure to always make it the top room in our list so create a new room and give it a name I sort my resource list pretty commonly so I'm going to give it a name that will always appear at the top of my alphabetized room list but name it whatever you want just remember this should always be the top room in your list so it is run first set the room size to something small like 16 by 16 and set the background to black this room will be visible on the screen when your game starts for only a fraction of a second drop an instance of our manager in there and close the room back to the object itself add a create event this is where most of the magic is going to happen our first step is to decide on our games ideal resolution this is the resolution you were going to design your game for more specifically we only need to decide on the width or the height because we'll use the aspect ratio of the monitor to determine the other side this is where that decision to maintain the width or the height I talked about in part one comes into play let's pretend my game is sort of like Castlevania the height of my game is very important there could be enemies that walk along the ceiling and drop stuff on my player if my height is variable the shape of the monitor may determine whether that enemy is on screen or not allowing the player to see a little bit more to the left or the right of the level is not nearly as bad as hiding enemies and hazards from them as such I'm going to go with what I recommended in part one pick a static height and then dynamically change my width to fit the monitor so let's create two variables ideal width and ideal height set the width to zero because we're going to calculate it later and set ideal height to your desired height in my case 256 now we need the aspect ratio of the monitor create another variable and call it aspect ratio set it equal to display get width divided by display get height on a sixteen by nine monitor the result will be one point seven seven seven seven repeating here's a cool note about aspect ratios in this rational format an aspect ratio greater than one is a landscape display and asked to ratio of 1 is the square monitor I've never seen one of those and an aspect ratio less than 1 is a portrait display essentially the higher the number the wider the display the smaller the taller now we have the two pieces of information we need to calculate our width so set ideal width equal to round ideal height times aspect ratio if you decide to maintain the width and scale the height your ideal height would be equal to round I deal with divided by aspect ratio since our aspect ratio is a rational number instead of a whole number we want to round it but we have one other problem there is no monitor in the world at least not to my knowledge that has an odd number of horizontal or vertical pixels I don't think they exist as such your ideal width and height should be even numbers well we typed in our ideal height so that should be easy to control but we just calculated our width how do we make sure it's an even number the code itself is actually pretty simple but may seem a bit strange if you're curious about why this works look into bitwise operators regardless here's how we check for an odd number if I deal with and one I deal with plus plus that will check if it's an odd number and if it is add one to it but why do we increase instead of decrease and I honestly don't have a good answer for you it just seems to work for every resolution I've ever tested on there may be a mathematical explanation but if you want to math the explanation for things you've come to the wrong channel my friend now we have our ideal width and our ideal height next we need to use those values to resize the different layers we talked about in part 2 starting with the view here's where we set up the view for every single room in our game with a simple for loop and we'll never have to do it in the room editor ever again for VAR I equals 1 I is less than or equal to room last I plus plus so if you weren't aware every resource and your resource tree is just a number every sprite script object room etc the name is a variable you can access at runtime but the value of that variable the ID for the resource is just the position of that resource in the tree the top one in your list is zero the next one is 1 then 2 etc and so forth so we know this code is running in room 0 so we can skip that which is why we start with I equal in 1 and even though we're pretty sure that every number between 1 and room last is a room that exists we still want to double check we always want to give ourselves a safety net when dealing with accessing specific objects instances or resources so simply type if room exists I now inside of here we only need 2 lines of code the first is room set view and this thing has a ton of arguments so let's go through them one by one the first is our room index we're looping through all of our rooms so this is I next is the view index we are only using view 0 so we can just type 0 in here we want the view to be visible so set this argument to true we don't care where the view is for now because code will position it later so set the x view and Y view both to 0 here we go ok these two are important our view width and height should be set to our ideal width and ideal height next is the poor position we don't want to mess with this so leave them at 0 at 0 the port size arguments are a little weird so port size is basically read only and only applicable in the first room of your game it can't be used after your game is started running so these values really shouldn't matter however setting them to 0 0 will break everything for some reason but any value over 0 will be fine so set these to 1 1 I guess okay hold on a minute so after a bit of testing I noticed a really bizarre behavior that is linked to this script so I just said that port size can be any number greater than zero and it will work fine and as far as your visuals are concerned that is still true however if you want your mouse X and mouse Y variables to work properly this is not the case I don't know if this interaction is intended by yo-yo but your port size seems to have some interaction with your mouse coordinates like it affects the resolution your mouse can be read at or something strange like that so instead of 1:1 for the port width and height it's safer to have ideal with an ideal height this will ensure your mouse coordinates don't act strangely all right back to the tutorial rest of the values deal with automatic camera following and I recommend always handling this manually there are several big shortcomings with the automatic system that I won't get into now so set the rest of the arguments to zero but the very last one set to negative one oh okay that was a huge function but this next line is really easy we just need to make sure views are turned on in every room so room set view enabled I true now every room in our game from now on will have the view set up properly automatically you never need to go into the views tab ever again for this project but our game still isn't quite ready to be ran we need to update our other layers we talked about in part two let's resize the application surface to match our ideal resolution surface resize application surface ideal with ideal height and let's resize the window window set size ideal with ideal height and that's pretty much it now we just need to go to the actual first room of our game the next room after the init room so the game can start room go to room next room don't forget to put your display on it room at the top of your list and then let's run the game and see what we got and there we go game window is sized properly our view is working great and when we switch to full screen no black bars now those of you have been paying close attention may notice something odd my games resolution right now is 456 by 256 but it's plain full screen on a 1920 by 1080 monitor 1920 divided by 4 56 equals 4 point 2 1 875 that's not a whole number we aren't scaling perfectly where's all this pixel distortion and awful graphics I was warning about back in part 1 the answer is that it is there but it's not such a big deal really when you're scaling up pixel art 1.5 is pretty much the absolute worst case scenario as you get higher and higher the distortion will be less and less pronounced at over 4 times which is what we're at now it's almost impossible to notice what may make it a problem is if certain patterns in your games art specifically repeating background tiles make the distortion more pronounced so the lower res your game is the less you really need to worry about perfect scaling on that note here's pixelated Pope's programming pro pointer number one never build your game for 1280 by 720 it is the absolute worst resolution you can build your game for right now a 720p game when stretched to a 1080p monitor the most common monitor resolution among gamers according to steams Hardware survey from August of 2016 is scaling exactly 1.5 X and you will get the absolute worst possible pixel Distortion in full screen all right we have our game and it looks okay but the window size is very small so we want our player to be able to make the window bigger that should be pretty easy first open up the global game settings and go to the windows tab if you haven't already make sure interpolate colors between pixels is unchecked checking this looks horrible for pixel art next just check the allow the player to resize game window box make sure the scaling is set to keep aspect ratio this is that option I talked about in part 2 that will change how the application surface is drawn to the window I literally have no idea why you'd ever want full scale alright run your game the window is resizable but is this really how you want your player to resize the window it's sort of ghetto they can scale it up to any multiplier so we lose all control for preventing pixel Distortion and since it can be any dimension we get the black bars even in windowed mode Yawk so let's go turn that silly option off and do this the right way what we want to do is allow the player to zoom the game window so let's go back to the manager object and open the create event at the top let's define a new variable zoom the higher the zoom the bigger the window set it to 1 now let's add a step event and drop a code block in there well now listen for a certain key to be pressed and then increase the zoom every time it's pressed let's listen for the Z button if keyboard check press or Z zoom plus plus we also need to apply that zoom to the window size so window set size I deal with time zoom ideal height times oom simple as that run the game we've got a few problems first and foremost is the game doesn't Center after resizing secondly we can zoom infinitely obviously that's not useful let's tackle that centering problem first like I said back in part two there's a function for centering the window however there's a one step delay for it to work as you would expect so add a new alarm and drop a code block in there in that code block call Windows Center now back to our step event every time we resize the window we set alarm 0 equals 1 next let's stop the window from zooming to infinity in the create event at a new variable under zoom called max zoom set it to 1 for now we're going to calculate the actual value down after we finalized our ideal width and height we can calculate the max window zoom max zoom equals floor display get width divided by ideal width in this case our maximum will be 4 if we rounded it instead of flooring we would run the risk of rounding up which could give us a maqsuum that would make the window bigger than our monitor so always floor this calculation now we need to actually enforce this mac zoom head back to our step event after we increase the zoom let's check to make sure the zoom hasn't exceeded our maqsuum and if it has set it back to 1 if zoom greater than max zoom zoom equals 1 let's run it again and see how everything looks all right now we can zoom lock to perfect multiples for perfect pixel scaling the window is centered each time and it wraps around back to 1x if we exceed our calculated maxes ooh now that we've zoomed the window what about zooming the camera in our game that's totally possible with this system since the view is always being scaled to fit the application surface all we need to do is make the view bigger to zoom out and smaller to zoom in all while maintaining the current aspect ratio it's actually pretty simple however this code won't actually go in the display manager ideally you would have a camera object or something that is controlling how your view behaves in your game in this demo it's actually the character that is controlling the camera so let's go to the player object and add some new variables in the create event we add view zoom equals one and view max zoom equals 10 now go to the step event where we were updating the position of the view we want to apply the zoom before we reposition the view first let's add some simple controls bar zoom speed equals point one view zoom plus equals keyboard check VK up time zoom speed view zoom minus equals keyboard check VK down time zoom speed so when we press up on the keyboard will increase our zoom which will appear like we are zooming in and when we press down will decrease it zooming out but we need to make sure we don't go out of bounds view zoom equals clamp view zoom one view Max's oom now let's actually resize the view the UW view equals your display manager ideal width / view zoom and view H view equals your display manager dot ideal height / zoom the rest of the code just centers the view on the player and make sure the view is clamped to the room let's run it and see how it looks so it looks okay but when the window is large and we zoom in just a little bit we are starting to see the pixel Distortion we were talking about in part 1 so how do we fix that well remember how I said there was no such thing as half a pixel in computer graphics that's not entirely true when we scale our game window we stretch the view to the application surface in the case of a 4x zoom that means each of our pixels is being displayed as a block of 16 pixels with a single simple line of code we can actually force GM to use all 16 of those pixels instead of treating them as 1 this will smooth out scaling and rotation distortion and any sort of movement or scrolling back to the manager step event after we resize the window let's resize the application service to be the same size as our window surface resize application surface ideal width times zoom ideal height times oom it's that simple now when we run the game and zoom in all the pixel distortion is gone it's worth noting that this is a bit of a performance hit as we are essentially upping the resolution of our game by 4 times in your game try and find a nice balance resizing the application surface to be 2 times the size instead of nearly 5 and fullscreen may eliminate most distortion and give you plenty of pixels to work with while having minimal impact on performance you don't always have to go full-blown max resolution we've been ignoring one of the layers discussed last time so far the GUI layer let's draw some text in the top left of the screen and the bottom right just to demonstrate how the GUI layer works and the display manager at a draw a GUI event and drop a code block in there draw set color see white draw set a July on FA left draw set be aligned if a top draw text 5:5 top left and draw set H a line F a right draw set V line F a bottom draw text display get GUI width - 5 display get GUI height - 5 bottom right let's run to see what that looks like all right pretty cool as we walk left and right or zoom in and out the text stays exactly where it belongs but what happens if we scale the window notice how the text stays the exact same size while everything else appears to get bigger that's because by default if you're using the GUI layer but never specifically set the size GM will always make it be the same size as your window so as our window and everything and it gets bigger our text doesn't so let's fix that and the majority of cases setting the GUI to be your ideal width and height and leaving it at that will be sufficient so open up your create event code and right next to where we resize the app surface let's resize the gooey layer display set GUI size ideal width ideal height and let's see if that worked now as we resize the window the text size stays relative to the rest of our game you can even dynamically resize the GUI layer as much as you want if you want your HUD to stay small or allow your player to choose how large they want it I've been putting this one off until last as it's the most math heavy feature way back in part 1 we talked about resizing our ideal width not just to eliminate black bars but also to scale perfectly a full screen with no Distortion let's implement that now as I mentioned previously this feature is a bit of a double-edged sword the higher res your game is the more drastic the change will be to make it scale perfectly but the lower res your game is the less this actually matters this pixel distortion will be more difficult to detect when the multiplier is over 4 or 5 so don't feel forced to use this feature if your game looks fine on most monitors without it with that in mind back to the managers create event underneath where we set our ideal width let's do the calculations if display get width mod ideal width does not equal 0 so this is checking if our ideal width divides into our display width perfectly mod will give us the remainder of the left side divided by the right side if our display width is already a perfect multiple of our ideal width then we don't need to do anything otherwise we need to adjust it to be a perfect multiplier VAR d equals round display get with / ideal width I deal with equals display get width / D so we divide our width by our ideal width and round it to be the nearest whole number multiplier then set our ideal width to our monitors width divided by that new whole number multiplier so let's let's break that down if our display width is 1920 and our ideal width is 460 1920 divided by four sixty equals four point one seven four rounded is for 1920 divided by four equals 480 so 480 would be our new ideal width now we do the same thing for height if display get high Mada ideal height does not equal 0 VAR d equals round display get height divided by ideal height ideal height equals display get height divided by d just for safety let's add a check for odd numbers with our height like we do with the width since we were calculating it now now let's give our ideal height a strange size just to see how it changes everything so let's set it to 247 an odd number that doesn't divide into 1080 evenly one more thing real quick let's go to the draw a GUI event and display our view size in the top left corner so we can see the changes all this math is doing display right specs display dot view this is a little script I've included with the example project that will print out the size and aspect ratio of the monitor the window the view the app surface or the gooey layer useful for debugging all this resolution stuff let's run and see what we got so our height of 247 got changed to 270 a difference of 23 pixels and a new width has been calculated using the 16 by 9 aspect ratio the game now scales perfectly 2 for X on my 1080p monitor and that is pretty much it you now have a pretty functional display manager I was planning on releasing my own version with a bunch of additional features and whatnot but it feels bloated and a bit unwieldy still but I think you can take this and run with it here are some ideas for what you can do to expand on this restrict your ideal width and height by a min and Max aspect ratio maybe you don't want to support monitors that are more square than 4 by 3 or wider than 16 by 9 restrict your ideal width and height by a minute max size to ensure you aren't designing your levels and screens for infinite possibilities with this restriction you only have to test the two extremes and then everything in between should work perfectly allow your player to select the resolution and aspect ratio they want if they want black bars they can play with black bars if they want to play in your recommended size and windowed mode regardless of monitor aspect ratio let them let the player choose the multiplier for the application surface this setting would actually be more similar to a 3d games resolution setting than anything else as increasing it will improve fidelity as well as decrease performance save and load the players previous settings if they were playing the game in windowed mode with a zoom of 3x start the game in that mode next time they started up there are so many possibilities anyway thanks for sticking with me through this enormous tutorial hopefully with this you can spend less time worrying about how your game displays and spend more time on how your gameplays again the finished example project is available for download down in the description so check that out if you need to if you'd like to see more tutorials like this try hitting those like and subscribe buttons if you have any questions or if there's a topic you'd like to see a tutorial on post them in the comment section below and I'll do what I can to respond thanks for watching now go make something awesome
Info
Channel: PixelatedPope
Views: 48,339
Rating: undefined out of 5
Keywords: Game Maker Studio, YoYo Games, GML, GM:S, Resolution, Pixel Art, Scaling, Zooming, Camera, View, Application Surface, Fix Distortion
Id: wv3R2Q536ZU
Channel Id: undefined
Length: 24min 37sec (1477 seconds)
Published: Sun Sep 11 2016
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.