Welcome to the Fire Jump tutorial! This
series will take you through developing an infinite platformer game in
GameMaker using GML Visual. 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. Everything is explained in an easy to
understand manner, so you can follow this tutorial even if you have
never used GameMaker before, and there is enough useful
information for intermediate users to enjoy as well.
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.
Let’s start by creating a new project which we’re going to use to develop our game.
Open GameMaker and click on “New”, then select "New Blank" as we'll be starting with a blank project.
Enter a name for your project (you can name it “Fire Jump”)
and click on "Let's Go!".
After creating your new project, you will see it open up in GameMaker:
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 “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.
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.
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”.
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”!
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:
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.
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.
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:
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.
If you don't see this menu, click once on Room1 in your Asset Browser. These settings should now appear on the left (under the Inspector).
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!
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.
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.
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:
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 GML Visual: 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.
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:
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:
Automatically jump on creation
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.
When you select your event, you will be asked to choose between GML Visual and GML Code:
Select GML Visual, and make sure to enable "Don't ask again for this project". Hit "OK".
Doing this will open the event
in a new window, which is where you can add actions:
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:
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.
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.
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.
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
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:
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:
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.
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!
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.
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:
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):
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:
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!
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.
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.
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:
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:
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 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).
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.
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.
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, hspeedand 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:
Get the player’s upward speed ⬆
Turn that around so it becomes a downward speed ⬇
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 vspeedis
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 vspeedis less than 0!
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!
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).
vspeedstores the player’s vertical speed, and since it’s jumping up (we made that sure in our condition), vspeedwill
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 downspeedvariable.
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 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.
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 downspeedvariable. In short, the windows will now move down! This is what our Step event should look like at this point:
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_widthvariable for its width, and the room_heightvariable 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.
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.
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.
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 plus button to the left of the action, which will add another argument
field. Set this to back_y + downspeed.
Now when you run the game you will see that the background moves as well:
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!
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.
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 200and 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_xvariable
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:
If you run the game now, you will see that the windows are being randomly generated!
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:
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:
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.
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.
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.
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.
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.