This tutorial explores arguably the most important tool that GameMaker Studio 2 has to offer... the Room Editor. No matter how many sprites, objects or other resources you create, your game will not run unless it has at least one room, which is why all new projects are created with a room by default. However you are not limited to one room and can have as many as you require to bring your project to life.
The room editor has a great many tools for you to use and has some quite advanced functionality to let you create your games how you want to, and in this tutorial we will cover the essential aspects that you need to know to get started, and simply give a brief overview of the more advanced aspects. When you finish you can always press to open the manual and get more information.
Before actually opening a room, we'll first talk about Game Speed as this will affect everything about your game and should be set at the start. The game speed is calculated as Game Frames Per Second, and can be set from the project Options window (click on the Options button to open):
In the image above the default value is shown which is 30 Frames per second (fps). This means that the game loop will tick over 30 times (frames) in one second, so, for example, if you have an instance that is drawing an animated sprite, the sprite will show 30 frames in one second - assuming the animation speed is also set to 30 in the image editor - or if you have an enemy object that has to run AI code in the Step Event, it will run its code 30 times in a second. You can set this value to whatever feels right for your game, with 30, 40 and 60 being the most common fps that people choose. Note that this is not a fixed value, and is simply the frame rate that you want the game to try to maintain. If you have too much happening or the game is poorly optimised, then the fps can go down causing your game to lag, although it will not ever go over the given fps. Also note that a higher fps will mean that the target platform will have to work harder, so you need to balance this with the amount of processing you do in your game - a fps of 120 will make everything happen twice as frequently as a fps of 60, meaning twice the workload for the platform processor.
You can have instances with movement, animated tile sets, animated sprite assets, and a great many other things in your game room and they all depend on the game speed to tell them at what time to perform their actions and change frame, etc... So, setting the game speed first is important as it will affect how everything you place in the game rooms looks and works, and changing it later because you've made a mistake can be problematic. Now lets actually set up a room!
By default GameMaker Studio 2 will always create an empty room for you whenever you start a project, since all games require at least one room to run. When you double click on this resource from the resource tree, it will open the Room Editor Workspace, with a number of tools and sections for you to use to design your game levels. This can all be a bit daunting to look at to start with, so we'll look at the main sections one at a time starting with the Room Properties:
This panel is where you can set the room width and height, in pixels, as well as a whether it should inherit the properties of a parent room. We'll talk more about inheritance later in this tutorial, but basically you can create parent and child rooms and have child rooms inherit properties from the parent. This means that you only have to set up, for example, a tile layer once in the parent room, and then all child layers will get it too. Beneath the "Inherit" button you can set the room to persistent and set whether you want the back buffer to be cleared every step of the game or not:
- Persistent: If the room is classed as persistent then this code will only be run the first time the room is entered, unless persistence is turned off through code. But what is a persistent room? Well, you can see a checkbox for it in the properties window, and ticking it makes the room persist its last state when it was exited. For example, say you have a persistent room with 100 enemies and the player kills 40 before going to the exit and into another room. If the player then goes back to that room, there will only be 60 enemies, since the room has persisted within the game.
- Clear Display Buffer: This one is a bit tricky to explain... Basically, the display buffer is what things in your game are drawn to, and to start with it's usually cleared with a colour (black), and then the application surface and GUI etc... are drawn to it. However you can uncheck this option to stop the automatic clearing of this buffer, meaning that things that are drawn to it one step, will not be cleared before the next step is drawn. This can give some very interesting "trail" effects, but in general it's not what you want unless you know that the views or backgrounds in your project are going to be covering the whole screen at all times or that you have a fullscreen background being drawn - in these cases you can safely un-check this (which saves a redraw and so helps optimise your game). If you have overlapping views that when on the screen leave open spaces, or your background has any transparency, or you have used "Correct Aspect Ratio" as a Game Option, then you will want to leave this checked too.
This panel also has a button for adding room Creation Code. The room Creation Code is a single section of code (or actions if you have created a DnD™ project) which is run once when the room is first initialised. The actual order of initialisation is as follows:
- Create Event of each instance, followed by the
- Instance Creation Code of each instance
- Game Start Event (this will only be run in the very first room of the game)
- Room Creation Code
- Room Start Event of all instances
The other button under the Creation Code is for setting the Instance creation Order. When adding instances to a layer, they may be initialised in any order, which normally isn't a problem. However it may be that you have a controller object or some other object that is required to be created first before all others (for example, it may be that it is initialising global variables that all other instances require). You can do this from the window that opens when you click the Instance Creation Order button.
Finally, we have sections for Views and Physics. We'll come back to the Views section in a moment, so for now we'll finish this part by looking at the Physics section:
Using physics in your games is an advanced feature and as such we're only going to touch briefly on what this option does, but you can find the full documentation pressing to open up the manual. Enabling physics tells GameMaker Studio 2 that the room is a physics simulation and permits you to set up some basic properties that govern this simulation. It is essential to know that when you convert a room into a physics enabled room in this way, you are changing quite radically how things are done, especially movement and collisions between instances. They will all be affected by the gravity vector you set here, and will all behave very differently depending on the value that you set for the Pixels To Meters scale.
The final room property that we need to look at is the use of Views. Views are split into two parts: the view port and the camera, where the port is the area of the screen that will be drawn to, and the camera defining what will be drawn to that area. If you expand the views section you will see the following:
By default GameMaker Studio 2 will display your room to the player exactly as you created it, ie: if it is 640x480, then it will be run in a 640x480 window. This is okay if you have a standard sized room, but when you start to get into long rooms that you want to scroll left or right, or huge overworlds that you only want to show a part of then you need to be able to set a specific window size and only show certain areas of the room in that window. For that, you need to tick the Enable Viewports checkbox. The other option available is to Clear Viewport Background, which can be used to clear the background of the view before every draw event in the game loop (this doesn't usually need to be ticked unless you are using multiple views or haven't assigned a background layer in the room editor).
When you have enabled views, you will then need to set up the view port and the view camera. As hinted at above, you can create multiple view ports and cameras, but for this tutorial we're simply going to cover the basics of a single view. If you want more information on multiple view ports, then please check the room editor section of the manual (press ). To set the view properties you need to click on the view you want to enable (from 0 to 7, so you have 8 view ports that can potentially be used at any one time) and it will expand:
You need to first make sure that the view is set to visible otherwise even if you have enabled views nothing will be drawn. You then have to modify the first two sections to set how you want to display your room, and (optionally) the third section for setting up object following. The sections are as follows:
- Camera Properties - The view Camera is defined as the area of the room that the camera views. So if you have a long room, for example, that is 3000x540 and you only want to show a single "screen" of that room, you would set the view camera width and height for the camera to something like 960x540. Apart from the width and height, you can also set the position of the camera within the room by changing the x/y values. Note that you can use negative values for position and place the view camera outside of the room, which can be useful.
- Viewport Properties - The Viewport is the area that we will reserve on the screen for drawing what the view in the room "sees". For example, it may be that you have a low resolution game that only uses a camera view 160x96 in size. If you set the view port to be the same, then it will be drawn at exactly that size on the players screen, which is obviously too small with today's monitor resolutions. To remedy this you can change the view port to be larger, knowing that any camera attached to that view port will be scaled up to fit, so our port could be 800x480 (five times the camera size). You can also set the position of the view port, but if you have only one port active then this makes no difference and can be left at 0 (see the manual for more info on what these values mean for multiple view ports).
- Object Following - This is the final section for setting up the view properties. This is entirely optional and can be ignored if not required. What it does is permit you to select an object from the resource tree and set it as the "follow" object. Once set, the view will follow an instance of that object around, trying to keep the instance always within the area set for the horizontal and vertical border values. If you set these to 0, then the view will always try to center the instance, and setting it to larger values will permit the instance to move that amount in the direction before the view moves to catch up. You can set the speed that the view will follow the object at, with a value of -1 meaning that the view will move instantly to follow the instance, while other values will move the view that number of pixels every game frame.
Layers and Resources
Our room has been set to the size we want and we have set our views... now it's time to add the elements that will make our game function from the resource tree. You can add a number of different resource directly into the room editor and they are all placed on Layers. A layer is simply an imaginary plane on which we can place sprites, tiles, paths and instances so that the room knows when and how to display them. By default the Layer Properties window will open whenever you open a new Room Editor workspace (if you have closed it by mistake you can open it again from the Room context menu at the top of the IDE) and will have a couple of layers created for you by default:
Layers are ordered from the lowest to the highest, so those layers lower on the list will be drawn first and higher layers drawn over them. The image below shows how this works, with the backbuffer being drawn first, then the room layers, then the GUI layer on top (corresponding to the Pre Draw, Draw and Draw GUI events):
There will always be two layers added to any room you create as you will almost always require these two layers: a background layer and an instance layer. These layers can be removed at any time, and you can also add more layers as you require, and note that you are not limited to just one layer of any given type, so you can - for example - add 3 or four background layers offset to each to create a parallax background. You can click on any layer to bring up that layers properties window, where you can edit things specific to the layer type like position or draw order, etc... You can drag and drop layers up and down the list to reorder them too, and you can even create group folders by clicking the icon and dragging layers onto it. If you no longer wish to keep a layer, you can select it and hit to delete it.
Below is a list of the different layers available and a brief description of what they are for (for detailed explanations of each layer and their properties, please see the manual):
|The background layer consists of a single colour that covers the whole room area, or a single sprite that can be stretched to cover the room, or tiled horizontally and/or vertically.
|The instance layer is where you add instances of your game objects. All instances placed on a single layer occupy the same "depth", which is the value given to the layer to determine draw order, where the lower the value the nearer to the camera they are.
|A tilemap is a rectangular grid made up of tiles from a tile set. These are typically used for static or non interactive elements in your game, although they do permit limited animations. As they are on a grid and are simply being drawn every game frame, tiles are a very efficient way to add graphic resources to a room.
|The path layer is really a convenience rather than an actual layer within the room. Basically, you can create a path layer to create (or use) a Path Resource as it would be used within the actual game room at runtime. So you can edit the path around changed room elements, or plan a route based on tiles, etc... but it will not draw anything when the game runs.
|The asset layer is a halfway-house between using a background and using an instance. Essentially this layer will draw any sprite element at any given position with the room, and you can also set certain properties like its blending colour or scale. Assets are faster to draw than instances, but will not experience collisions and cannot run any code, but they are slower to draw than tile sets since they have a bit more processing overhead.
After you have created the desired layer type you need to add the different resources to it. This is done by simply clicking on the resource and then dragging it into the room editor. Below you can see an example of some sprite assets being added to a room, edited and then tested:
We touched on Room Inheritance briefly at the beginning of this tutorial, and here we're just going to expand on what was said a bit, since inheritance is one of the most powerful (and time saving) features of the GameMaker Studio 2 room editor. We mentioned before that you can create a main "parent" room and then clone "child" rooms from it that will inherit all the properties from the main parent room. Well, while this is true, there is much more to it than that!
You can make a child room from any room in the resource tree by right clicking on the room resource you want to "clone" and selecting Create Child:
This will create a new room for you and open the workspace for you to edit it. You will notice that all the "Inherit" buttons are now highlighted for everything that was in the parent room. You can also see that you have access to all the same layers and properties as those set in the parent room:
What has happened is that everything in the room that has the inherit button highlighted is based off of what is in the parent room. If you change a tile in a parent room, then all child rooms will reflect this change too. However, what if for example, you want to change a tile in the child room but leave everything else as it is in the parent? Well, you can simply change that tile and it will be shown in the room changed. By editing any feature from an inherited room in a child room, you break inheritance and the item will no longer be considers as part of the initial room.
There are many, many ways that this system can be used, especially as you can have multi-room hierarchies, with each room being a child of the previous room. So, you could have an empty first room that simply sets up the view port and the camera, and then you can make a child room that is a level, and then another child room of that which contains the same level but with different tiles. For example, think of an RPG - you could have a town room with a background, a tilemap to draw houses and plants etc... and an instance layer with NPCs. Now, you want to have the same room again, only in this one you want to use a night-time tile set. This would normally require you to duplicate the room and redo the tile set by hand, but with inheritance, you simply set the new room as a child and change the tile set that is used to draw the tilemap layer. Everything else will be inherited from the parent room, but now the tiles will draw using the tile set chosen.
This tutorial has gone over all the basics of how the room editor works and hopefully now you are ready and confident enough to start making your own game projects. Keep in mind that a room is simply an area that can be drawn to the screen where you can place different resources. What is drawn and how they are drawn will depend on the resource chosen and the properties you set for it. Keep in mind too that everything in a room can be inherited (or not) from one or more parent rooms. you should also note that if you close any of the room editor windows (like the layer or room properties windows) you can open them again from the Room context menu at the top of the IDE.