Make An Endless Platformer With Fire Jump


Make An Endless Platformer With Fire Jump

Welcome to the Fire Jump tutorial! This series will take you through developing an infinite platformer game in GameMaker Studio 2 using Drag and Drop™. You will learn how to make a playable character, generate infinite obstacles, build a solid game loop along with menus and much more.

This tutorial will take you through the process of making the game from start to finish, step-by-step, and also introduce you to the various elements of GameMaker Studio 2. Everything is explained in an easy to understand manner, so you can follow this tutorial even if you have never used GameMaker Studio 2 before, and there is enough useful information for intermediate users to enjoy as well.

undefined

This is Part 1 of a 4-part series, all of which are available for free on this site. You can refer to the index page to navigate to the other parts.

Here is a video version of this tutorial:

Goal

Our goal is to create a game where you control a firefighter as they scale a building by jumping on randomly generated windows, rescuing trapped civilians while putting out fires along the way. The game will consist of three different screens:

  • Title screen
  • Main game
  • Game over screen

We will make use of a variety of image assets for our in-game elements and interface animations, which you can download by clicking here.

Overview

This page is divided into the following sections:

  1. Starting a Project
  2. Creating and Importing Assets
  3. The Game Room
  4. Events and Actions
  5. Player Controls
  6. Bouncing Off Windows
  7. View Scrolling
  8. Spawning Windows
  9. Street Area

Starting a Project

Let’s start by creating a new project which we’re going to use to develop our game.

Open the GameMaker Studio 2 IDE and click on “New”, then select "New Blank" as we'll be starting with a blank project.

Under "New Blank Template", choose “Drag and Drop” as that is what we’re going to use to program our game. Finally, enter a name for your project (you can name it “Fire Jump”) and click on "Let's Go!".

undefined

After creating your new project, you will see it open up in the GameMaker Studio 2 IDE:

undefined

The Asset Browser is where we create and manage all of our assets, which includes all the art (sprites), objects, rooms, and other assets that we use in our game. The Workspace is where we edit those assets and program our game.

Creating and Importing Assets

Let’s start by creating a sprite, which is an image asset that can be used for in-game objects and animations. Select the Sprites group using the left mouse button, go to the undefined “Create Asset” menu at the top and double click on “Sprites” to create a new sprite asset. Name this asset “spr_player_air” -- we’re going to use this as our player’s “in-air” image.

undefined

Note: The “spr_” prefix denotes that the asset is a sprite. Including this prefix is not required, however doing so will result in easily recognizable asset names.

In the Workspace on the left, you will see a Sprite Editor open up. Here you can rename the sprite, change its size and use the “Edit Image” option to open the Image Editor, which will allow you to draw on that sprite.

undefined

We’re going to use the “Import” option to load an external image file, which will be imported as our player’s in-air sprite. Click on Import, navigate to the assets folder that you downloaded and from a Character folder, select “spr_player_air”.

undefined

You will see the imported image in the Sprite Preview pane. Here we need to adjust its “origin”, which is the point on the sprite that it rotates around. For this sprite we want its origin to be at the center, so open the drop-down menu in the top right corner of the Sprite Editor (where it says “Top Left”) and change it to “Middle Center”.

Side-note on Origin: The origin is not only used for rotation, but also as the central point of an object to which its location points. You will learn more about the origin point as you progress through this series.

Let’s import the images for the window that the player will jump on. Select the Sprites group in the Asset Browser, go into the Create Asset menu and add a new sprite. We’ll call this “spr_window”. In the Sprite Editor, click on Import, and navigate to the sprites folder for this tutorial. We’re not going to import just one image but three: these are variations of the same window which we will show based on what kind of window it is!

In the "Building" folder, select the files “spr_window_0”, “spr_window_1” and “spr_window2”, then click “Open” which should import those three images into the same sprite asset as “sub-images”!

undefined

Note: If the order of your sub-images is not the same as shown above, please drag the sub-images around in the frames section of the Sprite Editor as this order will be important going forward.

Sub-images are usually used for animated sprites, which we will do for another sprite in this tutorial — however, this is not an animation, so we’re going to set the FPS at the top-left corner of the Sprite Editor to 0. Doing this ensures that your sprite doesn’t animate when it’s used in the game.

We also need to set an origin point for this sprite. The window doesn’t move or rotate, so the origin should not matter in that regard, however we will use the origin point to spawn civilians and fire on the window. To make sure that they are placed right on top of the window sill, we need to place the origin point atop the sill as well, right in the middle. Drag the origin pointer from the top-left corner of the image and place it here:

undefined

With that done, we need to import one final image for this part of the tutorial. Just as we did with the previous sprites, create a new one called “spr_brick_tile” and import the file with the same name from the tutorial’s sprites folder. This will be the brick image that is tiled as the game’s background.

undefined

We have imported three game elements: the jumping player, the window that the player will jump off, and a brick sprite that will be tiled in the background. We’re going to add them to our game, however these are only images, and to program the behavior of our player and windows, we need to create “objects”.

Objects

An object can act as a visual part of the game that has a sprite attached to it (to control how it appears) and a list of events (to control what it does). Our player and window will be objects, and they will use the sprites that we have imported. However, objects can also be used as non-visual controllers that have no sprite attached, but still have a list of events performing their behaviors in the background.

An object can act as a visual part of the game that has a sprite attached to it (to control how it appears) and a list of events (to control what it does)

Let’s create our first two objects. Select the “Objects” group in the Asset Browser, go into the “Create Asset” menu at the top, and create two objects: "obj_player" and "obj_window".

In the workspace, you will see the Object Editor open up for each object you have created. Under the “Sprite” section of the Object Editor, you can click on “No Sprite” to open the Asset Explorer, where you can select a sprite to be assigned to the object. So go ahead and use the sprite spr_player_air for obj_player, and spr_window for obj_window.

undefined

Note: See how our naming convention makes it easier to identify the assets, as we instantly know that spr_player_air is the player sprite, and obj_player is the player object.

The Game Room

Now that we have the basic objects that we need, we’re going to set up our game “room”. A room is an asset that serves as the game’s screen, so for example, you can have one room for the main menu and another for the game. You can easily switch between rooms and the currently active room will appear in the game’s window.

In the Asset Browser, open the “Rooms” group and you will see that there is already a room present. Let's rename it first -- right click on it and select "Rename" (or press F2) and name it rm_game (since our game will take place here).

Double click on the room asset to open the Room Editor:

undefined

On the left you have the Room Properties, and in the centre the main room area. This space is what you will see when you run your game, and this is where we want our game to take place.

First of all, let’s adjust the size of this room, which will be the resolution of our game. Go into the Room Settings at the bottom-left corner of the IDE, and set the width and height to 1080 and 1920 respectively.

undefined

Note: We’re using a resolution of 1080x1920 instead of 1920x1080 as we want to use a mobile-like aspect ratio. This will enable you to easily port this game to any mobile platforms later on!

Tiled Background

Now that we have an appropriately sized room, let’s give it a background so it’s not blank anymore. Go into the Layers section in the top-left corner of the Room Editor, and you will see the two default layers: “Instances” and “Background”. We’re going to look at the Instances layer soon, but let’s first assign a background image to our room.

Select the “Background” layer, and just below the Layers section you will see the Background Layer Properties. Click where it says “No Sprite”, which will open up the Asset Explorer (similar to the one we used in the Object Editor). Here you can select a sprite to assign as the room’s background, so go into the Sprites group and select spr_brick_tile.

You will notice that the tile appears in the room, but only in its top-left corner. To tile it all over the room, go into the Background Layer Properties and enable both “Horizontal Tile” and “Vertical Tile”. Doing that will fill the room with the brick tile!

undefined

Note: If you see a grid overlay in the room, you can press G to disable it.

Now let's see how we can place objects in rooms.

Instances

When you place an object in the room, it becomes an “instance” of that object. This means that you can have one object asset and place multiple instances of it in a room, with each instance having its own unique properties.

Instances are placed in Instance Layers, and the “Instances” layer that is present in the Layers section is one such layer. Select that layer, and drag in the window object from your Asset Browser.

undefined


You have a window instance now! Drag in some more and create a line-up of windows on the building for our player to climb on.

Where is our player, though? Let’s add it in as well, but in a new layer. Create a new Instance layer using the buttons at the bottom of the Layers panel, and name it “Player” (press F2 or select “Rename Layer” in the right-click menu). Make sure that it is placed above the “Instances” layer, and if it’s not, you can simply drag it to the top.

undefined

Why are we creating a new layer? The order of the layers determines when its instances are drawn, so placing a layer higher in this list ensures that it is drawn above the other layers. This means that our “Player” layer will be drawn above the “Instances” layer, to ensure that the player instance appears above the windows.

Drag in the player object into the “Player” layer to create an instance, and place it somewhere around the bottom-center area of the room. Your room should be looking something like this now:

undefined

Now that our room is ready, let’s see how we can program the behavior of our objects.

Events and Actions

We’re going to take a look at the two most important features when it comes to programming with Drag and Drop: Events and Actions.

Actions are used to program your object -- you can use an action to tell the object to move, jump, rotate, destroy itself, and so on.

undefined

This is a pretty simple concept, however there is one question that makes it a little complicated: when do we run an action?

As a solution to that problem, GameMaker has “events”. You will see an Events window in the Object Editor, with an “Add Event” button that opens up a list of all the available events:

undefined

Any of these events can be added to an object, and any number of actions can be placed inside an event. Each event has its own behavior as to when it runs!

For example, the Create event runs when the instance is created, which means that it runs only once. Then there is the Step event which runs every frame of the game, and since there are 60 frames in a second by default, that event runs 60 times in one second.

There are also input events that run based on keyboard and mouse input. This enables us to easily create controllable characters by adding actions to such events!

Player Controls

We’re going to program our player to do two things:

  1. Automatically jump on creation
  2. Move left or right depending on keyboard input.

Let’s start with the first one! Go into the obj_player object, and in the Events window, click on Add Event. In the list that opens, click on Create to add that event into the object. Doing so will open the event in a new window, which is where you can add actions:

undefined

The “Toolbox” panel to the right of that window allows you to search for actions and add them to your event. We added the Create event so we could ask the player to jump when it’s created, so let’s find an action for that! Scroll to the “Movement” section of the Toolbox and find the “Set Speed” action (or just search for it through the Search field at the top). Once you’ve found the action, drag and drop it into the empty space on the left:

undefined

Using this action, we can tell the object’s instance to move in any given direction. We want it to have a vertical speed in the beginning so it can jump up, and to achieve that, we need to set the “Type” of this action to “Vertical”. Before we give it a speed however, let’s look at how movement works.

Moving Around

Our room has two dimensions, one horizontal and the other vertical -- hence resulting in a 2D game. We use these two dimensions to move our instances around the room.

The horizontal dimension is called the X axis, and the vertical dimension is called the Y axis. Coordinates are usually written in the (X, Y) format, so for example, if an instance is at 20 pixels on the X axis and 10 pixels on Y, it would be written as (20, 10).

Room coordinates start from the top-left corner of a room, which is (0, 0). The X value increases as you move right, and the Y value increases as you go down.

undefined

This means that to move an instance, we need to add or subtract its position on the X or Y axis.

  • +X: Adding to the X axis moves it to the right
  • +Y: Adding to the Y axis moves it down
  • -X: Subtracting from the X axis moves it left
  • -Y: Subtracting from the Y axis moves it up

We’re going to use this technique to move our player on both axes, so let’s continue with implementing our initial jump.

Tip: You can see the coordinates at any point in the room by hovering your mouse on that point and reading the coordinates at the bottom of the Room Editor.

undefined

Jumping

Note: When we’re programming an object in this tutorial, I will be referring to it as an “instance”, because any actions in the object will be carried out by its instance in the room.

After setting “Type” to “Vertical”, we need to specify a speed for the instance’s vertical axis. Since we need to subtract from the Y axis to move it up, we’re going to enter -35 as the speed.

undefined

This action will make our player move up at a speed of -35. If you run the game now, you will only see the player moving up, as we haven’t implemented gravity to make it fall down. So, let’s do that!

To run the game, press F5 or click on the play button at the top of the IDE
undefined

We need to use the “Set Gravity Force” action, which is present in the “Movement” section of the Toolbox, same as the previous action. Keep in mind that you can always search for the action, and once you have found it, drag it into the event.

The force of gravity can simply be 1, but feel free to change this (and the initial vertical speed) as this is your game and you can make it feel exactly how you want!

This is what your Create event should look like now:

undefined

Running the game now will show the player jumping and then falling down. What we need now is a way for it to move horizontally and bounce off the windows.

Note: You can pan around the event space by holding the middle mouse button, or by holding the Alt key if you're using Laptop Mode. This will come in handy if you have a lot of actions in one event.

Horizontal Movement

We want the player to move horizontally using the left and right arrow keys. As mentioned in the part on Events & Actions, GameMaker has events for keyboard & mouse input. We’re going to use a couple of them for our left and right arrow keys.

In the Events window for obj_player, click on “Add Event”, go under “Key Down” and select the “Left” event. This will add an event called “Key Down - Left” to your events list. Repeat the same action but this time, select the "Right" event. Now along with the Create event, you will have two new events:

undefined

These events are for the left and right arrow keys respectively. In each event we are simply going to modify the X position of the instance so it moves horizontally.

Go into the “Key Down - Left” event (you can double click on an event to open its window) and here, search for the “Set Instance Variable” action and drag it in. This action allows us to modify any one of the instance’s properties (also known as “instance variables”) and the property that we need to modify should be selected from the given list.

Make sure that “X Coordinate” is selected as the variable, and in the “Value” field, enter -15 (negative fifteen). Then, check the “Relative” box so it is enabled.

undefined

Because we have “Relative” checked, -15 will be added to the instance’s X coordinate, and since it is a negative value, the instance will move 15 pixels to the left. However, if we hadn’t checked “Relative”, then the X coordinate would have been set to -15 meaning that it would immediately jump to that point on the X axis. To move the instance, we want its X coordinate to be set relative to its current position, which is why we need to enable that option.

We’re going to do something similar in the “Key Down - Right” event. Add the same action there (“Set Instance Variable”) and set the “X Coordinate” variable to 15 -- make sure to check the “Relative” option!

undefined

This will move the instance 15 pixels to the right.

If you run the game now, you will be able to move the player left or right, but only until it falls down never to appear again…

Bouncing Off Windows

To keep the player going, we want it to jump again when it comes in contact with a window. In GameMaker, such an event is known as a “collision”, so we can use that to make the player jump when it collides with a window.

Click on “Add Event” in obj_player and go under “Collision”. This will open up a list of objects, where you can select an object for the player to collide with. Click on obj_window which will add a collision event with that object.

undefined

This event will run whenever the player comes in contact with a window. We’ll make the player jump when this event runs, but before we do that, let’s learn about masks.

Masks

Each object has a mask which is used as its “hitbox”. This mask determines whether it's colliding with any other instance. By default, the mask is retrieved from the object’s sprite, and luckily the Sprite Editor lets us adjust the mask of a sprite.

In the Asset Browser, go into the “Sprites” group and find the spr_window asset, then double click on it to open the Sprite Editor. On the left of that editor you will see a few closed menus, one of which is “Collision Mask”. If you open it you will see that the image is overlaid with a transparent, black box, which is simply the sprite’s mask:

undefined

By default, a sprite’s mask is as large as the sprite itself, which means that any area of the sprite is able to collide with other instances. This is usually fine, however we only want our player to be able to jump on the window’s sill, which is why we need to modify the sprite’s mask.

Under the “Collision Mask” menu, change the “Mode” option from “Automatic” to “Manual”. Now you will be able to modify the mask’s rectangle in the sprite’s preview panel, by moving it around and changing its size by dragging its corners. Now make sure that it only covers the window sill (it doesn't have to be perfect):

undefined

Let’s do the same for the player. We only want its bottom half to be able to collide with windows and other in-game elements (to be added later), so open spr_player, change the mask's Mode to Manual and make it look something like this:

undefined

You can now close the Sprite Editor windows and return to the obj_player object.

Bounce On Collision

We added a new event in the player object for a collision with the window. Let’s add an action in this event -- in the Toolbox, search for the “Set Speed” action and drag it into the event.

For this action, we want to do the exact same thing we did in the Create event -- give it a vertical speed so it jumps up. Set “Type” to “Vertical” and in the “Speed” field, enter -35. This will make our player jump up whenever it collides with a window!

Tip: You can change this value if you want to increase or decrease the player’s jump power.

Now run the game (hit F5 or press the play button at the top of the IDE) and you will see that the player jumps whenever it comes in contact with a window. You are also able to move left and right, so you can now move freely throughout your level!

undefined

Flipping

You will notice that the player only ever looks in one direction. Ideally, it should flip to face the direction it’s moving in, and adding such a feature is fairly quick!

Let’s learn a little about scaling first. Every instance in GameMaker has an X scale and a Y scale, where its X scale controls its horizontal size, and Y scale controls its vertical size. When they are both set to 1, the instance’s scale is unchanged, however increasing that value will make the instance larger and decreasing it will make it smaller.

undefined

As you can see in the image above, setting the X scale to -1 (negative one) flips it around. We can use this technique to make our player face the direction it’s moving in.

Go into the “Key Down - Left” event in obj_player. In the Toolbox, search for the “Set Instance Scale” action (found under the “Instances” section) and drag it into the event. This action will allow us to change the horizontal and vertical scale of the instance.

If you open the spr_player sprite, you will see that our player sprite is facing right by default. This is its default scale, which means that when the X scale of the instance is set to 1, it will be facing right. This means that we simply need to set its X scale to -1 so that it faces right!

So in the “Set Instance Scale” action, set “Horizontal” to -1. Leave “Vertical” at 1 as we don’t want to change the instance’s Y scale. Now whenever you hold the left arrow key, the X scale of the instance will be flipped around.

undefined

Now go into the “Key Down - Right” event, add the same action there, and leave it at its default values. When this event runs, the instance will simply return to its default scale with the player facing right.

Run the game now, and you will see that the player now faces where it moves!

Note: If your player moves a large distance as it flips, make sure the origin for its sprite is set to Middle Centre.

Note on Display

Depending on your display, the window might be too large or too small. By default you are not able to resize the game window, so let’s enable that.

In the Asset Browser, go under “Quick Access”, expand “Game Options” and double click on your platform (Windows or macOS). This will open a new window in the workspace with settings for that platform. On the left you will see a list of menus. Click on “Graphics” and in the options that open up to the right, make sure that “Allow window resize” is enabled.

There is another option here that might be worth enabling. The “Interpolate colours between pixels” option makes sure that any scaled graphics appear smooth and that edges between sprites are not jagged. This should be disabled if you are using pixel art, however for our example we want this to be enabled as we are making use of full resolution art.

Tip: You can compare the game's graphics with this option disabled and enabled, and choose the one you like better.

In the following screenshot you can see both options enabled for the Windows platform:

undefined

Make sure to click on “Apply” or “OK” to save your changes, and then run your game. You will now be able to resize your game window. Note that by default the aspect ratio of the game will remain the same no matter what the size of the window is, which is also something that you can change through the Game Options for your platform.

View Scrolling

You can jump on the windows now, but you can’t go past the top boundary of the room. Since this will be an infinite scroller, we want the player to be able to climb as high as they can!

To achieve that effect, we’re going to move our instances down to give the illusion that the player is moving up. We’ll do this when the player reaches the middle of the screen:

undefined

We will need to move instances of multiple objects down to give the illusion of the player moving up. Right now we only have windows, but later we will add civilians, fires, and other objects, which will all need to be moved down as the player goes up. This means that we somehow need to group these objects together…

Object Parenting

GameMaker has a solution for this called “object parenting”. Basically, you can create a “parent” object and assign some objects as its “children”. Any changes you make to the parent object will also be applied to its children!

We can use this concept to create a parent object for those objects that need to be moved down. Go into the Objects group in your Asset Browser and create a new object called “obj_move_parent”. We don’t need to assign a sprite to this object as it won’t appear anywhere -- it exists only in the game assets so we can access its children.

Now to add children to this object, go into its Object Editor and click on the “Parent” button. This will open a new window where you can assign a parent to this object, however we want to add a child to it -- so click on the undefined plus button to the right of the “Children” section and select obj_window (alternatively you can simply drag in that object from the Asset Browser and drop it into the “Children” section).

undefined

Right now this is the only child that this object has, but when we add more objects later we can simply add them as children to this object and they will automatically move down too.

Now let’s continue with our goal to implement scrolling.

Conditions

Go into obj_player’s Events window and click on “Add Event”. Under “Step”, you will see three events, and you need to select the one that simply says “Step”. It will be added to your object.

undefined

This event runs every frame, so the actions you add here will constantly run for the instance. Actions in this event run unconditionally, but we want to add our own conditions to them: to check if the player is jumping up, and to check if it’s in the upper half of the screen.

For that purpose we have the “If Variable” action, which checks whether a variable meets a certain condition. Then we can connect actions to that action so that they run when the condition is met.

undefined

A variable keeps track of a value. For example, x and y are variables that hold the instance’s X and Y coordinates respectively. Similarly, hspeed and vspeed hold the horizontal and vertical speeds of the instance, respectively.

As you can see in the image above, this action acts as a condition (to check if a variable is holding a certain value). When that condition is met, any actions connected to it on the right are executed. This means that if that condition is not met, then those actions simply won’t run.

Scrolling

To scroll the view, we want to do a few things:

  1. Get the player’s upward speed ⬆
  2. Turn that around so it becomes a downward speed ⬇
  3. Apply that downward speed to the window so it moves down.

It sounds simple, but we also need to apply a condition to these actions. That condition will check if the player is moving up, because we only want the room to scroll when the player is jumping, not falling.

In the Step event's Toolbox, search for the “If Variable” action and drop it into the event. The variable that we need to check is vspeed (the player’s vertical speed) so enter that into the “Variable” field.

The “Is” option will be at “Equal” by default. This lets us check whether the variable’s value is equal to some other value (for example, checking if it’s equal to 4, or 200, and so on), but we want to check if vspeed is less than 0. If you remember, we set the instance’s vertical speed to -35 to make it jump up. This means that if the player is still jumping, its vertical speed would be negative, so we need to check if it’s less than 0.

Change the “Is” field to “Less”, and in the “Value” field enter 0 (zero). Now our condition checks if vspeed is less than 0!

undefined

Note: The "Not" option is used to flip the condition, making it false when it would be true and vice-versa. We don't need to use it right now.

Now we’re going to attach some actions to the “If Variable” action, so that they run when the condition is true. As previously mentioned, we need to get the player’s upward speed and turn it around. In the Toolbox, search for “Declare Temp” and add that action to the event: make sure to attach it to the right of the “If Variable” action!

undefined

Note: If you place an action below the “If Variable” action, it will not be controlled by that condition and will be independent.

Using this action we can declare (or create) a “temporary variable”. Such a variable only exists for the current event and is not available after that.

We want to create a temporary variable to store the downward speed. In the “Name” field, enter downspeed which will be our variable’s name (you can name it whatever you like). In the “Value” field, enter -vspeed (negative vspeed).

vspeed stores the player’s vertical speed, and since it’s jumping up (we made that sure in our condition), vspeed will be negative. To turn this speed around we use the negative sign, and since this value is already negative, it will result in a positive number. That number will be saved into our downspeed variable.

undefined

Now we want to apply this downward speed to the window, so it moves down. You might remember that we created an object called obj_move_parent to group those objects that need to move down. We’re going to apply our downward movement to that parent object, so that it’s automatically applied to all of its children.

In the Toolbox, search for “Set Instance Variable” and drop it into the same chain that was started by our “If Variable” action, so that it’s also controlled by that condition.

Before we modify any of this action’s properties, we need to think about what it will do. We want to use this action to move the windows, however we are inside the player object, so it will move the player. To apply this action to obj_move_parent instead, click on the undefined little arrow to the right of the action’s name, which will open the Asset Explorer.

This window will allow you to select an object to which this action will apply. Since we want to move any objects assigned to obj_move_parent, go into the Objects group and click on obj_move_parent (or just enter that into the “Expression” field). You will notice that your action now has a pink border, indicating that it will be applied to another instance.

undefined

Now set the “Variable” field to “Y Coordinate” and the “Value” field to downspeed. Make sure that the “Relative” checkbox is enabled. This will move the instance (relative to its own position) on the Y axis, by the amount stored in the downspeed variable. In short, the windows will now move down! This is what our Step event should look like at this point:

undefined

If you run the game now, you will see the windows move down, however they don't wait for the player to get to the middle of the screen first...

Upper Half Only!

The issue right now is that the view is always moving up, but it should only move if the player touches the upper half of the room.

To achieve this we’re going to use another condition. In the player’s Step event, add a new “If Variable” action at the top. We want to use this action to check whether the player is in the upper half of the room.

We can get the size of our room by reading the room_width variable for its width, and the room_height variable for its height. For our condition, we’re going to check if the player’s y (its Y position) is less than room_height / 2, as that gives us half the room’s height. So in the new “If Variable” action, set:

  • “Variable” to y
  • “Is” to “Less”
  • “Value” to room_height / 2

Now we want to apply the rest of our actions to this action, so they only run when this condition is met. Drag the old “If Variable” action and drop it to the right of our new action, so that it controls all of our previous actions.

undefined

If all of this has happened -- the player reached the upper half of the room while jumping -- we also want the player to stick to the center of the room, as we’re moving the rest of the objects in relation to the player.

In the same chain as our previous actions (controlled by the two conditions) we’re going to add a new “Set Instance Variable” action. This will set the player’s Y position to the center of the room, so that it doesn’t move any further into its upper half. To achieve that, we’ll set “Variable” to “Y Coordinate” and “Value” to room_height / 2.

undefined

When you run the game, you will see that the view only scrolls when the player intersects the upper half of the screen:

Woohoo!

Background Scrolling

You will notice that the background wall doesn't scroll. We'll need a different approach to make that work, as it's a background layer and not an object instance.

Let’s go back into the player’s Step event. In the Toolbox, search for the “Function Call” action and drag and drop it into the event, below the “Set Instance Variable” action.

This action lets us run a “function”, which is simply an extra action for us to use. We want to get the current Y position of the background layer, so in the “Function” field, enter layer_get_y. In the “Argument” field, enter “Background” -- this is the name of our background layer. In the “Target” field, enter back_y and enable the “Temp” checkbox.

undefined

Note: An “argument” is simply an option for a function. Functions can take multiple arguments.

This action will get the Y position of the background layer and store it in a new, temporary variable called back_y. We’ll use this variable in a new action to move the layer, so in the Toolbox, search for the “Function Call” action again (or find it under “Recently Used”) and drop it below your previous “Function Call” action.

We want to use this new “Function Call” action to change the Y position of our background layer. In the “Name” field, enter layer_y, and in the “Argument” field, enter “Background” (same as the previous action). This function needs a second argument, so click on the undefined plus button to the left of the action, which will add another argument field. Set this to back_y + downspeed.

undefined

Now when you run the game you will see that the background moves as well:

undefined

It definitely looks like the player is going up, when in reality it's the other visuals that are going down!

Spawning Windows

You can go as high as you want now, but there aren’t any more windows beyond the ones you placed in the room. We want the windows to keep coming in so the player can climb as high as they can!

We’re not going to create new window instances as the view scrolls. Instead, when a window exits the room from the bottom, we want it to reappear at the top at a different horizontal position.

To implement this, let’s go into the window object (obj_window) and add the Step event. We’ll use this event to check if the window has gone out of the room and if it has, we’ll respawn it. To check that we need a new condition -- so add an “If Variable” action and let’s proceed.

Condition: Below Room?

We want to check if the Y position of the instance is greater than room_height, which is the total height of the room. If this condition is met it means that the instance is below the room. However, we need to be careful with this, as the Y position of the instance refers to its origin, and we placed the origin of our window sprite above its sill. This means that such a condition will only check if that origin point is below the room -- not the whole window!

undefined

We can work around this by adding an offset to the room’s height in the condition. So instead of checking if the y is greater than room_height, we’ll check if it’s greater than room_height + 360 as that gives us the extra room we need for the whole window to disappear.

In the "If Variable" action, set the “Variable” field to y, the “Is” field to “Greater” and the “Value” field to room_height + 360. This condition will allow us to perform actions when the window is below the room.

undefined

The first thing we want to do now is to calculate a random X coordinate where the window will be placed, so it’s not always in the exact same horizontal position. For that we’re going to use the “Get Random Number” action -- find it in the Toolbox and attach it to the “If Variable” action.

This action generates a random number based on our specified range. First of all, make sure that the “Type” is set to “Integer” since we don’t want a decimal value. We want the new X position to be anywhere between 0 and room_width (as that is the room’s range on the X axis), but there is something else to consider.

We don’t want the window to spawn too near to the left or right border, as then the window will be cut off and will not appear in full. We’re going to allow a margin of 200 pixels for the spawning range, so we’ll set the “Minimum” field to 200 and the “Maximum” field to room_width - 200.

This will now generate an integer value between that range, but how do we retrieve it? For that we’re going to use the “Target” field. Simply enter a variable name here and the generated value will be stored into that variable.

We want to use a temporary variable to store the random value, as we only need it for this event. Set the “Target” field to new_x and enable the “Temp” checkbox.

Now to respawn the window above the room (so it can come down again) we need to change its position. Find the “Jump To Point” action in the Toolbox and drag it into the chain. This action allows us to set new X and Y coordinates for the instance, making it instantly jump to that point. For the “X” field we’re going to use the new_x variable which is randomly generated. For the “Y” field, we’ll use -200 (negative 200) to place it above the room and give it a 200-pixel margin.

Your event should look like this now:

undefined

If you run the game now, you will see that the windows are being randomly generated!

undefined

Tip: If you need help with your project at any point, you can join the GameMaker Community and create a thread there.

If you’re not able to reach any newly spawned windows because they spawn too high, or if some windows spawn too close to each other, you will need to adjust the separation between your windows in the Room Editor. You can also place extra windows above the room to fill any gaps:

undefined

Combo Jump Issue

There is an issue with our game right now. If there is a row of windows, you will see that the player easily boosts through it:

undefined

This is not intended, as we want the player to bounce on each window individually. We’re facing this issue because the player jumps as soon as it comes in contact with a window, even as it’s jumping! We only want it to be able to jump while it’s falling.

To fix this problem, let’s go into the player object (obj_player) and open its Collision event with obj_window. Here we have an action that sets the player’s vertical speed to -35, making it jump. We want to put this action under a condition to check if the player is falling, so search for the “If Variable” action in the Toolbox and drag it into the event.

Moving down involves a positive vertical speed, so to check if the player is falling, we need to check if its vertical speed is greater than 0. So in the “If Variable” action, set the “Variable” field to vspeed, the “Is” field to “Greater” and the “Value” field to 0. This will now check if the player is falling, and to make it jump only when this condition is met, drag the “Set Speed” action and attach it to the “If Variable” action.

undefined

You will now see that the issue is fixed. With that done, let’s move on to the final part of this tutorial!

Street Area

Our game only has a brick background at the moment. We want to make it so you can see the street in the beginning, adding polish to our game.

In the Sprites group in your Asset Browser, create a new sprite called “spr_street”. Import the image with the same name from the tutorial assets.

undefined

In the Objects group, create an object for this called “obj_street” and assign the spr_street sprite to it. Open its “Parent” menu and click where it says “No Object”. This will open up the Asset Explorer where you can select an object to assign as this object’s parent. We want this street object to automatically move down with the view, so we’re going to set obj_move_parent as its parent.

undefined

The final step is to place it in the room. Open the rm_game room, make sure the “Instances” layer is selected (which is below the “Player” layer) and drag obj_street into the room area to create an instance. Place it at the bottom and make sure it doesn’t overlap with any windows (if they do, move the windows up).

In the game you will now see the street area in the beginning, which will simply move down with the view just like our windows. We didn’t have to add any more actions to make it move, because we're already applying downward movement to obj_move_parent, which is the parent of the window object and the street object.

undefined

Summary

Before we continue to the next part of the tutorial, let’s summarize what we have learned so far:

  • You can import images as sprites, and create objects that can be programmed
  • Room layers can be organized so you can control which instances appear at the top
  • Input Events can be used for player control
  • Object Parenting can be used to group multiple objects together and move them at once
  • Finally: You are awesome at making games!

In the next part, we’re going to add civilians that can be rescued and the ability to score points.

Next: Fire Jump Tutorial - Part 2