Do you dream of creating your own video game but don’t know where to start? You’re in the right place.
Creating games is easier than it ever was with tools like GameMaker – a popular engine geared specifically for 2D game development. With a thriving community, beginner-friendly language, and robust eventing system, GameMaker empowers you to quickly create whatever kind of game you could imagine.
This GameMaker tutorial will be your gateway to the fascinating world of game development. Perfect for both aspiring and seasoned developers, this guide will walk you through every step of building a fully functional game using GameMaker Studio and set you up with the fundamentals you’ll need for future projects. Imagine the thrill of seeing your ideas come to life on the screen as you gain essential skills in coding, design, and animation!
Without delay, let’s dive in!
Table of contents
GameMaker Tutorial Project Files
Want to use the same assets as this GameMaker tutorial? Or want to compare the final project code to your own? You can download the project files for this tutorial below!
- GameMaker Tutorial Assets
- GameMaker Tutorial Complete Project
Want to explore GameMaker in a more comprehensive manner? Explore our GameMaker Academy—a complete learning pathway packed with project-based courses across various genres geared at making you an industry-ready developer with GameMaker!
FREE COURSES AT ZENVA
LEARN GAME DEVELOPMENT, PYTHON AND MORE
AVAILABLE FOR A LIMITED TIME ONLY
What is the GameMaker Engine?
GameMaker is a free game engine, a software that allows you to create any type of game you can imagine. It is a 2D-only engine, but it is cross-platform, meaning that you can develop games for various platforms including phones, computers, web browsers, and consoles such as Nintendo Switch, Xbox, and PlayStation.
While GameMaker may not be suitable for creating AAA games, it has been the engine behind many successful indie games such as Spelunky, Hyper Light Drifter, Nuclear Throne, Hotline Miami, Cook Serve Delicious 2, and Undertale.
This article is divided into several sections, each focusing on a different aspect of GameMaker and game development as follows:
- Introduction to GameMaker: We start by installing GameMaker and learning how to use the GameMaker Editor, which is the central hub for all your game development needs.
- Features of GameMaker: We will explore specific GameMaker features such as the sprite editor, events, alarms, collisions, automatic bouncing off of objects, and how to move and rotate our sprites.
- GameMaker Language: We will delve into the GameMaker language, a beginner-friendly programming language. Even if you’ve never coded before, this article will guide you from the basics.
- Creating a Game: Finally, we will put everything we’ve learned into practice by creating a simple game where the player has to dodge arrows that spawn throughout the level.
Without further ado, let’s get started!
Installation
In this section, we will guide you through the installation process of the GameMaker engine. This will be the first step in setting up your game development environment. Whether you’re a Windows or Mac user, the process is straightforward and simple.
Firstly, navigate to the GameMaker download page by typing the following URL into your browser: gamemaker.io/en/download. Depending on your operating system (Windows or Mac), click on the appropriate download button:
Once the download is complete, locate the downloaded .exe file in your Downloads folder. Double-click on the file to start the installation process. A prompt may appear asking you if you want to make changes to your computer, simply click ‘Yes’ to proceed.
Next, a setup wizard will then guide you through the installation process. You will be asked to accept the terms of the agreement, which you can do by clicking ‘I Agree’:
You will also have the option to install OperaGX, but this is not necessary for the GameMaker engine to function. The rest of the default settings should be fine, so you can click ‘Next’ to continue:
The setup wizard will then ask you to choose the location where you want to install the GameMaker engine. The default location is usually sufficient, but you can change this if you wish. Once you’ve made your choice, click ‘Next’ to proceed.
The GameMaker engine will then begin to download and install. Once this process is complete, click ‘Next’ and then ‘Finish’ to close the setup wizard.
After the installation is complete, the GameMaker engine should automatically open. You will then be asked to install any platforms you’d like to upload your games to. Ensure you have Windows or Mac VM installed (depending on the platform you’re currently using) so you can play your own games.
- HTML5 is a good option as it allows you to upload your games to the web, making it easy to share them with others.
- Android is also an option if you want to put your games on a phone.
With the GameMaker engine now installed, you are ready to start creating your first game project.
Creating Your Project
When you first open GameMaker, you will see a screen displaying a list of your previous projects and when they were last edited. If you’re opening GameMaker for the first time, you might also see a setup wizard. Don’t worry about the setup wizard for now, as this article will serve as your personal wizard.
To start a new project, navigate to the ‘Get Started’ section and click ‘New’:
This will present you with several options:
- Live wallpaper: This allows you to create an animated wallpaper for use with Wallpaper Engine on Steam.
- Game strip: This feature is related to OperaGX, but we will not be using it in this tutorial.
- Game: This is the option we will be using.
After selecting ‘Game’, you will see a list of game templates. These templates can be useful for experimenting and learning how the GameMaker engine works. However, for this article, we will be starting with a ‘Blank Game’ project:
Once you’ve selected your project template, it’s time to name your project. We will name our project ‘Intro to GameMaker’. Make sure to save your project in a location you can easily remember, in case it doesn’t appear in your recent projects later. After naming your project, click ‘Let’s Go’.
You are now inside the GameMaker editor:
GameMaker Editor Overview
The GameMaker Editor can be quite intimidating for beginners, but we will break it down into manageable sections, starting with the Asset Browser. Understanding how to navigate and use this section is crucial for game creation.
Understanding Assets
An asset refers to any element that makes up a game. This includes characters, images, code, levels, and more. Essentially, every single component of your game is an asset. In the Asset Browser, you will find different folders representing various types of assets:
You can also create your own folders, known as groups, for better organization.
There are numerous types of assets you can use in your GameMaker game. In this introductory article, we will focus on a few key ones:
- Objects: These are everything that exists in your game. While you might think of images as objects, in GameMaker, an object is an image linked up to its behavior.
- Sprites: These are the images in your game. They make up the 2D characters, enemies, objects, weapons, bullets, projectiles, and more.
- Sounds: These are the sound effects and music for your game.
- Scripts: This is where all the code for your game goes.
- Rooms: These constitute the levels of your game. You’re given a starting level, which is indicated by a little home icon. As you create more rooms, the game knows which one to start you at and which ones you’ll go to throughout the game.
The Workspace
The workspace, which is a large blank area in front of our screen, is a unique feature in GameMaker. It serves as an area where we can organize and edit our assets. For instance, if we create a sprite, it will appear in the workspace:
We can edit various aspects of our sprite, including animations, collision data, and size. If we create another sprite, it opens in another sub-window in our workspace, below the first one:
We can navigate around our workspace using the scroll wheel on our mouse or the middle mouse button. We can also move around any of these windows, just like any window on a computer. In the workspace, we can open and edit all our sprites, sound files, and objects.
Essentially, all our assets in the game exist in this 2D space, which we can organize any way we want. We can also zoom in and out to visualize our game at a glance:
The Inspector
When we click on any of these assets on the left side of our screen, all of these options will also appear to us in the inspector:
The inspector is a convenient way to edit our assets on the fly while we might be in another window such as the room window. When we click on one of our rooms, it opens its own window separate from the workspace. Here, we can edit everything about our room, including placing and moving objects:
The Output Tab
At the bottom, there’s an output tab, which will be important later. If our code is throwing errors or acting unexpectedly, we’ll see the output here. We can also put lines in our code that’ll print stuff out to the output. This won’t be visible to the player but might be useful for us during development:
Top Bar Options
At the top of the screen, there are several options. Some of the most important ones include saving our project, building our project, opening different windows, accessing tools, and accessing the marketplace for assets:
We can also save and load different layouts. There’s also a help section, which includes a button to open up the GameMaker manual. This will be useful when we want to code something new or learn how part of the engine works.
The toolbar under the first bar allows us to save and open new projects. There’s also a button that allows us to run our game:
At this stage, our game is a blank screen because we haven’t really built a game yet. So, we can close the game window or stop the game by clicking on the button to the right of the run button.
Let’s now delve into how we can import sprites into our GameMaker projects. Sprites are a fundamental part of game design, representing the visual elements in your game, such as characters, objects, and backgrounds.
Adding a Sprite
To create a sprite, follow these steps:
- Right-click on your sprites folder (in the Asset Browser).
- Hover over ‘Create’ and click on ‘Sprite’.
- Name your asset. For sprites, it is recommended to start with ‘spr‘, followed by an underscore and the name of your sprite. For example, ‘spr_player‘.
Importing a Sprite
After creating a sprite, you can import an image file to represent it:
- Double-click on your sprite asset to open it in the workspace.
- Click on ‘Import’ and navigate to the image file you wish to use. In this case, we are using a ‘player.png’ file included in the asset pack for this article.
- A message will appear warning that importing a sprite is not an undoable action. Click ‘Yes’ to continue.
After importing, you can see the size of your sprite in pixels and set its origin. The origin determines the point on the sprite that represents its position in space. This is particularly important for things like rotation and collision detection. To set the origin to the middle center of the sprite, click on the dropdown that says ‘Top Left’ and select ‘Middle Centre‘:
Creating Animations from Sprite Sheets
GameMaker also allows you to create animations from sprite sheets. A sprite sheet is an image file containing multiple frames of an animation:
To create an animation:
- Click on ‘Import’ and select your sprite sheet. In this case, we are using an ‘arrow.png’ file that contains four frames of a rotating arrow.
- Click ‘Edit Image’ and then click on ‘Image’ on the bar at the top of the screen.
- Click on ‘Convert to Frames’. A dialog will appear allowing you to determine how to split your image into different frames.
- Enter the number of frames in your animation and the number of frames per row in your sprite sheet. In this case, we have a 2 by 2 grid, so we enter 4 frames and 2 frames per row.
- Click ‘Convert’ to create your animation.
After creating your animation, you can adjust its speed by editing the frames per second in the sprite settings. For example, a four-frame animation at 60 frames per second will appear very fast. Reducing the frames per second to 15 will result in a slower, more natural-looking rotation.
Customizing Sprites
GameMaker offers the unique ability to create your own sprites within the engine itself, eliminating the need for a separate program. Let’s now take a look at the process of creating a new sprite, editing its size, and utilizing the sprite editor panel.
Creating a New Blank Sprite
To create a new sprite, follow the steps below:
- Create a new sprite and name it ‘spr_custom_player’.
- The default size of sprite assets is 64 by 64. However, you can alter this size according to your needs. For this tutorial, we will use a size of 32 by 32.
- If you do not want your sprite to be square, uncheck the ‘Maintain aspect ratio’ box. This allows you to create a sprite that is wider or longer.
- Click ‘Edit image’ to access the sprite editor panel.
Using the Sprite Editor Panel
The sprite editor panel in GameMaker is a robust image editor that offers a range of tools. These include:
- A standard brush to draw any shape
- A color picker with a history of previously used colors
- An eraser tool
- A tool to replace one color with another
- A fill tool to fill any space with a color
- Tools to draw straight lines, rectangles, squares, circles, and polygons
You can also adjust the size of your brushes and erasers, view a grid for precision, and move your selection around using the rectangular select tool.
Creating Animated Sprites from Scratch
To create an animated sprite, you need to generate new frames. You can do this by clicking the plus symbol in the sprite editor panel. If you want to use the current frame as a basis for the next one, press control D to duplicate it:
You can also copy a part of your frame and paste it using the rectangular select tool.
By following these steps, you can create unique and custom sprites for your GameMaker projects. This adds a level of personalization and creativity to your game development process.
Importing Audio
Next, we will walk through the process of importing audio into our GameMaker project. This is a crucial step in the game development process, as sound effects and background music can significantly enhance the gaming experience. The process is straightforward and can be easily followed by beginners.
The first step is to create a sound in your project. To do this, right-click on the ‘Sounds’ folder in your asset browser and select ‘Create Sound’. This will create a new sound asset in your project which you can then rename. It is recommended to name your assets using the type of the asset in the name. For sounds, it would start with the prefix ‘sfx_’. For example, if you are importing background music, you can name it ‘sfx_bgmusic‘.
Once you have created your sound asset, you can import your audio file. Click on the three dots (…) next to the ‘Name’ field to open a file browser:
Navigate to your audio file, select it and click ‘Open’.
If you have a lot of audio files or if your files are long, you might want to consider compressing them under the ‘Attributes’ section. This will reduce the size of your audio files, which can help improve the performance of your game.
In the ‘Target Options’ section, set the ‘Output‘ from ‘Mono’ to ‘Stereo‘. This will ensure that your audio plays back in stereo, which can provide a more immersive gaming experience.
It is always a good idea to double-check the audio level of your sound assets. This is because sound effects and background music can often be much louder than expected, which can be jarring for players. To adjust the audio level, use the volume slider in the ‘Volume’ section. You can preview the audio by clicking on the play button:
Now, you have successfully imported an audio file into your GameMaker project. Remember, the right sound effects and background music can significantly enhance the gaming experience. So, choose your audio files wisely and always keep the audio level in check.
Creating Your First Object
Objects are a crucial part of game development in GameMaker as they are the entities that the player will interact with in the game.
Creating an Object
To create an object in GameMaker, follow these steps:
- Right-click on the ‘Objects’ folder.
- Hover over ‘Create’ and then click on ‘Object’.
- Name your object. It is common practice to use ‘obj_’ as a prefix. For instance, if we are creating a player object, we can name it ‘obj_player‘.
After creating the object, you need to select a sprite for it:
A sprite is a graphic that will be displayed for that object. You can select a sprite from our ‘Sprites’ folder. For example, we can select the player sprite for our player object:
Setting the Collision Mask
Next, you need to set the collision mask for the object. The collision mask is the area of the sprite that is considered when calculating collisions between objects. GameMaker usually defaults the collision mask to a box around the outermost pixels of a sprite:
However, it’s always a good idea to double-check this before moving on.
Object Properties
There are also some other properties that you can set for your object:
- Visible: Determines whether or not the object is visible when it is first instantiated.
- Solid: If set to true, whenever a sprite attempts to move into the object, it will automatically stop. However, the game will not process the collision as actually occurring. Hence, it is generally recommended to keep this off.
- Uses Physics: This relates to the physics system of the engine, which we won’t be covering in this article.
- Persistent: If checked, the object will remain when you swap between rooms and levels. This is useful when you want to maintain certain aspects of the game, like the player’s inventory or health bar, across different levels.
Once you have set all these properties for your object, you can proceed to create objects for your other sprites. However, note that you don’t need to create an object for your background as backgrounds are handled differently in GameMaker.
Building Levels
We’re ready to learn how to place the objects we’ve just created in our game level.
Level Size & Background
Begin by double-clicking on the room, which will present you with a blank black screen. The first thing we want to do is change the width and height of our level. Navigate to the left side of the screen and set the width to 750 and the height to 384. This size is suitable for working with 32 by 32 assets and for creating a small, simple scene.
Next, let’s set the background. You can select any of your sprites for this. For this tutorial, we will choose the dirt or sand texture. Initially, it will appear only in the corner, but don’t worry, we can adjust this. We can set the default color for our background. If you want to create multiple levels with the same background, changing the color slightly can give the illusion of a new environment. However, we will keep the default white color:
You can expand the background to the rest of the screen using the following options:
- Stretch: This will stretch the texture to the size of the room.
- Horizontal tiling: This will tile the texture across the screen if you made a very tall sprite.
- Vertical tiling: This will tile the texture vertically.
- Both: This will duplicate the texture across the screen.
For this tutorial, we will choose both the horizontal tiling and vertical tiling so we can fill out our entire level:
You can also set a speed for your background, which might be useful for creating a scrolling background for certain types of games.
Designing a Level
Now that our background is set, let’s place one of our objects. Ensure that you are on the ‘Instances’ layer, then drag your object in. If you want to create multiple instances of an object, you can hold the Alt key on your keyboard and click and drag:
If you make a mistake, you can use the Shift key to select multiple objects and then press Delete. Finally, add a player and an arrow to your scene.
Launch the game to see your newly created level:
Congratulations, you have created your first level!
Events Overview
We’ve learned how to place objects in our GameMaker scene. However, without any behavior, these objects are mere static sprites. To make them interactive, we need to add events and associate them with specific actions.
Understanding Events in GameMaker
An event in GameMaker is a specific circ*mstance or trigger that leads to the execution of certain code. For instance, when an object is created, destroyed, or interacts with the user in a certain way, specific code associated with these events is executed, thus defining the behavior of the object. To add events, we need to navigate to our ‘Objects’ folder and double-click on it:
This will present us with a list of events.
Types of Events
GameMaker offers a wide array of event types to choose from. Here are some of them:
- Create: The code associated with this event runs whenever an object is first spawned in.
- Destroy: This event triggers code whenever an object is destroyed.
- Step Events: These are events that occur every single frame. There are three types of step events: Begin Step, Step, and End Step.
- Alarm Functions: These are time-based events that allow us to run code at specific intervals.
- Draw Functions: These events, similar to step events, occur after the step. They follow the same pattern where Begin Draw runs, then Draw, followed by End Draw.
- Mouse Events: These events are triggered by mouse interactions, such as left, right, and middle click.
- Keyboard Events: Similar to mouse events, these are triggered by interactions with the keyboard.
- Gesture Events: These are specific to mobile games and include events like dragging, double tapping, pinching for zooming, rotating, etc.
- Collisions: These events occur when an object collides with another specific object.
- Other Events: These are a variety of events that can occur at different points, including animations, room starts, game starts, etc.
- Asynchronous Events: These are events that might take longer than a single frame to occur, such as grabbing data from a web-based database or saving and loading the game.
Each of these events gives you the flexibility to define complex behaviors and interactions for your game objects.
Understanding the Timing of Events
The timing of events like ‘Begin Step’, ‘End Step’, ‘Key Down’, ‘Key Press’ might seem a bit complex at first, but let’s break it down:
- When a key is pressed on the keyboard, the ‘Key Pressed’ event occurs.
- For every frame in which the key remains pressed, the ‘Key Down’ event occurs.
- Once the key is released, the ‘Key Up’ event is triggered.
Similarly, the sequence of step events is as follows:
- When the game first starts or an object is spawned, the ‘Create’ event fires.
- Every single frame after that, the ‘Begin Step’ event for every object occurs, followed by the ‘Step’ event and then the ‘End Step’ event.
- After the step events, the ‘Draw Begin’ event occurs, followed by ‘Draw’ and ‘End Draw’.
- Finally, all the ‘Draw GUI’ events occur.
Understanding these event sequences will help you better manage the behavior and interactions of your game objects. Next, we’ll get started on the GameMaker Language to be able to set these events and more in motion and link them to our objects.
Introduction To GameMaker Language
In this section, we will dive into the basics of writing in the GameMaker Language (GML), understanding comments, and executing our first functional line of code.
GameMaker Language is a programming language unique to the GameMaker engine. Its syntax and functionality are quite similar to Python, making it a good starting point for beginners. Moreover, the principles you learn while working with GML are applicable to many other programming languages.
To start coding, let’s add a Create event as follows:
Understanding Comments
When you open the GameMaker code editor, you will notice two pre-provided lines. These lines are known as comments. Comments are not functional code. They do not run or affect the game’s behavior in any way. However, they are crucial for documentation purposes, allowing you to write notes or descriptions for yourself or others working on the project.
A comment starts with two slashes, like this:
// This is a comment
And, you can add a description tag to your comments with an ‘@’ symbol:
// @description This is a description
This description is displayed on the list of events you have created for your object:
Writing Our First Line of Code
Let’s write our first line of functional code. It’s a tradition in programming to start with a ‘Hello, World!’ print statement when learning any new language. In GML, we use the ‘show_debug_message‘ function to print messages:
show_debug_message("Hello, World!");
The ‘show_debug_message’ function accepts a string as a parameter. A string is a sequence of characters enclosed in quotes. So, “Hello, World!” is our string here.
When you run the game, you will see the ‘Hello, World!’ message in the output window:
Congratulations on writing your first line of GML code!
Handling Key Events
Now, let’s reinforce our understanding of key events – ‘Key Down’, ‘Key Pressed’, and ‘Key Up’. We will write some code to print a message whenever the W key is pressed, held down, or released.
First, create the event for the W key, starting with the ‘Key Pressed’:
For the ‘Key Pressed’ event, we use:
show_debug_message("W Pressed");
Similarly, for the ‘Key Down’ event, we use:
show_debug_message("W Down");
And for the ‘Key Up’ event, we use:
show_debug_message("W Released");
If we run our game and press the W key, we can see the corresponding messages in the output window. This way, we can track the states of our key events:
Note that as soon as we press the W key, both ‘Key Down’ and ‘Key Pressed’ events happen in the same frame. ‘Key Down’ continues being called while we are still pressing W, and then finally no more messages appear on the console when we release the key. Also, remember to always close your game when you’re done running it. It’s easy to forget this when you’re busy editing your code, but it’s an essential practice to avoid potential issues.
Variables and Data Types
Variables are a fundamental part of any programming language, including GML. They can be thought of as a box that you use to store some type of data. This box can be passed around in the code into different parts of the code. Different parts of the code can look at the box, see the data on the inside, and modify the data on the inside. When it is passed to other parts of the code, that data is persistent.
Creating a Variable
To create a variable in GML, you just need to name the variable. Different programming languages have different preferences or naming conventions for variables. In GML, if the variable’s name consists of multiple words, we put underscores between the words. For instance, we could name a variable as ‘my_variable’.
Data Types
Variables in GML can hold many different types of data. Here are some of the most common data types:
- Real: A real number is any positive or negative number that includes or doesn’t include a decimal. For example, 1, 12, 123, or 123.555555.
- Integer: An integer represents any positive or negative number that does not include a decimal.
- String: Strings represent a word or a sentence. It can be a single letter, a single character, or anything you could type in a text file.
- Boolean: Booleans represent true or false values.
- Assets: Assets are anything in our game. You can reference them via an asset variable.
- List: A list defines a list of variables. For example, your grocery list where you might have apples, bananas, oranges, and so on could be considered a list of strings.
- Colors: You can define a color here if we want to, say, reskin our character depending on a certain state in our game.
Let’s now see how these variables work in the actual code.
Using Variables in the Code
For instance, let’s say we want to create a scenario where every time the W key is pressed, we reset our variable to zero:
And every time the W key is held down, we add one to our variable. Here’s how we would write this in GML:
my_variable = my_variable + 1
In the code above, we first initialize our variable and set it to zero. Then, we check if the W key is being held down. If it is, we add one to our variable.
To display our variable, we can use the debug message. The debug message expects a string, so if we want to display a number, we need to cast it to a string first. Here’s how we can do this:
show_debug_message("W Down " + string(my_variable))
By using the string function to cast our variable to a string we can then display it in the debug message:
Understanding variables and data types is crucial for programming in GML, so make sure to experiment with them and get comfortable using them in your code.
Movement in GML
In this section, we will learn how to implement movement in GameMaker using the GameMaker Language. This will involve writing code to add movement to our player and other game objects. Before we start, let’s review some basic math concepts related to coordinate grids.
Understanding Coordinate Grids
In a standard coordinate grid that you might have learned about in math class, there are four primary quadrants. The center of these quadrants is (0, 0). As you move to the right, the x-coordinate increases, and as you move to the left, the x-coordinate decreases. Similarly, as you move upwards, the y-coordinate increases, and as you move downwards, the y-coordinate decreases. Therefore, any point in this 2D space can be expressed with an x and a y number:
However, the coordinate system in GameMaker is a little different. In GameMaker, the coordinate system starts at the top left, which is the origin (0,0) of the game room. As you move to the right, your x-coordinate increases until you reach the end of the screen, which is referred to as the room_width.
Similarly, the y-coordinate starts at zero at the top and increases as you move downwards until it reaches the room_height. The bottom right corner is when your x-coordinate is at its maximum (room_width) and your y-coordinate is at its maximum (room_height):
It’s important to note that these coordinates do not end at the end of the room. They could go off to infinity. This is useful when you want to have some projectiles start way past the screen’s boundary and move left until they’re eventually visible by the user. Or, if you’re making a side-scrolling platformer, you can place level elements out to the side as far as you would like and have it all scroll as the player moves.
Player Movement
Let’s now write some code for player movement. The easiest way to manipulate a character’s x and y values is by changing them directly. In our ‘Key Pressed’, we can set the player’s x and y equal to a certain number:
// Setting player's x and y coordinatesx = 250;y = 250;
With this code, when we press the W key, the player’s position will move to (250, 250) on the grid. If we press it again, nothing happens because the x and y values are hard-coded to 250:
If we want the player to have some movement and make sure they move every frame, then we can use the hspeed and vspeed values. HSpeed corresponds to the horizontal speed (x-direction), and VSpeed corresponds to the vertical speed (y-direction). Here’s an example:
// Setting player's horizontal and vertical speedhSpeed = 5;vSpeed = 2;
In this case, when we press the W key, the player will start moving and will keep moving forever. Every single frame, the player will move 5 pixels to the right (x-direction) and 2 pixels downwards (y-direction):
However, we have a problem here. The player continues moving forever because we’re never setting the speed or the velocity back to zero. To solve this, we can set our velocity to a certain value when the W key is pressed:
And then set it back to zero when the key is released, using the ‘Key Up’ event:
Here’s the code:
// Setting player's velocity when key is pressedhspeed = 5;// Setting player's velocity back to zero when key is releasedhspeed = 0
With this code, when we press down the W key, the player moves. When we let go of the W key, the player stops moving. This is the most basic player movement you could implement. However, we can keep all our code inside the ‘Key Down’ if instead of using the player’s velocity, we use it’s coordinates directly as follows:
Note that x += 5
is the same as writing x = x + 5
. It’s summing up 5 to the value of a variable that has already been initialized and attributing the result of the operation back to the variable.
Implementing WASD Movement
Now that we have made the player move in one direction (to the right when we press W), let’s implement basic WASD movement for the player. This means, the player should move up when we press W, right when we press D, down when we press S, and left when we press A:
Using the ‘Key Down’ event, we’re going to adjust the player’s x or y coordinate manually as seen below:
// Key Down - Wy -= 5// Key Down - Ax -= 5// Key Down - Sy += 5// Key Down - Dx += 5
In this code, we are checking if a certain key is pressed and then adjusting the player’s x or y coordinate accordingly. Note that, in GameMaker’s coordinate system, we subtract from the y-coordinate to move up and add to it to move down.
However, there is a slight issue here. If we decide the speed is too fast or too slow, our current implementation means we have to manually adjust all those values. Instead, we can use a variable to hold the speed data. In this way, we only need to change this variable to adjust the player speed for all four directions:
To do this, first make the variable ‘player_speed’ as type Real. Then, adjust your code to use the variable:
// Key Down - W y -= player_speed // Key Down - A x -= player_speed// Key Down - S y += player_speed// Key Down - D x += player_speed
Let’s now explore another approach to moving objects in GameMaker. While before we were directly modifying the x and y coordinates of the player to create movement, we’re going to look at a different method involving the use of speed and direction variables. This method is especially useful when we want to create more complex movement patterns, such as circular motion.
Direction and Speed
Our new method of moving things in GameMaker involves using two variables: direction and speed. These two variables will be used to control the movement of our arrow object.
- Speed: This variable determines how fast our arrow moves.
- Direction: This variable determines the direction in which our arrow moves. The direction is measured in degrees, with 0 degrees pointing to the right, 90 degrees pointing upwards, 180 degrees pointing to the left, and 270 degrees pointing downwards. A full circle is 360 degrees, so a direction of 360 degrees is equivalent to 0 degrees.
Let’s create a script for the ‘Create’ event on our arrow and initialize our speed and direction variables:
// Create event for the arrowspeed = 1direction = 0
With this code, our arrow will start moving slightly to the right:
If we change the direction to 90, the arrow will start moving upwards.
Changing Direction and Speed
We can also change the direction and speed dynamically to create more complex movement patterns. For instance, if we increment the direction by one every frame, the arrow will start moving in a circle. This is because the direction is being adjusted slightly every frame, causing the arrow to turn gradually:
// Step event for the arrowdirection += 1
If we also change the speed every frame, the arrow will start moving in larger and larger circles until it eventually moves off the screen:
// Step event for the arrowdirection += 3speed += 0.05
Even though we’re controlling the movement of our arrow using the direction and speed variables, the arrow still has horizontal and vertical speed (hspeed and vspeed). These two variables are automatically calculated by GameMaker based on the current speed and direction. Therefore, if we print the horizontal speed of our arrow, we will see that it changes as the direction and speed of the arrow change:
// Step event for the arrowshow_debug_message(hspeed);
Similarly, the x and y coordinates of the arrow still exist and are automatically updated by GameMaker based on the hspeed and vspeed. Therefore, we can still check the position of our arrow even though we’re not directly modifying the x and y coordinates in our code:
// Step event for the arrowshow_debug_message(x);
In a nutshell, using speed and direction variables can be a powerful way to create complex movement patterns in GameMaker. However, it’s important to remember that the X, Y, hspeed, and vspeed variables still exist and can be used in conjunction with speed and direction.
Alarm Events
Alarms are not just the thing that wakes you up every morning. In GameMaker, alarms are the key to time-based events. They are used to trigger certain actions after a specified number of frames.
Setting an Alarm
Let’s start with an example of setting an alarm. We will use ‘Alarm 0’, which is an event that will occur whenever we tell it to occur. For instance, we can set Alarm 0 to change the player’s x and y coordinates to 250 each time it is triggered:
x = 250y = 250
However, we do need to trigger it, which we’ll do in the Create event for the player object:
// Set Alarm 0 to change player's coordinatesalarm[0] = 600
In the above code, Alarm 0 is set to 600. This means that after 600 frames, the event specified in the Alarm 0 event will occur. Here, we are setting the player’s x and y coordinates to 250 each time Alarm 0 is triggered.
In GameMaker, alarms count down from the value you set them at. So if we set Alarm 1 to 300, then in five seconds (assuming a frame rate of 60 frames per second), whatever we put in our Alarm 1 event will trigger:
// Set Alarm 1 to trigger in 5 secondsalarm[1] = 300
We can also make an alarm self-looping by setting its value within the alarm event itself. For instance, if we set Alarm 0 to 50 within the Alarm 0 event, the event will retrigger every 50 frames:
// Set Alarm 0 to retrigger every 50 framesalarm[0] = 50
Ping Pong Arrow
Let’s apply what we’ve learned with a practical exercise. The challenge is to make the arrow move right for one second, then left for one second, and keep repeating this pattern indefinitely:
We’ll use the alarm system to achieve this. Once you’ve given the exercise a try, you can view the solution below.
Ping Pong Arrow Solution
Here’s a possible solution to make a ping pong arrow:
// Set initial direction and speed in the arrow's create event. Set the alarm to loop.direction = 0speed = 8alarm[0] = 60// In Alarm 0 eventdirection = 180 // Change direction to leftalarm[1] = 60 // Set alarm one to change direction after 1 second// In Alarm 1 eventdirection = 0 // Change direction to rightalarm[0] = 60 // Set alarm zero to change direction after 1 second
The above solution uses two alarms to continuously change the direction of the arrow. However, if you’re familiar with angular math, you might realize that there’s a simpler solution that only uses one alarm:
// In Alarm 0 eventdirection += 180 // Add 180 to current directionalarm[0] = 60 // Set alarm zero to change direction after 1 second (60 frames)
In this solution, we’re taking advantage of the fact that 360 degrees is the same as 0 degrees, so adding 180 to the direction will always switch it between right (0 degrees) and left (180 degrees).
Practice using alarms to create time-based events in your games!
Random Number Generation
This section will focus on how to implement randomness in the GameMaker Language. Specifically, we’ll be going over how to make an arrow randomly appear in different positions on the screen. This will be a great introduction to the concept of randomness, which can later be used to create more complex and unpredictable game scenarios.
Random Positioning
To start, we’re going to comment out or remove the existing code in the alarm that changes the arrow’s direction every time Alarm 0 goes off. Instead, we’re going to make the arrow appear at a random position every second.
First, we’ll set the arrow’s x position to a random range. The ‘random_range’ function is the primary way of doing randomness in GameMaker. It works by generating a random number between a minimum and a maximum number, separated by a comma. For instance:
x = random_range(0, 300)
This will generate a random number between zero and 300 and assign it to the x position of our arrow. We can do the same thing for the y position to make it appear randomly in both dimensions.
y = random_range(0,300)
But what if we want the arrow to appear anywhere on the screen, not just within a 300 by 300 box? We can use the ‘room_width’ and ‘room_height’ variables, which represent the size of our room, as our maximum values:
x = random_range(0, room_width)y = random_range(0, room_height)
By using these variables, the arrow can now spawn anywhere in the room. However, there’s a potential issue here. The arrow can spawn inside walls or other objects, which can lead to problems if these arrows are supposed to move around or interact with these objects:
Preventing Arrows from Spawning Inside Walls
We need to modify the code so that the arrows don’t spawn inside the walls. We can do so by controlling the random range to ensure the arrows only spawn in valid locations. This will involve adjusting the minimum and maximum values used in the ‘random_range’ function.
Since we know that the walls are 32 pixels thick, we can adjust our random range to account for this. Instead of starting from zero, we can start from 32 pixels away from the edge. Similarly, we can subtract 32 from the room width and height to avoid spawning arrows inside the walls on the other side:
x = random_range(32, room_width - 32)y = random_range(32, room_height - 32)
This ensures that the arrows will always spawn at least 32 pixels away from the room borders, preventing them from spawning inside the walls.
Spawning New Objects
Now, let’s combine what we’ve learned about alarms and random positioning to spawn new enemies or obstacles. One common use case for alarms is to spawn new enemies or waves of enemies at regular intervals.
To do this, we’re going to use the ‘instance_create_layer’ function. This function takes several arguments: the x and y coordinates, the layer, and the object to spawn. We can use the random ranges we’ve defined for the x and y coordinates to spawn the arrows at random locations:
var arrow_x = random_range(32, room_width - 32)var arrow_y = random_range(32, room_height - 32)instance_create_layer(arrow_x, arrow_y, layer, obj_arrow)
However, you may notice the arrows still spawn slightly in the walls. We can add some padding to our spawn coordinates to ensure they stay within our walls:
// In player's Alarm 2 eventvar arrow_x = random_range(50,room_width-50)var arrow_y = random_range(50,room_height-50)instance_create_layer(arrow_x,arrow_y,layer,obj_arrow)alarm[2] = 300
Also, we’re setting the alarm back up to 300 (or any other number) to spawn another arrow every few seconds.
Now you should have a good understanding of how to use randomness in GameMaker to create more dynamic and unpredictable game scenarios.
Collisions and Bouncing
Collisions are crucial in any game as they help us detect when two objects are interacting with each other. This is fundamental to almost every game mechanic in existence. The first thing we want to do, though, is to manage the alarms on the player. Let’s increase the alarm time to 300. This will give us a manageable amount of arrows and we won’t get spammed with them when we’re testing our game:
// In player's Create eventalarm[2] = 300
Implementing Bounce Behavior
Next, we’ll add a collision event for our arrow object. In GameMaker, you can add an event for whenever an object collides with any other object. For now, we will add an event for when the arrow collides with the wall:
When the arrow collides with the wall, we want it to bounce off and continue moving around the screen, similar to the famous DVD logo screensaver. In GameMaker, this can be achieved quite simply with the move_bounce_all
function. The parameter for this function determines whether or not you want to use GameMaker’s advanced collision system. For now, we don’t need to worry about this, so we will set this to false:
move_bounce_all(false)
Currently, our arrow isn’t moving. To fix this, we need to set a speed and a direction for the arrow. Let’s set the speed to 10 and the direction to 45 degrees. This will cause the arrow to start moving and bouncing off the walls:
// In arrow's Create event speed = 10direction = 45
Right now, all the arrows start in the same direction. To make the game more interesting, let’s randomize the direction of the arrows when they spawn. We can do this by setting the direction to a random value between 0 and 359 degrees:
direction = random_range(0,359)
Adding Player-Arrow Interaction
Now that we have multiple arrows bouncing around the screen, let’s make the player interact with these arrows. We will add a collision event for when the player collides with the arrow:
When this happens, we want the room to restart. This can be achieved by using the room_restart
function:
room_restart()
With this, we have a basic game where the player has to avoid the arrows. However, there’s a problem – the player can walk inside the wall and avoid the arrows completely. Fixing this will require more than just simple collision events, which we will cover in the next section.
Conditionals
Conditional statements, also known as ‘if statements’ in programming, are crucial components of code that you we’ll frequently use. The basic structure of an if statement involves a condition that evaluates to true or false, known as a boolean expression. If the condition is true, the code within the if statement’s brackets runs. If it’s false, the code does not run.
Creating a Basic Conditional Statement
To write our first conditional statement, we will use an example involving an arrow collision. The code for this would look something like this:
if (a) { // code to run if 'a' is true}
In this code snippet, ‘a’ is the condition that will evaluate to either true or false. If ‘a’ is true, then the code within the brackets will run. If ‘a’ is false, then the code will not run.
For instance, if we want to check whether 2 is equal to 2, we would write:
if (2 == 2) { // code to run if 2 equals 2}
In this case, ‘2 == 2’ is the condition, and because it is true, the code within the brackets will run. Note the use of two equal signs (==), which is used for comparison in programming. This is different from the single equal sign (=), which is used for assignment.
Using Conditionals to Handle Collisions
One common use of conditionals in game development is to handle collisions. For example, when a player character runs into a wall, we want to stop the character from moving through the wall. To do this, we can use a conditional statement to check if the player is colliding with the wall.
We will first create a boolean variable called ‘collided’ in our player’s object:
This variable will be set to true when a collision with a wall occurs and false otherwise:
// Player Object Collides with Wall eventcollided = true
With this setup, we can use a conditional statement to check the value of ‘collided’ before allowing the player to move. If ‘collided’ is false, the player can move. If ‘collided’ is true, the player cannot move. Let’s do this for all keys of our WASD movement. For instance:
// In the Key Down event for the D keyif (collided == false) { x += player_speed}
Similarly, wrap the already existing code in each of the other keys up in an if statement.This setup works well for preventing the player from moving through walls, but there is one issue: Once ‘collided’ is set to true, it never gets set back to false. This means that once the player hits a wall, they can never move again. To fix this, we need to set ‘collided’ back to false at the start of each frame:
// In player's Begin Step eventcollided = false
With this change, ‘collided’ will be set to false at the start of each frame, allowing the player to move again. However, we also need to check for potential collisions before moving the player due to the time in which each event occurs inside a single frame.
Checking for Potential Collisions
To check for potential collisions before moving the player, we will use both Step Begin and Step End events. Let’s create 2 new variables to save the player’s position, as follows:
Then, in our player’s Begin Step, set these variables to the player’s current position:
collided = falsestep_start_x = xstep_start_y = y
If a collision occurs after moving the player, we will reset the player’s position to the saved position in the Step End event:
if(collided == true){ x = step_start_x y = step_start_y}
With this, we have a complete collision detection system using conditional statements. The player can move freely until they hit a wall, at which point they will stop and cannot move through the wall.
Lastly, remember to remove the if statements we had added to our WASD keys in their Key Down events!
Sprite Transformations
Sprite transformations are important for creating dynamic and interactive game elements. For instance, we can use them to change the direction an object points in or to modify the size of an object.
Arrow Pointing Direction & Scale
Consider a game where an arrow is always pointing downwards, regardless of the direction it is moving. This is not how an arrow should function in a game. Ideally, the arrow should point in the direction it is moving. This is where sprite transformations come to the rescue.
GameMaker provides a way to change the image angle of an object, just like we can change the direction of our object. By setting the image angle equal to our direction, we can change the angle at which our sprite renders. However, this might not always give the desired result. For example, if an arrow sprite is initialized pointing downwards, simply setting the image angle equal to the direction will not make the arrow point in the direction it is moving. This is because GameMaker handles direction differently.
Here’s how GameMaker handles direction:
- 0 is to the right
- 90 is upwards
- 180 is to the left
- 270 is downwards
So, to make our arrow point in the direction it is moving, we need to adjust our direction accordingly. If our arrow sprite is initialized pointing downwards (i.e., at 270 degrees), we need to add 90 to our direction to make it point to the right (at 0 degrees). The code to do this is:
// In arrow's Step eventimage_angle = direction + 90
Now, the arrows will point in the direction they are supposed to be pointing:
In addition to changing the angle of a sprite, we can also change its scale in the x and y directions. For example, if we set both the x and y scale to 2, the arrow will appear larger. We can do this with the following code:
// In arrow's Create eventimage_xscale = 2image_yscale = 2
Handling Collision Issues
While testing our game, we might notice that the arrows are getting stuck in the wall. This is because the arrows are bouncing into the wall twice in the same frame, causing them to reverse their direction twice and hence, leading to no change in direction:
To fix this, we can add a new boolean variable for our arrow, say ‘collided’. We can set ‘collided’ to false at the start of each step and to true when we collide with the wall:
// In arrow's Begin Step eventcollided = false
We’ll only bounce, however, if we haven’t already collided:
// Arrow Object Collides with Wall eventif(collided == false){ move_bounce_all(false)}collided = true
Rotating the Player
Just like we rotated our arrows, we can also rotate our player according to our key presses. However, we need to physically change its angle and in some instances, its scale, in each of the ‘Key Down’ events. This can be done with the following code:
// when pressing the 'A' keyimage_xscale = -1image_angle = 0// when pressing the 'D' keyimage_xscale = 1image_angle = 0// when pressing the 'S' keyimage_xscale = 1image_angle = 270// when pressing the 'W' keyimage_xscale = 1image_angle = 90
With this, our player will properly rotate when they move, and our arrows will properly rotate when they hit the walls:
Remember to always test your game to identify and fix any issues that may arise!
Playing Audio in GML
In this section, we’ll learn how to play audio in GameMaker. We will be using a sound file that we have previously imported and named ‘sfx_bgmusic’.
Playing the Sound
Once your sound file has been imported, you can call it from any object and in any event. To play the sound, you will need to use a simple function that has 3 parameters:
audio_play_sound(sound, priority, loop)
These parameters are:
- The name of the sound effect, which in our case is ‘sfx_bgmusic’.
- The priority of the sound. You can insert any number here. Higher-priority sounds will be played over lower-priority sounds. This can be useful when you want to ensure a sound effect is heard above the music. When the sound effect plays, the music will temporarily stop and then resume once the sound effect has finished.
- Whether or not you want the sound to loop. For a music track, you would typically set this to true so that the music continues to play.
When writing a function, the parameters will be displayed at the bottom of your screen. Parameters that are optional will be shown in brackets, while required parameters will not have brackets:
Let’s play our background music when the player is created like so:
audio_play_sound(sfx_bgmusic,1,true)
Stopping the Sound
When testing your game, you may notice that the music continues to play even when the player dies. This is because any audio tracks that haven’t finished will continue to play even if the room changes or restarts. For a looping audio track, this means it will play forever. To prevent this, we need to stop all audio before restarting the room when the player gets hit with an arrow:
audio_stop_all()
By inserting this line of code before restarting the room, the music will stop when the player dies and then start again when the room restarts, as expected.
Displaying Text
The ability to display text allows you to communicate with the player, provide instructions, show scores, or even advance the narrative of your game.
The game we are building is a time-based survival game. The player needs to avoid arrows for as long as possible. When the player dies, we want to display the time they survived and their score on the screen. This gives the player a target to beat in their next attempt, making the game more engaging.
Drawing Text on the Screen
First, let’s add a new event to our player. We’ll use the Draw GUI event. Draw GUI happens after all of the draw calls that draw all of our sprites. This means that anything we put in the Draw GUI event will render above all of the other sprites in our game. This is ideal for displaying text, as we want it to be visible and not obscured by other game elements.
To add the Draw GUI event, follow these steps:
- Click on the ‘Add Event’ button.
- Select ‘Draw’ from the drop-down menu.
- Choose ‘Draw GUI’ from the list of options.
With our Draw GUI event set up, we can now add the code to display the text on the screen. This is achieved through the function draw_text
.
The function draw_text
requires three arguments:
- The x-coordinate of the top left corner of the text box.
- The y-coordinate of the top left corner of the text box.
- The text you want to display on the screen.
Here is an example of how to use the draw_text
function:
draw_text(50, 50, "Score: ")
This line of code will display the text ‘Score: ‘ at the coordinates (50, 50) on the screen.
Displaying the Player’s Score
To display the player’s score, we need a variable to store this value. Let’s create a new variable called time_alive
and set it as an integer. This variable will keep track of how long the player has survived in the game:
Now, we can display the player’s score on the screen by adding the time_alive
variable to our draw_text
function. However, we need to convert the integer to a string before we can display it. This is done using a typecast:
draw_text(50, 50, "Score: " + string(time_alive))
The string(time_alive)
function converts the integer time_alive
to a string so that it can be displayed on the screen.
With our score display set up, we need to update the score as the game progresses. We can do this by incrementing the time_alive
variable every frame. This can be done using the ++
operator:
This line of code adds one to time_alive
every frame, effectively keeping track of how long the player has survived in the game:
That’s it! Now you know how to display text on the screen in GameMaker. You can use this feature to display messages to the player, show scores, or even advance the narrative of your game. Go ahead and experiment with this feature to make your game more appealing.
Finalizing Your Project
In this section, you’ll learn how to export your game project in GameMaker. After spending hours coding and debugging, it’s finally time to show off your creation to the world. We will go through the process of cleaning up the code, balancing the game, and finally exporting the project.
Cleaning & Balancing Game Code
Before we export our game, we need to remove any unnecessary code. This could be any code that we wrote for learning purposes that is not needed in the final version of our game. Here are the steps to clean up your code:
- Go to your player and navigate to the ‘Create’ event. Remove any unnecessary code such as the ‘Hello world’ message.
- Check all the steps and events, remove any unused alarms (Alarm 0 and Alarm 1 , in our case) or variables (e.g., my_variable).
- Remove unused events, such as ‘Key Press’ and ‘Key Up’ for the W key.
- Go to the arrow and check the ‘Create’ event. Again, remove any unnecessary alarms (i.e., Alarm 0).
Remember to ensure you have only what you need by revising the variables and events of all your objects!
Before releasing your game, it’s important to ensure that it’s well-balanced. This means it should be fun, not too hard, and not so easy that it’s boring. Play your game and adjust the difficulty until you reach a balance that feels right. For the game we’ve just created, for instance, you could adjust the arrow speed and the time between arrow spawns.
Exporting the Game
Once you’re satisfied with your game, it’s time to export it. Follow these steps:
- Click ‘Build’, then ‘Create Executable’:
- Choose whether to package your game as an installer or a zip file. If you’re sharing the game with strangers, it’s recommended to choose the zip file option as it does not require administrator permission to install:
- Save the zip file in your project’s Assets folder.
- Once the game is done building, extract the files from the zip file. You’ll see your game, along with some other files such as data files and options:
- Double-click the executable to launch the game.
Now your game is ready to be shared with the world. You can make variations, build it again, and really do whatever you want.
GameMaker Tutorial Summary
Congratulations on completing our GameMaker tutorial!
You’ve taken a significant step toward mastering game development with GameMaker Studio by developing this arrow-dodging game. From nothing, you’ve discovered how to use things like events, sprites, GML, and more to craft these into a fully-fledged game project ready to be shared with your friends. By applying the skills and techniques covered in this tutorial, you’re now equipped to bring your game ideas to life and potentially even create the next indie hit.
If you’re eager to continue honing your craft, though, look no further than our GameMaker Academy. This Learning Pathway is meticulously designed to help you build a strong, comprehensive skill set through a series of engaging, project-based courses. From casual games to RPGs, you’ll explore a variety of genres, all while bolstering your portfolio with impressive projects.
Remember, practice makes perfect, so keep experimenting and building upon the foundation you’ve established here. Good luck with your future GameMaker projects!
Did you come across any errors in this tutorial? Please let us know by completing this form and we’ll look into it!
FREE COURSES
FINAL DAYS: Unlock coding courses in Unity, Godot, Unreal, Python and more.