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
is Part 2 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:
Overview
In
the previous part, we created a basic example with a jumping player and
infinitely spawning windows. Now we will expand on that example to add
player animations, civilians to rescue and scores.
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.
Player States
Importing Sprites
We’ve
made the player move exactly as we wanted, however it appears to be
stuck in the same animation. That’s because we only imported one sprite
for the player and that is all we see.
We’re
going to import two more sprites to animate our player. Go into your
Asset Browser, and in the “Sprites” group, create two new sprite assets: "spr_player_jump" and "spr_player_fall". You can find both of these sprites
in this tutorial’s art assets folder, which you can import and use.
Make sure to set the origins for these sprites to “Middle-Center”.
Let’s
open the spr_player_jump sprite and make a small adjustment. We want
this state to have a time limit, so it should only run for a few frames and
then switch to another state. For that we are going to use its
“sub-images” (or frames) feature, although you will notice that this
sprite only has one frame.
We
can extend a sub-image so that it lasts for multiple frames instead of
only one. Place your mouse cursor near the right edge of the first frame,
and drag it out so it lasts for about 8 frames. This sprite will now
function as an 8-frame animation that we can run when we want!
Now we have three player sprites in total, for the three states that it’s going to be in:
spr_player_jump: The jump state which plays after you bounce off a window
spr_player_air: The “in-air” state that plays after the jump state is over
spr_player_fall: The fall state that plays as the player is falling down
We
can easily change the sprite of an object using actions, so let’s
program our player to display the correct sprite depending on its state.
Jump State
We
want the jump state to play when the player bounces off a window. To
implement this, let’s go into obj_player and open its Collision Event
with obj_window.
This
event currently checks if the player is falling, and sets its vertical
speed so that it jumps again. We also want to change its sprite at the
same moment, so go into the Toolbox and search for the “Set Sprite”
action. When you have found it, drag and drop the action to the right of
the “If Variable” action, so that it’s controlled by that condition.
This
action changes the sprite of the instance to the one set in the
“Sprite” field. You can click on the icon next to that field to
open the Asset Explorer, which will allow you to select a sprite asset.
At this point we want the player to switch over to spr_player_jump, so
find that sprite and assign it to the action.
Alternatively, you can drag the sprite asset from the Asset Browser and drop it into the “Sprite” field:
The “Frame” field is the sub-image to switch to, and we're keeping it at 0 so the sprite animation starts from the beginning.
In-Air State
The
jump animation will now play when the player bounces off a window,
however when that animation ends, we want it to transition into its
“in-air” sprite. For this we need a new event, so click on “Add Event”
in the player’s Events window, go under “Other” and select “Animation
End”.
This
event is as simple as it sounds: it runs when the player’s current
animation ends. We want to use this event to check if the player’s jump
animation has just ended, and in that case, change the sprite to
spr_player_air.
Search
for the “If Variable” action in the Toolbox and drag it into the event.
We’re going to use this action to check the variable sprite_index, which stores the sprite that the instance is currently using. So set the “Variable” field to sprite_indexand the “Value” field to spr_player_jump.
This
condition now checks if the player’s sprite is spr_player_jump, meaning
that it’s playing the jump animation. Because of the event we are in,
we know that the jump animation has ended, so we’re going to switch to
the “in-air” state instead.
In
the Toolbox, search for the “Set Sprite” action and drop it to the
right of the “If Variable” action, so it’s controlled by that condition.
In the Sprite field, enter “spr_player_air” or press the button next to
it to open the Asset Explorer and find the asset there.
This event is now finished, and will change the player’s sprite to spr_player_air when the spr_player_jump animation ends.
Tip: You can use this same technique anywhere to create transitions between two sprites
Fall State
The
fall state plays as the player is falling. We’re going to check this in
a new event and change the sprite to spr_player_fall.
In
the Events window for obj_player, click on “Add Event”, go under “Step”
and select the “End Step” event. This event runs after the Step event,
so like that event it also runs once per frame, and we’re using it
to make our object more organized (instead of putting everything into
the one Step event).
To go into the fall state, the vspeed(vertical
speed) of the player needs to be greater than 0, so we’ll use this as
our condition. In the Toolbox, search for the “If Variable” action and
drop it into the event. Set the “Variable” field to vspeed, the “Is” field to “Greater” and the “Value” field to 0.
If
this condition is met we want to change the sprite, so look for the
“Set Sprite” action and attach it to our “If Variable” action. Set the
“Sprite” field to spr_player_fall or use the button next to it to find
it through the Asset Explorer.
This
will now set the player’s sprite to spr_player_fall whenever it’s
falling down. That’s all three states down now, so let’s run the game
and play around:
The player now animates between its three states! You may find that the player jumps too easily now, and that is because the mask of the instance is not consistent. Let's work on that now.
Masks
In
the previous part of the tutorial, we edited the mask of the player
sprite (spr_player_air) so it only covers its lower half:
Now
that we’ve added two more sprites for the player, the other sprites are
not going to use this mask. This means that the hitbox for the player will be inconsistent as it changes with the sprite. To fix this, we could edit the masks for the
other player sprites to look the same, but luckily we don’t have to do
that.
We
can assign a sprite to an object as its “mask”, so the mask from that
sprite will be assigned as the permanent mask (hitbox) for that object.
This means that even if the sprite for that object changes to something
else, the mask that we set will be kept.
Let’s
go into obj_player, and find the “Collision Mask” option in its Object
Editor. You will see that it says “Same As Sprite” which means that the
mask from the active sprite is used. We want to change this so it uses a
fixed mask, so click on it to open the Asset Explorer and look for spr_player_air. Select that sprite when you’ve found it, and it will
now be used as the player’s mask at all times.
Spawning Civilians
The
main part of our game’s loop is the ability for the player to rescue
civilians, so we’re going to work on that now. The windows should
randomly spawn civilians on them that the player can “collide” with and
rescue.
Importing Sprites
We’re
going to import three separate civilian sprites, one of which will be
randomly selected to spawn on a window, giving the game some variety in
its visuals.
In
your Asset Browser, right-click on the “Sprites” group and select
“Create Group”. This will create a new group that can be used to store
assets, and we want to use this for civilians -- so name it “Civilians”.
In
this new group, create a new Sprite asset and name it “spr_civilian_0”. In the Sprite Editor, click on "Import" and go to the tutorial's art assets. In the "Civilians" folder you will find "spr_civilian_0a" and "spr_civilian_0b", which are frames for this civilian's sprite, so select both files and import them.
Set the origin to Bottom-Centre. You will also need to adjust the "Fps" (animation speed) in the top-left corner of the Sprite Editor, as this animation only has two frames and will be too fast by default. You can set it to 4, or any other speed you prefer.
Now repeat this for
“spr_civilian_1” and “spr_civilian_2”, importing two frames for each, adjusting the Fps and setting the origin to "Bottom Centre".
Since the
origins for these sprites are set to “Bottom Centre”, and the
origin of our window sprite is directly above its sill, it means that we
can place the civilian directly on the window and both sprites should
perfectly line up because of their origin points:
Civilian Object
While
there are three separate civilian sprites, there will only be one
civilian object that will be assigned a random sprite to display. Go
into the “Objects” folder in your Asset Browser, and create a new Object
asset called “obj_civilian”. Assign the spr_civilian_0 sprite to it.
Before
we program any of its behaviours, we need to make it a child of
obj_move_parent so that it moves down with the view. Click on the
“Parent” button, and in the window that opens, click on “No Object” to
open the Asset Browser. Look for obj_move_parent and select it as the
parent.
We
now have one civilian object, but three sprites for it. We’re going to
make it so the object selects a random sprite from the three whenever it
is created.
In
the Events window for obj_civilian, click on “Add Event” and select
“Create”. Here we want the object to choose between the three sprites
available, and for that we’re going to use the “Choose” action. Search
for it in the Toolbox and drag it into the event.
This
action lets you specify multiple options, and selects one of them at
random. In the first “Option” field, enter spr_civilian_0. Then click
on the plus sign to the left of the action to add a new option,
and set that to spr_civilian_1. Add another option in the same manner
and set that to spr_civilian_2.
One
of these options will be selected and applied to the variable in the
“Target” field. We want it to be applied to the instance’s sprite, so
that a random sprite is selected and applied directly to the instance,
so we’re going to enter sprite_indexin the “Target” field.
This will now select a random sprite from our given options and apply that to the instance.
Cleaning Up
When
a window instance goes out of the room, we simply pull it out and place
it at the top, so it appears again and the game keeps going. This will
not happen with a civilian instance, as we don’t want it to appear again
if it has gone out of the room (since we will keep spawning new
civilians). This means that we need to destroy a civilian once it has
disappeared.
To
do this, we’re going to add the Step event to our civilian object. Once
you have added it, go into the Toolbox, search for “If Variable” and
drag it into the event. Here we want to do something that we have
previously done in the window object -- to check if the instance is
below the room. Set the “Variable” field to y, the “Is” field to “Greater” and the “Value” field to room_height + 350.
This
will check if the Y position of the instance is greater than the room’s
height, with an additional margin of 350 pixels as the civilian sprite
is quite large. In this case we simply want to destroy the instance, so
search for the “Destroy Instance” action in the Toolbox, and drop it to
the right of the “If Variable” action so it’s controlled by that
condition.
Spawning
We’re
going to spawn civilians with the windows, however we are going to use a
new layer for this to make sure that they are drawn between the windows
and the player. Go into the rm_game room and in the Layers panel on the left,
create a new Instance Layer and name it “Spawns”. Make sure that it’s
placed between the “Instances” and “Player” layers:
For
spawning civilians, let’s go into obj_window and open the Step event.
Here we already have one condition that checks if the window is below
the room, which controls a chain of actions for respawning the window.
We’re going to add more actions in this same chain for spawning a
civilian on the window.
We
need a random number generator to control if a civilian will spawn or
not. In the Toolbox, search for the “Get Random Number” action and drop
it into the event, under the same chain as the previous actions (below
“Jump to Point”). Set the “Type” field to “Integer”, the “Minimum” field
to 0 and the “Maximum” field to 1. We want the result of this action in
a new temporary variable, so set the “Target” field to chance(as the variable’s name) and enable the “Temp” checkbox.
This
will create a temporary variable named chance which will be either 0
or 1 (we will increase the maximum limit in the next part, but for now these are the only possible values). We will only spawn a civilian on the window if this number is 0,
so we’ll need a condition for this -- but instead of using the usual “If
Variable” action, we’re going to make use of a “Switch”.
A
Switch lets us specify a variable at the top, and then execute multiple
“cases” for it. If the specified variable is equal to any one of the
given cases, the actions under that case are going to run. See the
following visual:
Right now we have only one case to check (if chance is equal to 0)
however in the future we will add more cases, which is why the switch
is perfect for evaluating the same variable multiple times.
In the Toolbox, search for “Switch” and place it into the same chain of actions. Set the “Value” field to chance.
Back in the Toolbox, search for “Case” and add that action into the
“Switch” action. In this new action, set the “Constant” field to 0.
You
can now attach new actions to this “Case” action, just like with a “If
Variable” action, and those actions will only run if the chance variable is equal to 0.
If
this case is true, we want to spawn a civilian on the window. In the
Toolbox, search for “Create Instance” and attach that action to the Case action. This action lets us create an instance of an object, so we’re
going to use this to spawn a civilian.
Set the “Object” field to obj_civilian(or
press the button next to it to open the Asset Explorer and find it
there). We’ll create it at the same position as the window, so enable
the “Relative” checkbox for both “X” and “Y” and leave their values at
0. Set the “Layer” field to “Spawns” (including quotes) as the name of
the layer where our instance will be created.
This
will create a civilian instance on the window, however we also need to
take care of one more thing: the window is closed by default, so we need
to open it by using its second frame.
The
first frame of our spr_window sprite has the closed window image, which
is used by default. We want to assign the second frame to the window
when a civilian is spawned. We can use an action to achieve this, so in
the Toolbox, search for “Set Sprite” and drop it into the action chain,
under “Create Instance”.
Set
the “Sprite” field to spr_window, which is the sprite that the window
is already using -- we’re not changing that. What we are changing is the
frame. We want to assign the second frame to the window, and as frame
numbers start at 0, the second frame will be 1. Set the “Frame” field to
1 and this should do exactly what we want!
There
is one final change we need here: when the window respawns, it should
revert back to its default frame. In the Toolbox, search for “Set
Sprite” and drop it above the Switch action (so it's independent of it). Set the “Sprite” field to
spr_window and leave the “Frame” at 0. This makes sure that the window
always resets to its first frame, and then it can be changed by the Switch
action below.
If you run the game now, you will notice random civilians spawning on windows and moving down with the view!
Rescuing Civilians
We’re
going to make the player able to rescue civilians. The player will simply collide with a civilian instance, at which point the civilian
will fly off using a parachute and disappear.
We
need to import images for every civilian with a parachute, which will be
displayed after they are rescued. In your Asset Browser, you will have a
“Civilians” group under “Sprites”, which we created in the previous
section. Create three new sprites in it and import images for them from
the tutorial’s assets:
spr_civilian_rescued_0
spr_civilian_rescued_1
spr_civilian_rescued_2
Make sure that the origin for these sprites is set to “Bottom Centre”, so they match with the regular civilian sprites.
Now
to program its rescue animation, let’s go into obj_civilian and open
its Create event. Here we’re going to create a variable to store whether
this civilian has been rescued or not. In the Toolbox, search for the
“Assign Variable” action and drop it into the event. Set the “Name”
field to rescued, which will be the name of our new variable, and the “Value” field to false.
What we’re creating here is called a “boolean” variable. This can either be trueor false, telling us whether something has happened or not. Since rescuedis falseby default, it means that the civilian hasn’t been rescued. We’ll set this to truewhen we rescue it, and we check its value at any time to know the civilian’s state.
Help, Player!
The
civilian now needs to check whether the player is colliding with it. In
obj_civilian’s Events window, click on “Add Event”, go under
“Collision”, then “Objects” and select obj_player. This will add a
collision event between the civilian and the player.
This
event needs to have a condition at the top, to make sure that the
civilian has not been rescued yet. In the Toolbox, search for “If
Variable” and drag it into the event. Set the “Variable” field to rescuedand the “Value” field to false. All further actions added to this event should be attached to this action.
To make sure that this event only runs once, we need to set the rescued variable to true. Search for the “Assign Variable” action and attach it to the “If Variable” action. Set the “Name” field to rescuedand the “Value” field to true.
This makes sure that the civilian can only be rescued once, as the rescued variable will be true after this and not false.
Now
we want to make the civilian jump up and fall down, so we’re going to
give it an upward push as well as enable gravity. Add the “Set Speed”
action into the same chain as the previous action. Set the “Type” to
“Vertical” and the “Speed” to -18.
For
gravity, search for the “Set Gravity Force” action and drop it in the
event. Set the “Force” to 0.5 (we’re using a low gravity value since the
civilian is using a parachute).
The
civilian will now jump off the window, but it also needs to display the
correct "rescued" sprite from the ones we imported. Since there are three
different kinds of civilians, we’ll use a Switch block to assign the
correct sprite when it is rescued.
In
the same event, search for the “Switch” action and drag it into your
action chain. Since we need to check what sprite the civilian has, set the
“Value” field to sprite_index.
Now
it’s time to add cases to this Switch, so find the “Case” action in the
Toolbox and drop it into the Switch action. In the “Constant” field,
enter spr_civilian_0. If that is
the civilian’s sprite, we want to switch to its rescued equivalent, so
search for the “Set Sprite” action and attach it to your Case action. In
this new action, set the “Sprite” field to spr_civilian_rescued_0(or find it through the Asset Explorer button).
We
need to do the same for the other civilian sprites, so add cases for
both of those sprites (spr_civilian_1 and spr_civilian_2) and switch
them to their rescued equivalents (spr_civilian_rescued_1 and
spr_civilian_rescued_2). It should look like the following:
Using
these Switch and Case actions, we’re changing the civilian’s sprite
depending on the three possible sprites that it can have.
Tip: This technique
can be used anywhere to perform different actions based on different
values of a variable.
If
you run the game now, you should be able to rescue any civilians that
spawn. When the player collides with a civilian, that civilian gets a
parachute and falls off the window, and once it’s below the room it gets
destroyed because of its actions in the Step event.
Depth
In the GIF above, you can see that a rescued civilian appears below the player, since the "Spawns" layer is below the "Player" layer. To make it appear above the player after it has been rescued, we can change its "depth" value.
The depth controls which instance appears above others, and is usually tied to the layer. However we can change it manually using an action to change the order of appearance. If an instance has a lower depth value then it will appear above instances with higher depth values -- see it as the instance's distance from the player's eyes.
In the obj_civilian object, go to its Collision event with obj_player, and above the Switch action add the "Set Instance Variable" action:
Here we are changing the depth of the civilian instance to obj_player.depth - 10. This means that its depth will be 10 units less than the player's, and so will appear above it! Test the game now and you will see that all rescued civilians now draw above the player, making the game feel more realistic.
Rescue Score
We’re
going to add a score system to our game, so we can count how many civilians
the player has rescued and display that on the screen.
Set Up
First
of all we need to import a new image to display the rescue score on the
HUD. In your Asset Browser, go into the “Sprites” group and create a
new sprite asset called “spr_score_card”. You will find this image in
the tutorial’s art assets under "UI", which you can import through the Sprite Editor. Set its origin to "Middle-Centre".
We
need another visual addition to the project, but this time it’s not a
sprite but a font. Since we’ll be drawing the player’s score as text,
it’s best to have a custom font that you can personalize to fit the look
of your game.
In
the Asset Browser you will find a “Fonts” group. Right click on it, go
under “Create” and select “Font” (this is an alternative to creating assets through the "Create Asset" menu, and both are fine to use). This will create a new Font asset
that we’ll call “fnt_score”.
Note: The fnt_ prefix indicates that it is a Font asset.
You
will see the Font Editor open up in your workspace, where you can edit
the look of your font. Under the asset’s “Name” field, you will find the “Select Font” option which allows you to choose a font from the ones
installed on your computer. Under the “Presets” section in the middle,
you can assign a style and size to the font.
Tip: The font we've used in this tutorial is Poetsen One.
Go
ahead and choose whatever font you like, and set the size to be
somewhere around 36 as that works best for our example. When you are
done editing your font, you can close the Font Editor and proceed with the tutorial.
Global Variables
We know that we can create a variable using the “Assign Variable” action, however that
creates an Instance Variable. Such a variable is only available in one
instance and other instances cannot access it. We cannot use this to
create our score variable, as we want all instances to be able to
access and change it. So we’re instead going to use Global Variables.
A
Global Variable is accessible through all instances, which is ideal for
our score as there will be a separate object to draw it, but it will be
modified in a different object.
Let’s
create our player’s rescue score variable. Go into obj_player and open
its Create event. In the Toolbox, search for the “Set Global Variable”
action and drop it into the event. This action allows you to create (or
change) a global variable. Set the “Name” field to score_rescue, which will be the name of our new global variable, and set the “Value” field to 0 (there is no score by default).
Note:
The plus button to the left of the action is used to add another
variable to the same action. We will make use of this later in this
tutorial to create a new score type!
Adding Score
We
will increase this score variable by 1 whenever the player rescues a
civilian. Since that happens in the civilian object (obj_civilian) let’s
open it, and go into its Collision event with obj_player. In the
Toolbox, search for “Set Global Variable” and drag that action anywhere
into the “If Variable” action’s chain so it’s controlled by that
condition -- I’ve added it at the top:
As you can see in the image above, we’re setting the score_rescuevariable
to 1 with the “Relative” checkbox enabled. This will add 1 to the score
value, so the player’s rescue score will go up each time it rescues a
civilian.
Score Object
We
have a score variable now that goes up every time a civilian is
rescued. All we need to do now is to draw it on the screen, so the
player can see how good they are!
In
your Asset Browser, find the “Objects” group and create a new Object
asset here. We’ll call this “obj_score_rescue” as this will draw our
rescue score. Apply the spr_score_card sprite to this object.
We
want this object to draw the score value. This is something that
happens each frame, just like the Step event, however that event does
not support drawing. For this purpose we have an event called “Draw”. In
the Events window, click on “Add Event”, go under “Draw” and select the
“Draw” event.
This
event runs every frame, and allows us to draw anything (sprites, text,
shapes, etc.) to the screen. We need to draw our score text, however
before we do that, there is something important to take care of.
Once you add a Draw event to an object, its instances will notbe
drawn anymore. This is because GameMaker has now given you control over
the object to draw it in any way you like, however we want it to draw
normally as it would by default. To achieve this, search for “Draw Self”
in the Toolbox and when you find that action, drag and drop it into the
event.
With this action in the event, the instance will be visible again, so let’s proceed to drawing the score text over it.
Drawing Text
Before
drawing the score text, we need to make sure that it uses our new font
(fnt_score). In the Toolbox, search for “Set Font” and drop that action
into the event. Set the “Font” field to fnt_score(or
use the button to the right and find the asset through the Asset
Explorer). Any text we draw after this action will now use that font.
The
main action that we’ll use to draw our score is called “Draw Value”.
Search for it in the Toolbox, and drop it into the event. Make sure that
it comes after the “Draw Self” action, otherwise the text will be
hidden behind the sprite, and also make sure that it comes after the
“Set Font” action so our custom font is used to draw the score.
The
“Caption” field is the text that draws before the score. We’ll set this
to “Rescued ” including the space at the end, to add some distance
between that text and the score value.
Note: Make sure to include the quotes with the “Rescued ” text as shown in the screenshot. Such a text value is known as a “string”.
The “Value” field is the actual value that needs to be drawn, which we’ll set to global.score_rescue. We’re using our global variable in a non-global action, so we need to specify the global. prefix, otherwise it won't be able to find the variable.
The
“X” and “Y” fields take the position where this text will draw. We want
to draw it at the instance’s position, so we’ll leave them at 0 and
enable the “Relative” checkboxes for both.
This
will draw the text now, however it is not ideal. By default, the text
is drawn with a “Left-Top” alignment meaning that it wouldn’t be
centered on the instance.
Let’s first change the alignment to “Centre-Middle”. In the Toolbox, search for “Set Text Alignment” and drop that action before the “Draw Value” action. This action allows you to change the horizontal
and vertical alignment of your text. Click on the button to the right of
the “HAlign” field and select "Center”, then click on the button next
to the “VAlign” field and select “Middle”.
This action will change the global alignment,
meaning that any text drawn after this will use Center-Middle alignment. This
works well for us now, but to make sure that this change doesn't affect any other text in our game, we'll reset these values after drawing our text.
We’ll
use this same action again to reset the alignment back to default. Add another “Set Text Alignment” action (you can find it under “Recently
Used”) below the “Draw Value” action. Leave the values as they are so that they are reverted to default.
Because of the order of our actions, the following will happen:
The alignment will be set to Centre-Middle
Our text will be drawn using that alignment
The alignment will be reset to default
This is a fairly common technique in GameMaker, where you change a global property, draw something, and then reset that property to default.
HUD Layer
To
make the buttons visible, we’re going to place them in our room. In
your Asset Browser, go into the “Rooms” group and open rm_game. Go to
the Layers panel on the left and create a new Instance Layer called
“HUD”. Place it at the very top so that the HUD instances appear above
everything else.
Drag
the obj_score_rescue button into this layer and place it wherever you
like, preferably in the top-left corner. Run the game, and you will now
see your rescue score!
Height Score
We’re now going to add another score type to record how high the player has climbed.
Go
into obj_player and open its Create event. Find the already-existing “Set Global
Variable” action, and click on the plus button to its left to add
a new global variable. Set the “Name” for this variable to score_height and leave its value at 0.
This
variable will store the height score, so the player can tell how far
they have climbed. To increase this score value, we’ll go into the
player’s Step event, which is where we scroll the view. We’re going to
increase the score value here as well.
In the Toolbox, search for the “Set Global Variable” action and drop it into the action chain. Set the “Name” field to score_heightand the “Value” to downspeed / 100. Since we want to increase the score variable, enable the “Relative” checkbox.
We are increasing the score_heightvalue by the downspeedvalue divided by 100. We’re dividing it by 100 so that the
score stays relatively low: for every 100 pixels climbed, the score will
only go up by 1.
Drawing Score
We
want to draw the height score in its own object, just like we did with
the rescue score. In fact, we’ll simply duplicate the rescue score
object to save time.
In
your Asset Browser, expand the “Objects” group and find
obj_score_rescue. Right click on it and select “Duplicate”. This will
create a new object asset, which we’ll name “obj_score_height”.
Find
the Object Editor for obj_score_height in your workspace (or double
click on the asset to open it). Since we’ve duplicated the previous
object, it will already have the same Draw event for drawing the score. Open
this event so we can change what score variable it draws.
Find
the “Draw Value” action in this event. Change the “Caption” field to
“Height ” (including the quotes and the extra space), then change the
“Value” field to round(global.score_height).
For the rescue score value, we simply used global.score_rescue, however for the height score, we are using round(global.score_height). Why is that?
round() is
a function that rounds a value, so for example, 0.1 becomes 0, 1.7
becomes 2 and so on. If you remember, we made the height score go up by downspeed / 100,
which is a decimal value. This means that the score will also be a
decimal value, and to display it as an integer instead, we wrap it in round().
The
following image shows the score drawn with and without rounding, and
you can tell why we’re rounding the value as it looks much better:
Now
open your rm_game room, select the “HUD” instance layer and drop the
obj_score_height object anywhere you like, preferably in the top-right
corner. You will now see both scores in the game, and it'll be much more
exciting to play!
Bonus: Jump Effect
As
a bonus, we’re going to show a visual effect whenever the player jumps.
Let’s import a sprite first: go into the “Sprites” group and create a
new Sprite asset called “spr_jump_effect”. In the tutorial's art assets, in the "Animations" folder, you will find an image called spr_jump_effect_strip25 which you can import through the Sprite Editor. This file has _strip25 at the end of its name because it's a 25-frame animation, and GameMaker will use this information to automatically divide it into 25 separate frames (or sub-images):
Set the
origin to “Bottom Centre” so it’s easier to place at the player’s foot
when it jumps (which is on the window sill).
In the “Objects” group, create a new object called “obj_jump_effect”. Assign the spr_jump_effectsprite to it. We want this object to move down with the view, so open its “Parent” menu and assign obj_move_parent as its parent object.
We
will create an instance of this object whenever the player jumps, and
it should be destroyed when its animation ends. For this we’re going to
use a new event: click on “Add Event”, go under “Other” and add the
“Animation End” event.
In
the Toolbox, search for the “Destroy Instance” action and drop it into
the event. This will now destroy the jump effect when its animation
ends, meaning that it will play only once after its instance is created.
Now
to show this jump effect, let’s go into obj_player, and open its
Collision event with obj_window. Here we have an “If Variable” action
which creates a new chain of actions, and we want to add a new action to this chain.
In
the Toolbox, search for the “Create Instance” action and attach it to
the “If Variable” action so it’s placed in its chain. Set the “Object”
field to obj_jump_effect(or find it through the Asset Explorer button on the right).
Horizontally,
we want to place it exactly where the player is, so enable “Relative”
for the “X” field while leaving its value at 0.
Vertically,
we want it to be placed on the window, as the player is jumping off
it. If we used “Relative” here then it would be created at the player’s
chest by default, which is something we don’t want, so make sure that “Relative” is
disabled for the “Y” field. In the same field, enter other.y.
We
will learn more about other in the next part, but in this case it refers
to the window instance that is colliding with the player (as that is
the “other” instance in this collision). This means that the jump effect's Y position will be on the window, where the player has stepped.
Finally,
set the “Layer” field to “Player” so that the effect is created in the
same layer as our player, and then run the game to see your jump effect:
Summary
Before we add more amazing features to our game, let’s summarize what we learned in this part:
You can change the sprite after playing an animation once using the Animation End event
You can create a new instance in the game using the “Create Instance” action
You can use the Switch action to do something different based on a variable’s value
You can draw text in the Draw event using the “Draw Value” action
Remember that you need to use “Draw Self” to draw the instance itself
And finally: You are amazing!
In
the next part, we’re going to add fire to the windows and give the player
the power to put out those fires by shooting foam. We’ll also add sound
effects to give our game some polish.