Hero's Trail | Base Project Breakdown/Overview


Hero's Trail | Base Project Breakdown/Overview

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.

undefined

This page is divided into the following sections:

  1. Overview

  2. Rooms

  3. Layers

  4. Tile Sets

  5. Movement & Animation

  6. Collisions

  7. Editor Walls

  8. Props

  9. Footstep Sounds

  10. Enemy Movement

  11. Ambient Sounds

Overview

The project consists of three main parts:

  1. Player

  2. Enemies

  3. 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.

undefined

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.

undefined

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.

undefined

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:

undefined

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
undefined

These include the wall tiles that need to appear on top and hide any instances behind it
undefined


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.

undefined

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.

undefined

For animating the player’s movement, we make use of three separate sprites:

Side

Down

Up

undefined

undefined


undefined

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):

undefined

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:

undefined

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:

undefined

The top area of the wall is not covered by the wall instance so the player can freely walk “behind” that wall:

undefined

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.

undefined

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:

undefined

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).

undefined

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.

undefined

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.

undefined

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!