Lets Get Started:
First I want to discuss Surfaces. Surfaces are like canvases which GameMaker draws your game or whatever you tell it to draw, then displays that canvas on the screen. GameMaker’s documentation says it best so I’m just going to quote it:
In the normal draw events, GameMaker: Studio doesn’t actually draw directly to the screen, but rather draws to a surface called the application surface. This surface is basically a blank “canvas” that can then later be manipulated before being drawn to the screen when needed, and in most cases GameMaker: Studio handles this for you
So as the documentation states, even if you aren’t setting up surfaces, GameMaker has a default surface that it draws your game onto, named “application surface.”
Now that you understand the application surface, we will come back to it in a second.
Whenever I start a new project the first thing I do is decide what resolution/size I want the game to be. This can later be changed but I think it’s very important to have a basic idea. For the sake of this tutorial I want the game to be 4:3 resolution at 640×480.
Since we are going to be using pixel art, this means the actual resolution of the game will be 320×240 (half) but scaled up to 640×480 so we can clearly see everything.
Noitu Love by Konjak
Because I mean playing a game at this size is just too small and difficult to make out things. So we should make it bigger right?
Open up your Global Game Setting and set them to this: (You can customize these setting to however you want, just make sure “Interpolate colors between pixels” is not checked and Scaling is set to “Keep aspect ratio.”
So now lets get to the actual coding. Create a new script. lets call it InitGame. Write this into the script:
For every game of mine I have a similar script that initializes basic variables I’ll need. Since this is a tutorial this is all we need. Make sure to have this piece of code run before anything else in your game.
Now let me describe what this code is. Here I am setting up some global variables that contain my desired resolution of the game. Which we decided before was 320×240. So this means the game will be 320 pixels wide and 240 pixels tall. I have another global variable there that is the zoom level. Since I want the game to be scaled up by 2, this is what I set that variable.
Remember the application surface? We are now going to adjust it so the resolution of it is going to equal our desired resolution. This is what line 5 of the code is doing.
Line 6 is just resetting the display and setting the AA level to 0 and turning off vsync.
Now we can finally get to the actual camera. Create a new object and name it obj_camera. Add a Create Event and lets put some code into it:
Here we are making the views have our desired resolution. We are also changing the GUI layer to the same resolution, and changing the room speed to 60.
Lets add a Step Event and add some code into it:
Here we are checking if the game window size is the game resolution multiplied by the zoom, and if it isn’t we make the window that size, then resize the application surface back to our desired resolution, then reset the display.
We are also checking if the game is in Full Screen and if it is, this code will not be run because chances are the game window won’t be that size when full screen.
And that’s it, we’re done! We now have a pixel perfect game. Your camera and sprites will now stay on a perfect pixel grid. Make your camera follow your player and test it out!
You can further test by rotating sprites and noticing that none of the actual pixels are being rotated, or have smaller pixels in them.
In the image shown below, Left is pixel perfect where as the right is not.
You can also change the zoom at runtime. You can do this by having an options menu in your game or any way you see fit. Currently for testing purposes I just have the code below:
ALSO, GameMaker is a little weird when it comes to the GUI layer, and unfortunately I haven’t been able to get the GUI layer to be the resolution I want even though the rest of the game is. This causes sprites on the GUI layer to not be pixel perfect when rotated. Not a huge problem but still annoying. If anyone has figured out how to fix this please let me know!