Hi there! Welcome to the Hero’s Trail sandbox project. This
is an overview of the GML Visual template available within GameMaker. We’ll go through the structure of the project and see how
its various features have been implemented.
This page is divided into the following sections:
Overview
Rooms
Layers
Tile Sets
Movement & Animation
Collisions
Editor Walls
Props
Footstep Sounds
Enemy Movement
Ambient Sounds
Overview
The project consists of three main parts:
Player
Enemies
Environment
There are many more features that are implemented in the Hero's Trail complete game tutorial.
The player can move in all 4 directions and has animations for each
direction. The enemies follow a path that is pre-defined in the room.
These are the moving parts of the game, which are fully expanded upon
in the tutorials linked above, however the biggest part of this
project is its environment.
All of the above parts are explained in the sections below, and after
you’ve read all of it, you will have enough knowledge to modify and
to expand upon this base project.
Rooms
The project has three rooms:
rm_menu
rm_level_1
rm_level_2
rm_menu is the first room (as ordered in the Room
Manager) and serves as the game’s title screen.
Pressing “Play” on this screen takes you to the first level,
rm_level_1.
There is another room called rm_level_2, which is your canvas
to create a level your way. The base project does not let the player
continue into the second level, as that is implemented in Part 2
of the Hero’s Trail tutorials.
The rm_level_1 room has a lot of layers, which we’ll go
through later in this tutorial. Let’s first take a look at its Room
Properties, specifically the “Viewports and Cameras” section.
Viewports and Cameras
By default, GameMaker shows you the whole room when you run your
game. However, for games like Hero’s Trail, you only want to
see the area surrounding the player. This is achieved by creating a
camera with a specific resolution, which follows the player and
displays its surrounding area.
We have checked the “Enable Viewports” option and set
Viewport 0 to be visible. This is required for our camera to
function, which is set up in the rest of the options below.
The main properties we need to focus on here are the Width and
Height under “Camera Properties” and “Viewport
Properties”. The former is the size of the camera inside the
room, and the latter is the size of the game window (also known as
the viewport).
In this room, both of these are set to 1280x720. You can make the
camera size smaller than the viewport size, in which case the game
will be upscaled to fit the window.
This section lets you set up the camera so it follows a particular
object. We’ve assigned obj_player so it follows the player.
“Horizontal Border” and “Vertical Border” are the minimum
margins between the camera’s borders and the player before the
camera starts moving. We’ve set this to be half the camera’s
resolution so that the player always stays in the centre.
For more information on the camera settings, read the manual page on
Room
Properties.
Layers
The Hero’s Trail project uses various kinds of layers to achieve
its polished look. Let’s have a look at all of the layers in
rm_level_1:
The “Instances” layer, highlighted in the above image, is the
main layer that contains our player and enemy instances. All other
layers are placed either above or below this layer, depending on
where they should appear. There are two main layer groups that appear
on either side of the Instances layer:
Visuals_Below_Instances
|
Visuals_Above_Instances
|
These are visual layers that need to appear below the
player.
|
These are visual layers that need to appear above the
player.
|
These include floor, water and shadow tiles, and the walls that
need to appear behind the player
|
These include the wall tiles that need to appear on top and hide
any instances behind it
Important: If you edit the top tiles layer, you must also edit the
wall instances in the Wall_Collisions layer so the
collisions are updated.
|
The depth of the first layer in this group is set to 100 to
ensure that all layers that follow are drawn at a high
depth (appearing below other layers)
|
The depth of the last layer in this group is set to -12000 to
ensure that all layers above it are drawn at a low depth
(appearing above other layers)
|
For learning about Layers and their depth values, please read the
manual page on Layer
Properties.
Other Layers
Layer / Group
|
Description
|
Enemy_Paths
|
This group contains all Path Layers used by the enemy instances.
|
Wall_Collisions
|
This layer contains all wall instances that are used to stop the
player from moving into wall tiles. Note that its visibility is
turned off by default.
Important: Whenever you make any changes to the wall tiles,
you must edit the instances in this layer (or place new ones) so
the collisions are updated too.
|
Visuals_Above_Instances -> Lighting
|
This layer contains light instances that are placed on torch
tiles. This is used to achieve the glow that appears on all
torches.
|
Sound_Objects
|
This layer contains sound instances that are placed on torch and
fountain tiles. These instances handle playing the sound stored in
its sound_to_loop variable to achieve torch and fountain
ambience.
|
Tile Sets
Let’s take a look at the Tile Set assets that we use to build our
levels:
ts_floor
|
This Tile Set contains static tiles that are used to build the
floor and bridges. It also contains shadow tiles that are used in
a separate layer (“Tiles_Shadows”) to place shadows over water
tiles.
|
ts_walls
|
This Tile Set contains tiles used for the walls. A majority of
this Tile Set contains tiles used for Auto-Tiling,
which you can access from the “Auto Tiling” menu.
|
ts_animations
|
This Tile Set contains animated
tiles, which are placed in the
Visuals_Below_Instances group. This set comprises the water
tile, torch tile, fountain, flag, etc. The animations are created
from the various frames present within the Tile Set.
|
You can learn more about tiles on this page: A
Practical Guide to Using Tiles
Movement & Animation
The player object (obj_player) has a move_speed variable
that stores the amount of pixels it moves every frame. This value is
used in the Keyboard events to move it on the X or Y axis.
Within the Keyboard events, the “Set Instance Variable” action is
used with the Relative option to modify the instance’s position
based on the key that is held. For example, holding the Left key will
add -movespeed to the X coordinate, moving it left.
For animating the player’s movement, we make use of three separate
sprites:
Any one of these sprites are assigned to the player depending on
which key is held. In case of horizontal movement, the “side”
sprite is used, and the horizontal scale of the instance is simply
changed to make it turn left (-1) or right (1).
Collisions
Collisions can be complicated to implement, so this project contains
a simple but effective collision solution using GML Visual.
This is handled in a collision event with obj_collision_parent
(which is the parent of all objects that are used to stop
instances from moving):
This event runs once the player and a collision object (e.g. a wall)
have come into contact. At this point the player should stop, however
this results in a problem: if the player has only touched a wall
because of its movement on the X axis, it stops on both axes.
Ideally, it should stop only on the X axis and continue moving on Y,
given that there is room to move vertically. To achieve that we have
the following actions in the collision event:
This checks whether the player is not colliding with a wall
when its X position is returned to its previous frame (xprevious).
If that is true, the player jumps back to that X position and does
not otherwise stop (meaning it continues moving on the Y axis).
If the previous condition was false, it performs the same check on
the Y axis, and if that is true it jumps to that point. If neither of
these are true, it jumps to the previous position on both axes,
completely stopping the player’s movement.
Editor Walls
If you’ve made changes to any of the wall tiles, you will need to
update the contents of the Wall_Collisions layer. This is what
contains the actual collision boxes that stop the player from moving
into a wall, which are simply instances of the obj_editor_wall
object, and you can place them over some wall tiles by dragging
the object in from the Asset Browser:
The top area of the wall is not covered by the wall instance so the
player can freely walk “behind” that wall:
Make sure to make this layer invisible again once you are done editing it!
Props
The props placed around the room (barrels, chests, etc.) are children
of obj_collision_parent, much like obj_editor_wall (which
is placed over wall tiles). The difference is that the former are
visible obstacles, where the editor wall object is invisible.
To create more obstacles you can simply make them children of
obj_collision_parent and place them in the room.
Footstep Sounds
Footstep sounds make use of Broadcast
Messages. Every 5 frames the player’s animations
send out a broadcast message that simply says “step”, to tell the
player object that it should play a footstep sound.
This message is received by the player object in its Broadcast
Message event (found under “Other” events). If the message says
“step”, it plays a footstep sound:
That’s how simple it is!
Enemy Movement
The main enemy object, obj_baddie, uses Paths
for movement. Paths are pre-created sets of points which an instance
can follow.
The baddie object has a path_to_follow variable that can hold
a path asset. When the instance is created, it starts following that
path. Each baddie instance in the room has a different path assigned
to it (to change a variable for an instance, double-click on it and
open the “Variables” menu).
Since the enemy follows a predefined path, it does not receive
directional input like the player does, so it has to calculate where
it is moving by comparing its current position against its previous
position.
This is done in the End Step event, where it first retrieves the
speed values on the X and Y axis by performing a subtraction on the
current and previous X/Y positions.
Note: We have used the End Step event
as it runs after the Step event. This way we can perform actions
after the instance has moved in the main Step event.
It then performs a set of conditions to check whether the enemy is
moving right, left, down or up. In any of those cases it performs the
same actions as the player’s keyboard events, where its sprite and
horizontal scale are changed so it faces in the correct direction.
Ambient Sounds
The aforementioned “SoundObjects” room layer contains instances
of obj_sound_loop, which plays a sound on loop with varying
volume depending on the distance to the player. This is achieved in
its Step event, where it uses the point_distance()
function to get its distance from the player and then changes the
volume of its sound based on that distance.
The first “Set Audio Volume” action uses the min()
function which selects the minimum value from the ones provided to
it. This means that if the ‘100 / distance’ expression
happens to be greater than 1, it will simply use 1, meaning that the
audio volume will never go above that value.
Summary
The Hero’s Trail project is a great sandbox for you to create your
next action-adventure game. Make sure to follow the Hero's Trail full game tutorial so you can take this project to completion!
If there is anything else that you would like to learn about the Hero's Trail template project, reach out to us and we will make sure it is covered!
Happy GameMaking!