0% found this document useful (0 votes)
8 views109 pages

Code (2)

The document outlines the implementation of collectible objects in a game, specifically focusing on chests and coins. It details the creation, movement, and destruction of these objects, including sound effects and visual effects like sparkles and shadows. Additionally, it describes the interactions between the player and these collectibles, including state changes and animations upon collection.

Uploaded by

Xuan Nguyen
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views109 pages

Code (2)

The document outlines the implementation of collectible objects in a game, specifically focusing on chests and coins. It details the creation, movement, and destruction of these objects, including sound effects and visual effects like sparkles and shadows. Additionally, it describes the interactions between the player and these collectibles, including state changes and animations upon collection.

Uploaded by

Xuan Nguyen
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 109

I.

Objects
1. Collectables
a. obj_chest (hộp kho báu)

● Create
// Creates a sequence manager object for the chests idle animation
sequence_body = instance_create_layer(x, y, "Stage", obj_sequence_manager);
// Sets the owner to the chest
sequence_body.owner = self;
// Sets the object to use the idle sequence
sequence_body.create_seq(seq_chest_idle, "Stage");

// Creates new shadow object instance


var _shadow = instance_create_layer(x, y, "StageShadows", obj_shadow);

// Sets the shadow instance to chest parameters and targets self as owner of it
_shadow.sprite_index = spr_chest_shadow;
_shadow.owner = self;
_shadow.set_y_offset(40);

// State for if idle


is_idle = true;

// Sound effect for the chest


chest_sound = audio_play_sound(snd_coin_chest, 100, true, 0.0);

// Function used for creating sparkles


create_sparkles = function()
{
// Creates and sets sparkle particles objects at 3 offset points setting
them to the correct effects aswell
var _sparkle_particle = instance_create_layer(x - 85, y - 85, "Stage",
obj_particle_manager);
_sparkle_particle.set_particle(ps_sparkle_chest, "StageBackEffects");
_sparkle_particle = instance_create_layer(x, y - 85, "Stage",
obj_particle_manager);
_sparkle_particle.set_particle(ps_sparkle_chest, "StageBackEffects");
_sparkle_particle = instance_create_layer(x + 85, y - 85, "Stage",
obj_particle_manager);
_sparkle_particle.set_particle(ps_sparkle_chest, "StageBackEffects");
}
● Step
// Checks the game is not currently paused
if (obj_game_manager.current_game_state != GAME_STATE.PAUSED)
{
// Moves the chest at the games current move speed
x -= obj_game_manager.current_speed * 1.0;

// Calls the create sparkle function


create_sparkles();

// Checks if the chest has gone off screen


if (x < 0 - 169)
{
// Sets self as a temporary variable
var _chest = self;

// Loops though the shadow objects within the room


with (obj_shadow)
{
// Checks if the shadows owner matches the chest
if (owner == _chest)
{
// Destroys the shadow as no longer needed
instance_destroy();
}
}

// Checks idle state is still active and not collected


if (is_idle)
{
// Destroys the sequence associated
layer_sequence_destroy(sequence_body.set_sequence);
// Destroys the bodys sequence object
instance_destroy(sequence_body);

// Stops chest sound


audio_stop_sound(chest_sound);

// Destroys the chest as no longer needed


instance_destroy();
}

}
}

// Checks chest is not collected


if (is_idle)
{
// Checks the game is playing
if (obj_game_manager.current_game_state ==
GAME_STATE.PLAYING)
{
// Checks if the chest is to the right of the player
if (x > obj_player.x)
{
// Scales the gain by the distance between player and chest
to the room width
audio_sound_gain(chest_sound, 1.0 - clamp(abs(x -
obj_player.x) / room_width, 0.0, 1.0), 0.0);
}
else
{
// Scales the gain by the distance between player and chest
to a fraction of the room width
audio_sound_gain(chest_sound, 1.0 - clamp(abs(x -
obj_player.x) / (room_width * 0.33), 0.0, 1.0), 0.0);
}
}
else
{
// Fades out the chest sounds
audio_sound_gain(chest_sound, 0.0, 3000);
}
}
● Draw
// Checks if in idle state
if (is_idle)
{
// Draws self
draw_self();
}
● →←obj_player
// Checks if the chest is still in idle state and not collected
if (is_idle)
{
// Stops chest idle sound
audio_stop_sound(chest_sound);
// Plays chest collected sound
audio_play_sound(snd_coin_chest_collection, 100, false, 1.0);

// Sets idle state to false since collected


is_idle = false;

// Destroys the sequence associated


layer_sequence_destroy(sequence_body.set_sequence);
// Destroys the bodys sequence object
instance_destroy(sequence_body);

// Creates a new sequece manager


sequence_body = instance_create_layer(x, y, "Stage",
obj_sequence_manager);
// Sets the owner of the manager to this object
sequence_body.owner = self;
// Creates a new sequence to this chest breaking for the manager object
sequence_body.create_seq(seq_chest_breaking, "Stage");

// New temp function to be called after the chest breaking sequence ends
var _new_function = function()
{
// Destroys this object
instance_destroy(self);
}

// Creates new chest blast particle object


var _blast_particle = instance_create_layer(x, y, "Stage",
obj_particle_manager);
// Sets objects particle effect and layer target
_blast_particle.set_particle(ps_chest_blast, "StageBackEffects");

// Loops through for loop for horizontal positions


for (var _i = 0; _i < 5; _i++)
{
// Loops through for loop for virtical postions
for (var _j = 0; _j < 2; _j++)
{
// Creates new coin gui object
var _gui_coin = instance_create_layer(x - 75 + (150 / 4) *
(_i), y - 25 + _j * 50, "StageFront", obj_coin_gui);

// Creates new coin particle object


var _coin_particle = instance_create_layer(_gui_coin.x,
_gui_coin.y, "Stage", obj_particle_manager);
// Sets the particle objects parent to the gui coin
_coin_particle.owner = _gui_coin;
// Sets objects particle effect and layer target
_coin_particle.set_particle(ps_coin, "StageBackEffects");

// Sets the gui coins child object as the new particle


_gui_coin.child_particle = _coin_particle;
}
}

// Sets self as a temporary variable


var _chest = self;

// Loops though the shadow objects within the room


with (obj_shadow)
{
// Loops though the shadow objects within the room
if (owner == _chest)
{
// Creates a fade out for the shadow
fade_out(0.33);
}
}
}

b. obj_coin_gui
● Create
// Creates a random angle plus or minus 30 degrees to move the gui coin in for
variation
image_adjust = random_range(-30, 30);
// Sets the direction to head left with the added variation
direction = 180 + image_adjust;

// Sets the gui coins current speed to the games current speed
current_speed = obj_game_manager.current_speed;
// Applies this variable to the speed variable for movement updates
speed = current_speed;

// Sets the sprite to be visible


image_alpha = 1;

// Sets the sprite to be at full scale


image_xscale = 1;
image_yscale = 1;

// Sets an empty child particle variable, this is set when the instance is created
child_particle = noone;

// Adds gold to the game managers totals


obj_game_manager.current_gold++;
obj_game_manager.current_level_gold++;

● Destroy
// Checks if the child particle object still exists
if (instance_exists(child_particle))
{
// Sets the particle to have no parent so its movement will stop tracking
child_particle.owner = noone;
}
● Step
// Checks the game is not curently paused
if (obj_game_manager.current_game_state != GAME_STATE.PAUSED)
{
// Calculates the target direction of where the coin symbol is on the score
GUI
var _target_direction = point_direction(x, y, obj_gui.x - 5, obj_gui.y +
50);
// Calculates the difference in directions between the direction headed
and the target
var _dir_difference = angle_difference(_target_direction, direction);
// Adjusts the direction slowly at a rate of the directional difference
direction += _dir_difference * 0.1;

// Adjust the current speed variable to slower value at a slow rate


current_speed = lerp(current_speed, 10, 0.05);
// Applies the adjusted speed the the speed variable for movement
speed = current_speed;

// Sets the sprite image angle to the new direction with the adjusted
angles added
image_angle = direction - image_adjust + 180;

// Lerps the sprite variables to fade out and scale down


image_alpha = lerp(image_alpha, 0, 0.005);
image_xscale = lerp(image_xscale, 0, 0.01);
image_yscale = lerp(image_yscale, 0, 0.01);

// Checks if the image is no longer visible


if (image_alpha <= 0.1)
{
// Destroys the image
instance_destroy();
}
}
else
{
// Sets the speed to zero if paused to stop movement
speed = 0;
}
● →← obj_gui
// Destroys this GUI coin object when in contact with the Score gui's coin mask
instance_destroy();

c. obj_pickup_coin(>>)
● Create
randomise();
current_level = 1;
current_level_gold = 0;
current_distance = 0;
current_gold = 0;

// Stops the music track that was previously playing


audio_stop_sound(global.music);

// Checks if the game has been played before


if (global.times_played == 0)
{
// Sets the game state to tutorial mode
current_game_state = GAME_STATE.TUTORIAL;
// Creates the tutorial object
instance_create_layer(room_width * 0.5, room_height * 0.5, "GUI",
obj_tutorial);

// Play audio for tutorial


global.music = audio_play_sound(snd_ambience, 100, true, 1.0);
}
else
{
// Sets the game to play normally
current_game_state = GAME_STATE.PLAYING;

// Spawns the inital GameMaker logo in coins to fill in dead space


layer_sequence_create("Stage", 0, 0, seq_gm_layout);

// Checks if a highscore has been previously set


if (global.highscore != 0)
{
// Creates a flag object for the highscore at its position it would be
in
var _flag = instance_create_layer(640 + real(global.highscore) *
60, 950, "StageBack", obj_flag_marker);
// Sets the flag paramerters to know it has droppped and the score it
should have
_flag.has_dropped = true;
_flag.flag_distance = global.highscore;
}

// Plays the games main music


global.music = audio_play_sound(snd_infinite_runner_music, 100,
true, 0.5);
}

// Counts up the times played


global.times_played++;

/// Variables used to control the players speed


// Min speed is the slowest possible speed for players (ie zero for
stopped)
min_speed = 0.0;
// Max speed is the current maximum speed allowed (Boosted speed)
max_speed = 24.0;
// Sets the new max speed as the current max speed (this variable is what
adjusts the games speed curves
new_max_speed = max_speed;
// True max speed the the absolute fastest a player can go
true_max_speed = 72.0;

// Current speed is what tracks current movement for the backgrounds


and level elements that need to move over time
current_speed = 0.0;

// The speed percentages are used to gradually increase and decrease the
speed using smooth step interpolation
current_speed_percentage = 0.0;
target_speed_percentage = 0.5;

// The rate speed will go up or down so the player will stop or slow
down quicker than speeding up
speed_up_rate = 0.2;
speed_down_rate = 0.5;

// Initial cooldown for the background changing


background_cooldown = 100;

// Flag used to check if the environments have finished loading to before


starting the game
has_prefetched = false;

// Creates game objects for room environment


instance_create_layer(0, 0, "Farground", obj_far_background);
instance_create_layer(0, 0, "Midground", obj_interior_background);
instance_create_layer(0, 0, "Midground", obj_mid_background);
instance_create_layer(0, 0, "Foreground", obj_front_floor);
instance_create_layer(0, 0, "Foreground", obj_front_ceiling);

// Creates player object


instance_create_layer(0, 0, "Stage", obj_player);

// Add game paused variable for quiz popup


global.game_paused = false;

// Function used to update the speed with delta time passed though as
that is the time passed this frame meaning more accurate movement
update_speed = function(_delta_time)
{
// Checks if a player has collected 50 gold since the last time they
leveled up
if (current_level_gold >= 50)
{
// Removed the gold from their current count
current_level_gold -= 50;
// Increases the level
current_level++;
// Sets the max speed to be 5% faster
new_max_speed = max_speed * 1.05;
}

// Limits the max speed to the true max speed


if (new_max_speed > true_max_speed)
{
// Sets max to true max
new_max_speed = true_max_speed;
}

// Checks if new max speed has changed.


if (new_max_speed != max_speed)
{
// Adjusts the percentage.
current_speed_percentage *= max_speed / new_max_speed;
// Sets max speed to new value.
max_speed = new_max_speed;
}

// Check if speed is less than target.


if (current_speed_percentage < target_speed_percentage)
{
// Speed up at rate.
current_speed_percentage += speed_up_rate * _delta_time;

// Limit speed to target.


current_speed_percentage = min(current_speed_percentage,
target_speed_percentage);

// Interpolate speed using smoothstep curve.


current_speed = smoothstep(min_speed, max_speed,
current_speed_percentage);
}
// Check if speed is greater than target.
else if (current_speed_percentage > target_speed_percentage)
{
// Slow down at rate.
current_speed_percentage -= speed_down_rate * _delta_time;

// Limit speed to target.


current_speed_percentage = max(current_speed_percentage,
target_speed_percentage);

// Interpolate speed using smoothstep curve.


current_speed = smoothstep(min_speed, max_speed,
current_speed_percentage);
}

// Checks if game is not running in tutorial mode


if (current_game_state != GAME_STATE.TUTORIAL)
{
// Add current speed to distance traveled.
current_distance += current_speed * _delta_time;
}
}
● Step
// Checks the game is not currently paused (by game state)
if (obj_game_manager.current_game_state != GAME_STATE.PAUSED)
{
// Moves the pickup at the games current speed
x -= obj_game_manager.current_speed * 1.0;

// Checks if pickup has gone off screen to the left


if (x < 0 - 169)
{
// Destroys the pickup object
instance_destroy();
}

// Sets the animation speed to playing when not paused


image_speed = 1;
}
else
{
// Sets the animation speed to stop when game is paused
image_speed = 0;
}
● →← obj_player
// Create quiz popup instead of applying boost immediately
var quiz = instance_create_layer(0, 0, "GUI", obj_quiz_popup);
quiz.buff_type = "boost";
quiz.player_instance = other;
instance_destroy();

d. obj_pickup_coin
● Step
// Checks if the game is currently paused
if (obj_game_manager.current_game_state !=
GAME_STATE.PAUSED)
{
// Moves the coin objects left at the games current move speed
x -= obj_game_manager.current_speed * 1.0;

// Checks if the coins have gone offscreen


if (x < 0 - 169)
{
// Destroys the coins
instance_destroy();
}

// Sets the animation speed to playing


image_speed = 1;
}
else
{
// Pauses the animation speed
image_speed = 0;
}

● →← obj_player
// Checks if the coins current sprite not collected
if (sprite_index == spr_coin_idle)
{
// Creates a new gui coin object
var _gui_coin = instance_create_layer(x, y, "StageFront", obj_coin_gui);

// Creates a new coin particle object


var _coin_particle = instance_create_layer(_gui_coin.x, _gui_coin.y,
"Stage", obj_particle_manager);
// Sets the gui coin as the particle objects owner
_coin_particle.owner = _gui_coin;
// Sets the particle object to use the coin particle effect on the layer
specified
_coin_particle.set_particle(ps_coin, "StageFrontEffects");

// Sets the gui coin object to store the particle object it is attached to
_gui_coin.child_particle = _coin_particle;
// Plays coin collected sound
audio_play_sound(snd_coin_collection, 100, false, 1.0);

// Destroys this coin since it was collected


instance_destroy();
}
● Animation End
// Checks if the coin is collecting
if (sprite_index == spr_coin_colleting)
{
// Destroys the instance for the coin pickup
instance_destroy();

e. obj_pickup_shield(khiêng)
● Step
// Checks the current game state is not paused (by game state)
if (obj_game_manager.current_game_state !=
GAME_STATE.PAUSED)
{
// Moves the pick ups position at the games current speed
x -= obj_game_manager.current_speed * 1.0;

// Checks if the object has gone off screen to the left


if (x < 0 - 169)
{
// Destroys the pickup
instance_destroy();
}

// Plays the sprites animation speed normally


image_speed = 1;
}
else
{
// Pauses the animation speed if the game is paused
image_speed = 0;
}
● →← obj_player
// Create quiz popup instead of applying shield immediately
var quiz = instance_create_layer(0, 0, "GUI", obj_quiz_popup);
quiz.buff_type = "shield_new";
quiz.player_instance = other;
instance_destroy();
● →← obj_shield
// Checks if the shield still has life
if (other.life > 0)
{
// Adds life to the shield so it lasts longer
other.life += 10.0;

// Creates and sets a new particle handler object with the power up
collected particle effect attached to the player
var _new_aura_particle = instance_create_layer(obj_player.x,
obj_player.y, "Stage", obj_particle_manager);
_new_aura_particle.owner = obj_player;
_new_aura_particle.set_particle(ps_powerup_in, "StageFrontEffects");

// Plays collect sound


audio_play_sound(snd_shield_bonus_collection, 100, false, 1.0);

// Destroys the pickup


instance_destroy();
}

2. Enviroment
a. obj_far_bacground
● Create
// Creates an array and stores background sprites to it
sprites[0] = spr_farground_1;
sprites[1] = spr_farground_2;
sprites[2] = spr_farground_3;

// Fetches the sprite array to load them into the system resources
sprite_prefetch_multi(sprites);

// Sets sprite variables to the sprites from the array


before_sprite = sprites[0];
sprite_index = sprites[1];
after_sprite = sprites[2];
// Sets coordinates to a random x value less than the sprite width moving
it along
x = random_range(0, sprite_width);
y = 0;

// Sets the move rate for parallaxing effect


background_move_rate = 0.4;

● Step
// Checks the game is not currently paused
if (obj_game_manager.current_game_state !=
GAME_STATE.PAUSED)
{
// Reduces the x position by the current speed and move rate
x -= obj_game_manager.current_speed * background_move_rate;

// Checks if the x coordinate is less than the origin


if (x < 0)
{
// Sets the before sprite to the indexed (current) one
before_sprite = sprite_index;
// Sets the current sprite to the one after
sprite_index = after_sprite;

// Check what sprite the last one was set to and then set up
the appropriate sprite to follow
switch(after_sprite)
{
case sprites[0]:
after_sprite = sprites[1];
break;
case sprites[1]:
after_sprite = sprites[2];
break;
case sprites[2]:
after_sprite = sprites[0];
break;
}
// Move the x position forward the sprite width to move
the sprites draw positions
x += sprite_width;
}
}

● Draw
// Draw the before sprite at an offset of minus its width
draw_sprite(before_sprite, 0, x - sprite_get_width(before_sprite), y);
// Draw the main/middle sprite
draw_self();
// Draw the final sprite at an offset of its width
draw_sprite(after_sprite, 0, x + sprite_width, y);

b. obj_firework
● Create
// Variables set up for firework to use after being set
life = 0;
delay = 0;
death = 0;

// Tilt variable set to random swing of 10 degrees either way


tilt = random_range(-10, 10);
// Direction set to face up with added tilt
direction = 90 + tilt;

// Sets the inital fire speed


fire_speed = 1;

// Particle effects to be used for the firework


trail_ps = ps_firework_trail;
head_ps = ps_firework;

// Plays firework trail sound


var _sfx_trail = audio_play_sound(snd_celebration_firework, 100, false,
0.25, 0.0, random_range(0.95, 1.05));
audio_sound_set_track_position(_sfx_trail, 3.0);
audio_sound_gain(_sfx_trail, 0.0, 1750);

// Create ps function called to create new particle effect later


create_ps = function(_type)
{
var _new_particle = instance_create_layer(x, y, "Stage",
obj_particle_manager);
_new_particle.set_particle(_type, "StageBackEffects");
_new_particle.set_angle(tilt);
}
● Step
// Checks the game is not currently paused
if (obj_game_manager.current_game_state != GAME_STATE.PAUSED)
{
// Set the x position to move at the games current speed
x -= obj_game_manager.current_speed;
// Speeds up the fireworks rocket speed
fire_speed *= 1.005;
// Sets the speed to the new fire speed (done this was to retain the current
value if paused)
speed = fire_speed;

// Adds time to the time alive


life += delta_time * 0.000001;

// Checks if the firework has been alive for longer than the delay
attached so visually only appears after a set time
if (life > delay)
{
// Creates a new particle effect for the trail
create_ps(trail_ps);
}

// Checks if the firework has been alive long enough for its final
explosion
if (life > death)
{
// Creates the final particle effect for the explosions head
create_ps(head_ps);

// Chooses a random bang sound


var _sfx_bang = choose(snd_firework_bang_1,
snd_firework_bang_2, snd_firework_bang_3);
// Plays firework bang sound
audio_play_sound(_sfx_bang, 100, false, 0.5);

// Plays firework crackle sound


var _sfx_crackle = audio_play_sound(snd_celebration_firework,
100, false, 0.5, 0.5, random_range(0.95, 1.05));
audio_sound_set_track_position(_sfx_crackle, 5.0);

// Destroys the firework object


instance_destroy();
}
}
else
{
// Pauses the move speed
speed = 0;
}

c. obj_flower
● Step
// Checks if the game has been paused
if (obj_game_manager.current_game_state !=
GAME_STATE.PAUSED)
{
// Moves the flowers x position along at the games current speed
x -= obj_game_manager.current_speed * 1.0;

// Checks if the coordinate moves beyond the left offscreen


threshold
if (x < 0 - 59)
{
// Destroys the flower
instance_destroy();
}
}

d. obj_front_ceiling
● Create
// Keeps count of how many vines can be created
fauna_count = 2;

// Creates an empty array of x positions


x_coords = array_create(fauna_count, 0);
// Creates an empty array of unset sprites
set_sprites = array_create(fauna_count, -1);
// Creates an empty array of alpha values
set_alphas = array_create(fauna_count, 1.0);

// Sets the inital sprite in a sprite array to vine sprite


sprite[0] = spr_foreground_celing_1;

// Loops through the vines


for (var _i = 0; _i < fauna_count; _i++)
{
// Sets the sprite (Array and choose function used since you may
want to add more vines later!)
//set_sprites[_i] = choose(sprite[0]);
set_sprites[_i] = sprite[0];

// Temp variables for checking if the position has been set and
how many attempts have been made
var _pos_set = false;
var _attempts = 0;

// Checks position hasnt been set


while (!_pos_set)
{
// Sets position with added offset of attempts
x_coords[_i] = random_range(0, room_width * (2 + 1 *
_attempts));

// Adjusts the temp variables


_pos_set = true;
_attempts++;

// Loops through the existing vines


for (var _j = 0; _j < fauna_count; _j++)
{
// Checks they are not the same as the current fauna
being set
if (_i != _j)
{
// Checks if the sprites would be overlapping
if (x_coords[_i] +
sprite_get_width(set_sprites[_i]) > x_coords[_j] && x_coords[_i] <
x_coords[_j] + sprite_get_width(set_sprites[_j]))
{
// Changes the set flag to false
_pos_set = false;
}
}
}
}
}

// Sets the y position value to origin


y = 0;
// Sets default move rate
move_rate = 1.1;
● Step
// Checks if the game is currently paused
if (obj_game_manager.current_game_state != GAME_STATE.PAUSED)
{
// Loops through the current fauna
for (var _i = 0; _i < fauna_count; _i++)
{
// Moves the x position by the speed and set rate
x_coords[_i] -= obj_game_manager.current_speed * move_rate;

// Checks if the fauna has left the left of the screen


if (x_coords[_i] + sprite_get_width(set_sprites[_i]) < 0)
{
// Sets the sprite (Array and choose function used since
you may want to add more vines later!)
//set_sprites[_i] = choose(sprite[0]);
set_sprites[_i] = sprite[0];

// Sets the temp variables


var _pos_set = false;
var _attempts = 0;

// Checks if not set


while (!_pos_set)
{
// Sets the x position with offset based on attempts
x_coords[_i] = room_width +
sprite_get_width(set_sprites[_i]) + room_width * (1 + 1 * _attempts);

// Changes the set temp values


_pos_set = true;
_attempts++;

// Loops through the fauna


for (var _j = 0; _j < fauna_count; _j++)
{
// Checks new fauna dosen't match one being
set
if (_i != _j)
{
// Calculates if the spites would be
intersecting
if (x_coords[_i] +
sprite_get_width(set_sprites[_i]) > x_coords[_j] && x_coords[_i] <
x_coords[_j] + sprite_get_width(set_sprites[_j]))
{
// Unsets the position
_pos_set = false;
}
}
}
}
}

// Checks if the x postion is greater than the rooms width (aka


offscreen)
if (x_coords[_i] > room_width)
{
// Checks if the level is currently inside or out
if (obj_interior_background.current_pipe_state ==
INTERIOR_STATE.OUTSIDE)
{
// Shows the vines if outside
set_alphas[_i] = 1.0;
}
else
{
// Hides the vines if inside
set_alphas[_i] = 0.0;
}
}
}
}
● Draw
// Loops through the vines
for (var _i = 0; _i < fauna_count; _i++)
{
// Sets the draw alpha values
draw_set_alpha(set_alphas[_i]);
// Draws the sprites at set positions
draw_sprite(set_sprites[_i], 0, x_coords[_i], y);
}

// Sets the draw alpha back to default


draw_set_alpha(1.0);

e. obj_front_floor
● Create
// Variable for how many bushes can exist at once
fauna_count = 5;

// Creates array for the x positions


x_coords = array_create(fauna_count, 0);
// Creates array for the sprites to be used
set_sprites = array_create(fauna_count, -1);
// Creates array for the alpha values (hide/show)
set_alphas = array_create(fauna_count, 1.0);

// Fill the sprite array with the sprites created


sprite[0] = spr_foreground_floor_1;
sprite[1] = spr_foreground_floor_2;
sprite[2] = spr_foreground_floor_3;
sprite[3] = spr_foreground_floor_4;

// Calls prefetch function to call the sprites into system resources


sprite_prefetch_multi(sprite);
// Loops through the array of bushes
for (var _i = 0; _i < fauna_count; _i++)
{
// Sets bush up with random sprite
set_sprites[_i] = choose(sprite[0], sprite[1], sprite[2], sprite[3]);

// Creates temp variables for placement checking


var _pos_set = false;
var _attempts = 0;

// Loops when not set


while (!_pos_set)
{
// Sets at random coordinates with offset added for failed
attempts
x_coords[_i] = random_range(0, room_width * (2 + 1 *
_attempts));

// Changes the temp values


_pos_set = true;
_attempts++;

// Loops through the existing bushes


for (var _j = 0; _j < fauna_count; _j++)
{
// Checks bush is not the same
if (_i != _j)
{
// Checks if the sprites are overlapping
if (x_coords[_i] +
sprite_get_width(set_sprites[_i]) > x_coords[_j] && x_coords[_i] <
x_coords[_j] + sprite_get_width(set_sprites[_j]))
{
// Changes flag to not set
_pos_set = false;
}
}
}
}
}
// Sets the y position to room height
y = room_height;
// Sets the move rate for parallaxing
move_rate = 1.1;
● Step
// Checks the game is not currently paused
if (obj_game_manager.current_game_state != GAME_STATE.PAUSED)
{
// Loops through the bushes
for (var _i = 0; _i < fauna_count; _i++)
{
// Moves the x positions based on the current speed and
parallaxing move rate
x_coords[_i] -= obj_game_manager.current_speed * move_rate;

// Checks if the bush has left the left side of the screen
if (x_coords[_i] + sprite_get_width(set_sprites[_i]) < 0)
{
// Changes the bushes sprite
set_sprites[_i] = choose(sprite[0], sprite[1], sprite[2],
sprite[3]);

// Creates temp values for placement checking


var _pos_set = false;
var _attempts = 0;

// Loops when not set


while (!_pos_set)
{
// Sets x position at random with attempt count
adding to help hanging here
x_coords[_i] = room_width +
sprite_get_width(set_sprites[_i]) + random_range(0, room_width * (1 + 1 *
_attempts));

// Changes the values since now set


_pos_set = true;
_attempts++;

// Loops through the bushes again


for (var _j = 0; _j < fauna_count; _j++)
{
// Checks they are not the same
if (_i != _j)
{
// Checks the sprites are not
intersecting
if (x_coords[_i] +
sprite_get_width(set_sprites[_i]) > x_coords[_j] && x_coords[_i] <
x_coords[_j] + sprite_get_width(set_sprites[_j]))
{
// Unsets flag so loop will
reattempt placement
_pos_set = false;
}
}
}
}

// Checks when bush hasnt entered room yet


if (x_coords[_i] > room_width)
{
// Checks if game is inside or outside
if (obj_interior_background.current_ground_state ==
INTERIOR_STATE.OUTSIDE)
{
// Sets to visible bush since outside
set_alphas[_i] = 1.0;
}
else
{
// Hides bush since inside
set_alphas[_i] = 0.0;
}
}
}
}
● Draw
// Loops though the bushes
for (var _i = 0; _i < fauna_count; _i++)
{
// Sets the bushes alpha independently
draw_set_alpha(set_alphas[_i]);
// Draws the bush with its set sprite at its set coordinate
draw_sprite(set_sprites[_i], 0, x_coords[_i], y + 40);
}

// Resets the alpha back to normal


draw_set_alpha(1.0);

f. obj_interior_bacground
● Create
// Enum state for the interior states used
enum INTERIOR_STATE
{
OUTSIDE,
ENTER,
INSIDE,
EXIT,
SIZE
}

// Sets the inital interior state to outside


current_interior_state = INTERIOR_STATE.OUTSIDE;

// Sets all the environment wall, ground, pipe states to outside


current_wall_state = INTERIOR_STATE.OUTSIDE;
current_ground_state = INTERIOR_STATE.OUTSIDE;
current_pipe_state = INTERIOR_STATE.OUTSIDE;

// Sets state for knowing when a wall has changed


has_wall_changed = false;

// Count for how many walls can exist


wall_segment_count = 3;

// Stores the walls sprites within an array


wall_sprite[0] = spr_wall_1;
wall_sprite[1] = spr_wall_2;
wall_sprite[2] = spr_wall_3;
wall_sprite[3] = spr_wall_start;
wall_sprite[4] = spr_wall_end;

// Prefetches the sprite array to load into system resources (prevents


potential hanging when they are changed later)
sprite_prefetch_multi(wall_sprite);

// Creates an array for the set wall sprites to exist in


set_wall_sprites = array_create(wall_segment_count, -1);
// Creates an array of wall coordinates
wall_x_coords = array_create(wall_segment_count, 0);

// Sets the y coordinate to 0


wall_y_coords = 0;

// Sets the count for how many pipe segements will exist
pipe_segment_count = 3;

// Fills an array for all the pipe sprites


pipe_sprite[0] = spr_pipe_start;
pipe_sprite[1] = spr_pipe_mid;
pipe_sprite[2] = spr_pipe_end;

// Prefethes the sprite array (again prevents hanging)


sprite_prefetch_multi(pipe_sprite);

// Creates an array for the set sprites (what is drawn)


set_pipe_sprites = array_create(wall_segment_count, -1);
// Creates and array of pipe x coordinates
pipe_x_coords = array_create(wall_segment_count, 0);

// Creates the pipes y coordinate


pipe_y_coords = 0;

// Variable for the ground segment count (larger since these sprites are
smaller so more are needed to fill the screen)
ground_segment_count = 5;

// Stores the sprites for the runways within an array


ground_sprite[0] = spr_runway_inside_start;
ground_sprite[1] = spr_runway_inside_mid;
ground_sprite[2] = spr_runway_inside_end;
ground_sprite[3] = spr_runway_outside_1;
ground_sprite[4] = spr_runway_outside_2;
ground_sprite[5] = spr_runway_outside_3;

// Prefetches all the ground sprites from the array (again preventing
hanging later when needed for the first time)
sprite_prefetch_multi(ground_sprite);

// Array for seting the sprites drawn in


set_ground_sprites = array_create(ground_segment_count, -1);
// Array for the x coordinates positions
ground_x_coords = array_create(ground_segment_count, 0);

// Loops through the ground segments


for (var _i = 0; _i < ground_segment_count; _i++)
{
// Sets the sprite to follow a pattern (the last 3 from array drawn
outside 1, outside 2, outside 3)
set_ground_sprites[_i] = ground_sprite[3 + (_i % 3)];
// Sets the sprites x coordinates
ground_x_coords[_i] = 0 + 512 * _i;
}

// Sets the y coordinate


ground_y_coords = 610;

// Sets the backgrounds parallaxing move rate


background_move_rate = 1.0;

// Function for changing the interior state (swapping inside and outside
environments and back again)
change_interior_state = function()
{
// Checks what the current state is
switch (current_interior_state)
{
// When inside
case INTERIOR_STATE.INSIDE:
// Will only trigger when all environments are in
inside state
if (current_wall_state ==
INTERIOR_STATE.INSIDE &&
current_ground_state ==
INTERIOR_STATE.INSIDE &&
current_pipe_state ==
INTERIOR_STATE.INSIDE)
{
// Enters exit state
current_interior_state =
INTERIOR_STATE.EXIT;
}
break;

// When outside
case INTERIOR_STATE.OUTSIDE:
// Will only trigger when all environments are in
outside state
if (current_wall_state ==
INTERIOR_STATE.OUTSIDE &&
current_ground_state ==
INTERIOR_STATE.OUTSIDE &&
current_pipe_state ==
INTERIOR_STATE.OUTSIDE)
{
// Changes to enter state
current_interior_state =
INTERIOR_STATE.ENTER;
}
break;
}
}

// Functions for setting flowers


// Each set is created for the ground sprite bounds but are varied
// Flower object is created at random bounds from the coordinates set
// Object is then given a pre determined sprite based on those bounds
flower_set_1 = function(_x, _y)
{
var _flower_1 = instance_create_layer(_x + random_range(268,
500), _y + random_range(200, 230), "Flowers", obj_flower);
_flower_1.sprite_index = spr_flower_1;

var _flower_2 = instance_create_layer(_x + random_range(12,


246), _y + random_range(220, 250), "Flowers", obj_flower);
_flower_2.sprite_index = spr_flower_2;
}
flower_set_2 = function(_x, _y)
{
var _flower_1 = instance_create_layer(_x + random_range(268,
500), _y + random_range(200, 230), "Flowers", obj_flower);
_flower_1.sprite_index = spr_flower_1;

var _flower_3 = instance_create_layer(_x + random_range(12,


246), _y + random_range(200, 250), "Flowers", obj_flower);
_flower_3.sprite_index = spr_flower_3;
}
flower_set_3 = function(_x, _y)
{
var _flower_2 = instance_create_layer(_x + random_range(12,
246), _y + random_range(220, 250), "Flowers", obj_flower);
_flower_2.sprite_index = spr_flower_2;
var _flower_3 = instance_create_layer(_x + random_range(268,
500), _y + random_range(200, 250), "Flowers", obj_flower);
_flower_3.sprite_index = spr_flower_3;
}
flower_set_4 = function(_x, _y)
{
var _flower_2 = instance_create_layer(_x + random_range(268,
500), _y + random_range(220, 250), "Flowers", obj_flower);
_flower_2.sprite_index = spr_flower_2;
var _flower_3 = instance_create_layer(_x + random_range(12,
246), _y + random_range(200, 250), "Flowers", obj_flower);
_flower_3.sprite_index = spr_flower_3;
}

// Loops through the ground segements


for (var _i = 0; _i < ground_segment_count; _i++)
{
// Chooses a random flower set function
var _handle = choose(flower_set_1, flower_set_2, flower_set_3,
flower_set_4);
// Calls the chosen set function with the custom coordinates
_handle(ground_x_coords[_i], ground_y_coords);
}

// Tells the gamemanager that this object has prefetched since relies on
many sprite resources so it is safe to start the game
obj_game_manager.has_prefetched = true;
● Step
// Checks if the game is currently paused
if (obj_game_manager.current_game_state != GAME_STATE.PAUSED)
{
// Checks what state the game should be
switch(current_interior_state)
{
// When entering
case INTERIOR_STATE.ENTER:
// Sets walls and pipes to enter and pushes overall state to
inside
current_wall_state = INTERIOR_STATE.ENTER;
current_pipe_state = INTERIOR_STATE.ENTER;
current_interior_state = INTERIOR_STATE.INSIDE;
break;
// When exiting
case INTERIOR_STATE.EXIT:
// Sets a flag for the walls to change and its state to exit
has_wall_changed = true;
current_wall_state = INTERIOR_STATE.EXIT;
// Pushes overall state to outside
current_interior_state = INTERIOR_STATE.OUTSIDE;
break;
}

// Loops through all wall segments


for (var _i = 0; _i < wall_segment_count; _i++)
{
// Changes the x positions based on speed and parallaxing rate
wall_x_coords[_i] -= obj_game_manager.current_speed *
background_move_rate;
}

// Loops through all the wall segements again


for (var _i = 0; _i < wall_segment_count; _i++)
{
// Creates a value to store width of the walls
var _width = 0;

// Checks sprite exists


if (set_wall_sprites[_i] != -1)
{
// Sets value to sprites width (Not always the same)
_width = sprite_get_width(set_wall_sprites[_i]);
}

// Checks if the current wall is offscreen


if (wall_x_coords[_i] < -_width)
{
// Checks the walls current state
switch(current_wall_state)
{
// When entering
case INTERIOR_STATE.ENTER:
// Sets enter wall
set_wall_sprites[_i] = wall_sprite[3];
// Changes the wall state to inside
current_wall_state =
INTERIOR_STATE.INSIDE;
// Changes the ground state to enter (so dirt
path ends only when inside)
current_ground_state =
INTERIOR_STATE.ENTER;
break;
// When inside
case INTERIOR_STATE.INSIDE:
// Change sprite to a random interior wall
set_wall_sprites[_i] = choose(wall_sprite[0],
wall_sprite[1], wall_sprite[2]);
break;
// When exiting
case INTERIOR_STATE.EXIT:
// Sets the exit wall sprite
set_wall_sprites[_i] = wall_sprite[4];
// Changes the wall state
current_wall_state =
INTERIOR_STATE.OUTSIDE;
break;
// When outside
case INTERIOR_STATE.OUTSIDE:
// Checks the wall has changed
if (has_wall_changed)
{
// Changes the ground state to exit
current_ground_state =
INTERIOR_STATE.EXIT;
// Changes wall has changed state flag
back to false
has_wall_changed = false;
}
// Unsets sprite since the are walls outside
set_wall_sprites[_i] = -1;
break;
}

// Creates minimum room width variable (used to set


where the final x position should be when placed)
var _min_x = room_width;

// Loops all the wall segements again


for (var _j = 0; _j < wall_segment_count; _j++)
{
// Checks the wall segment isnt the same and has
been set
if (_i != _j && set_wall_sprites[_j] != -1)
{
// Sets the wall segment to the highest value
(itself or the other sprite coordinate plus its width
_min_x = max(_min_x, wall_x_coords[_j] +
sprite_get_width(set_wall_sprites[_j]));
}
}

// Sets the new x position


wall_x_coords[_i] = _min_x;
}
}

// Loops through all the pipe segments


for (var _i = 0; _i < pipe_segment_count; _i++)
{
// Moves their x coordinates by speed and parallaxing rate
pipe_x_coords[_i] -= obj_game_manager.current_speed *
background_move_rate;
}

// Loops through all the pipes again now their positions have been
changed
for (var _i = 0; _i < pipe_segment_count; _i++)
{
// Sets a width variable
var _width = 0;

// Checks the pipe sprite exists


if (set_pipe_sprites[_i] != -1)
{
// Sets the width to the sprite width
_width = sprite_get_width(set_pipe_sprites[_i]);
}

// Checks if the pipe is now off screen


if (pipe_x_coords[_i] < -_width)
{
// Check what state pipes are currently
switch(current_pipe_state)
{
// When enter
case INTERIOR_STATE.ENTER:
// Set enter sprite
set_pipe_sprites[_i] = pipe_sprite[0];
// Change state to inside
current_pipe_state =
INTERIOR_STATE.INSIDE;
break;
// When inside
case INTERIOR_STATE.INSIDE:
// Set to inside sprite
set_pipe_sprites[_i] = pipe_sprite[1];
break;
// When exit
case INTERIOR_STATE.EXIT:
// Set to exit sprite
set_pipe_sprites[_i] = pipe_sprite[2];
// Change state to outside
current_pipe_state =
INTERIOR_STATE.OUTSIDE;
break;
// When outside
case INTERIOR_STATE.OUTSIDE:
// Unset sprite since no pipes when outside
set_pipe_sprites[_i] = -1;
break;
}

// Variable for minimum x spawn position


var _min_x = room_width;

// Loop through the pipe segments again


for (var _j = 0; _j < pipe_segment_count; _j++)
{
// Check pipes are not the same and has been set
if (_i != _j && set_pipe_sprites[_j] != -1)
{
// Adjust the minimum x coordinate possible
again checking for the highest value of itself or the other cordinate and width
_min_x = max(_min_x, pipe_x_coords[_j] +
sprite_get_width(set_pipe_sprites[_j]));
}
}

// Sets the pipes new x position


pipe_x_coords[_i] = _min_x;
}
}

// Loop throught the ground segments


for (var _i = 0; _i < ground_segment_count; _i++)
{
// Adjust the positions by the speed and parallaxing rate
ground_x_coords[_i] -= obj_game_manager.current_speed *
background_move_rate;
}

// Loops throught the group segements again not they have moved
for (var _i = 0; _i < ground_segment_count; _i++)
{
// Check if the segement is off screen to the left
if (ground_x_coords[_i] < -512)
{
// Check what the current ground state is
switch(current_ground_state)
{
// When entering
case INTERIOR_STATE.ENTER:
// Set ground sprite to enter
set_ground_sprites[_i] = ground_sprite[0];
// Change state to inside
current_ground_state =
INTERIOR_STATE.INSIDE;
break;
// When inside
case INTERIOR_STATE.INSIDE:
// Change sprite to inside sprite
set_ground_sprites[_i] = ground_sprite[1];
break;
// When exit
case INTERIOR_STATE.EXIT:
// Set ground to exit
set_ground_sprites[_i] = ground_sprite[2];
// Sets state to outside
current_ground_state =
INTERIOR_STATE.OUTSIDE;
// Also sets the pipe to exit since the ground
is changing
current_pipe_state =
INTERIOR_STATE.EXIT;
break;
// When outside
case INTERIOR_STATE.OUTSIDE:
// Sets the ground sprite to outside in the
pattern it follows (last 3 in array in order looping)
set_ground_sprites[_i] = ground_sprite[3 +
(_i % 3)];
// Sets a random flower create function
var _handle = choose(flower_set_1,
flower_set_2, flower_set_3, flower_set_4);
// Calls the chosen function for making
flowers at new location
_handle(ground_x_coords[_i] + 512 *
ground_segment_count, ground_y_coords);
break;
}

// Sets new x position for ground sprite


ground_x_coords[_i] += 512 * ground_segment_count;
}
}
}
● Draw
// Loops through the wall segements
for (var _i = 0; _i < wall_segment_count; _i++)
{
// Checks they has sprite set
if (set_wall_sprites[_i] != -1)
{
// Draws at position
draw_sprite(set_wall_sprites[_i], 0, wall_x_coords[_i],
wall_y_coords);
}
}

// Loops through the pipe segements


for (var _i = 0; _i < pipe_segment_count; _i++)
{
// Checks they has sprite set
if (set_pipe_sprites[_i] != -1)
{
// Draws at position
draw_sprite(set_pipe_sprites[_i], 0, pipe_x_coords[_i],
pipe_y_coords);
}
}

// Loops through the ground segements


for (var _i = 0; _i < ground_segment_count; _i++)
{
// Draws at position
draw_sprite(set_ground_sprites[_i], 0, ground_x_coords[_i],
ground_y_coords);
}

g. obj_mid_background
● Create
// Stores the midground sprites inside an array
sprite[0] = spr_midground_1;
sprite[1] = spr_midground_2;
sprite[2] = spr_midground_3;
sprite[3] = spr_midground_4;

// Prefeches them to prevent hanging later


sprite_prefetch_multi(sprite);

// Sets before, current and after sprite from array


before_sprite = sprite[0];
sprite_index = sprite[1];
after_sprite =sprite[2];

// Sets new random x position


x = random_range(0, sprite_width);
// Sets y position
y = 0;
// Sets parallaxing move rate
background_move_rate = 0.8;

● Step
// Checks the game is not paused
if (obj_game_manager.current_game_state !=
GAME_STATE.PAUSED)
{
// Moves position at the speed and rate
x -= obj_game_manager.current_speed * background_move_rate;

// Checks if the x position has gone off screen to the left


if (x < 0)
{
// Sets the sprites to the next one along
before_sprite = sprite_index;
sprite_index = after_sprite;

// Checks what the last after sprite used was and swaps the
sprite to the next one along following the pattern
switch(after_sprite)
{
case sprite[0]:
after_sprite = sprite[1];
break;
case sprite[1]:
after_sprite = sprite[2];
break;
case sprite[2]:
after_sprite = sprite[3];
break;
case sprite[3]:
after_sprite = sprite[0];
break;
}

// Moves the x coordinate along by its width


x += sprite_width;
}
}
● Draw
// Draws the before sprite at a minus offset
draw_sprite(before_sprite, 0, x - sprite_get_width(before_sprite), y);
// Draws the middle current sprite
draw_self();
// Draws the after sprite with offset added to x position
draw_sprite(after_sprite, 0, x + sprite_width, y);
3. Managers
a. obj_debugger
● Create
// Checks if debug menu variable exists
if (!variable_global_exists("active_debug_menu"))
{
// Sets to false
global.active_debug_menu = false;
}
else
{
// Deletes the debug window
dbg_view_delete(global.debug_window);
}

// Sets up a new debug window called game info and


stores it as a global variable
global.debug_window = dbg_view("Game Info",
global.active_debug_menu);

// Creates a section called game manager


dbg_section("Game Manager");
// Object variable for gamestate
game_state = "";
// Watch references for game state and distance travelled
dbg_watch(ref_create(self, "game_state"), "Game State");
dbg_watch(ref_create(obj_game_manager,
"current_distance"), "Distance Travelled");

// Creates a section called interior mode


dbg_section("Interior Mode");
// Object variable for interior state
interior_state = "";
// Watch references for interior state
dbg_watch(ref_create(self, "interior_state"), "Interior
State");
// Function for button that swaps the interior state
button_interior = function()
{
// Calls function from object
obj_interior_background.change_interior_state();

}
// Sets up button refernece
dbg_button("Change Interior", ref_create(self,
"button_interior"), 240, 30);

// Creates a section called player variables


dbg_section("Player Variables");
// Set up all the referneces for speed and distance
dbg_watch(ref_create(obj_game_manager,
"current_speed"), "Speed");
dbg_watch(ref_create(obj_game_manager,
"current_speed_percentage"), "Speed Percent");
dbg_slider(ref_create(obj_game_manager,
"target_speed_percentage"), 0.0, 1.0, "Speed Target");
dbg_text_input(ref_create(obj_game_manager,
"new_max_speed"), "Max Speed");
dbg_text_input(ref_create(obj_game_manager,
"current_distance"), "Current Distance");

// Calls show overlay


show_debug_overlay(global.active_debug_menu);

● Step
// Checks for shift and tab button combo
if (keyboard_check_direct(vk_shift) &&
keyboard_check_pressed(vk_tab))
{
// Toggles debug menu
global.active_debug_menu = !
global.active_debug_menu;
show_debug_log(global.active_debug_menu);
}

// Checks if the menu is active


if (global.active_debug_menu)
{
// Calls custom function to set string information
about the states to object variables
game_state = get_gamestate();
interior_state = get_interiorstate();
}

b. obj_game_manager
● Create
// Game states.
enum GAME_STATE
{
PLAYING,
DYING,
ENDED,
PAUSED,
TUTORIAL,
SIZE
}

// Sets new random seed


randomise();

// Variables for gameplay (gold tracking is what will speed


up the player later in the game)
current_level = 1;
current_level_gold = 0;
current_distance = 0;
current_gold = 0;

// Stops the music track that was previously playing


audio_stop_sound(global.music);

// Checks if the game has been played before


if (global.times_played == 0)
{
// Sets the game state to tutorial mode
current_game_state = GAME_STATE.TUTORIAL;
// Creates the tutorial object
instance_create_layer(room_width * 0.5, room_height *
0.5, "GUI", obj_tutorial);

// Play audio for tutorial


global.music = audio_play_sound(snd_ambience, 100,
true, 1.0);
}
else
{
// Sets the game to play normally
current_game_state = GAME_STATE.PLAYING;

// Spawns the inital GameMaker logo in coins to fill in


dead space
layer_sequence_create("Stage", 0, 0, seq_gm_layout);

// Checks if a highscore has been previously set


if (global.highscore != 0)
{
// Creates a flag object for the highscore at its
position it would be in
var _flag = instance_create_layer(640 +
real(global.highscore) * 60, 950, "StageBack",
obj_flag_marker);
// Sets the flag paramerters to know it has droppped
and the score it should have
_flag.has_dropped = true;
_flag.flag_distance = global.highscore;
}

// Plays the games main music


global.music =
audio_play_sound(snd_infinite_runner_music, 100, true,
0.5);
}

// Counts up the times played


global.times_played++;
/// Variables used to control the players speed
// Min speed is the slowest possible speed for players (ie
zero for stopped)
min_speed = 0.0;
// Max speed is the current maximum speed allowed
(Boosted speed)
max_speed = 24.0;
// Sets the new max speed as the current max speed (this
variable is what adjusts the games speed curves
new_max_speed = max_speed;
// True max speed the the absolute fastest a player can go
true_max_speed = 72.0;

// Current speed is what tracks current movement for the


backgrounds and level elements that need to move over
time
current_speed = 0.0;

// The speed percentages are used to gradually increase


and decrease the speed using smooth step interpolation
current_speed_percentage = 0.0;
target_speed_percentage = 0.5;

// The rate speed will go up or down so the player will stop


or slow down quicker than speeding up
speed_up_rate = 0.2;
speed_down_rate = 0.5;

// Initial cooldown for the background changing


background_cooldown = 100;

// Flag used to check if the environments have finished


loading to before starting the game
has_prefetched = false;

// Creates game objects for room environment


instance_create_layer(0, 0, "Farground",
obj_far_background);
instance_create_layer(0, 0, "Midground",
obj_interior_background);
instance_create_layer(0, 0, "Midground",
obj_mid_background);
instance_create_layer(0, 0, "Foreground",
obj_front_floor);
instance_create_layer(0, 0, "Foreground",
obj_front_ceiling);

// Creates player object


instance_create_layer(0, 0, "Stage", obj_player);

// Function used to update the speed with delta time passed


though as that is the time passed this frame meaning more
accurate movement
update_speed = function(_delta_time)
{
// Checks if a player has collected 50 gold since the last
time they leveled up
if (current_level_gold >= 50)
{
// Removed the gold from their current count
current_level_gold -= 50;
// Increases the level
current_level++;
// Sets the max speed to be 5% faster
new_max_speed = max_speed * 1.05;
}

// Limits the max speed to the true max speed


if (new_max_speed > true_max_speed)
{
// Sets max to true max
new_max_speed = true_max_speed;
}

// Checks if new max speed has changed.


if (new_max_speed != max_speed)
{
// Adjusts the percentage.
current_speed_percentage *= max_speed /
new_max_speed;
// Sets max speed to new value.
max_speed = new_max_speed;
}

// Check if speed is less than target.


if (current_speed_percentage <
target_speed_percentage)
{
// Speed up at rate.
current_speed_percentage += speed_up_rate *
_delta_time;

// Limit speed to target.


current_speed_percentage =
min(current_speed_percentage, target_speed_percentage);

// Interpolate speed using smoothstep curve.


current_speed = smoothstep(min_speed, max_speed,
current_speed_percentage);
}
// Check if speed is greater than target.
else if (current_speed_percentage >
target_speed_percentage)
{
// Slow down at rate.
current_speed_percentage -= speed_down_rate *
_delta_time;

// Limit speed to target.


current_speed_percentage =
max(current_speed_percentage, target_speed_percentage);

// Interpolate speed using smoothstep curve.


current_speed = smoothstep(min_speed, max_speed,
current_speed_percentage);
}

// Checks if game is not running in tutorial mode


if (current_game_state != GAME_STATE.TUTORIAL)
{
// Add current speed to distance traveled.
current_distance += current_speed * _delta_time;
}
}
● Step
// Set delta time for movements that are time based.
var _delta_time = delta_time * 0.000001;

// Checks if prefetch flag has not been met


if (!has_prefetched)
{
// Sets delta time back to zero as game is still loading certain objects
_delta_time = 0;
}

// Change logic depending on the current game state.


switch (current_game_state)
{
// Logic for while the game is playing.
case GAME_STATE.PLAYING:
// Calls the update speed function passing though the delta time parameter
update_speed(_delta_time);

// Decreases the background cooldown timer by the current speed and time
passed
background_cooldown -= current_speed * _delta_time;

// Checks if the background cooldown has finished


if (background_cooldown <= 0)
{
// Calls the change state function for the backgrounds
obj_interior_background.change_interior_state();
// Resets the cooldown to a random value increasing the higher cap by
the current level since faster speeds may mean backgrounds apear for less time
background_cooldown = random_range(100, 100 + 50 * current_level);
}
break;

// Logic for when the player is dying


case GAME_STATE.DYING:
// Calls the update speed function
update_speed(_delta_time);

// Checks if the speed is currently zero and the player is now invisible
if (current_speed == 0 && obj_player.image_alpha == 0)
{
// Sets the games current state to end
current_game_state = GAME_STATE.ENDED;

// Checks if the current distance has passed the previously set high score
if (current_distance > global.highscore)
{
// Makes a new flag over the players position that will drop into the
level and has its distance set
var _flag = instance_create_layer(obj_player.x, -200, "Stage",
obj_flag_marker);
_flag.has_dropped = false;
_flag.has_passed = true;
_flag.flag_distance = current_distance;

// Sets the global highscore variable to the current distance


global.highscore = current_distance;

// Loads buffer for highscore


highscore_buffer = buffer_load("ENDLESS_RUNNER_HS.sav");

// Checks if buffer exists


if(!buffer_exists(highscore_buffer))
{
// Creates highscore buffer
highscore_buffer = buffer_create(16384, buffer_fixed, 2);
}

// Goes to the start of the buffer


buffer_seek(highscore_buffer, buffer_seek_start, 0);

// Writes highscore value to the buffer


buffer_write(highscore_buffer, buffer_u64, global.highscore);

// Saves the new highscore buffer


buffer_save(highscore_buffer, "ENDLESS_RUNNER_HS.sav");
}
else
{
// Stops the current music
audio_stop_sound(global.music);

// Plays game over sound effect and changes the global music to
ambience
audio_play_sound(snd_game_over_popup, 100, false, 1.0);
global.music = audio_play_sound(snd_ambience, 100, true, 1.0);

// Plays the game over sequence that creates the gameover menu
var _gameover_seq = layer_sequence_create("GUI", 0, 0,
seq_gameover);

// Create the replay button


var _replay_button = instance_create_layer(room_width / 2,
room_height / 2 + 100, "GUI", obj_button_replay);
}
}
break;
}

c. obj_particle_manager
● Create
// Empty variable for setting the particle system to
particle_sys = -1;

// Variable used for if follows owner


owner = noone;

// Variables used for if effected by world speed


move_rate = 1.0;
move_rate_target = 1.0;
drag_rate = 0.0;

// Variable used offsets


angle_offset = 0;
x_offset = 0;
y_offset = 0;
// Function used for setting particle systems angle
set_angle = function(_new_angle)
{
// Sets angle offset
angle_offset = _new_angle;
// Updates particle systems angle
part_system_angle(particle_sys, angle_offset);
}

// Function used for setting particle systems offset position


set_offset = function(_x_offset, _y_offset)
{
// Offset variables set to new temp variables passed
in
x_offset = _x_offset;
y_offset = _y_offset;

// Positions adjusted by offsets


x += x_offset;
y += y_offset;

// Particle position repositioned


part_system_position(particle_sys, x, y);
}

// Function used for setting particle system


set_particle = function(_new_ps, _layer)
{
// Creates smoke particle system
particle_sys = part_system_create_layer(_layer,
false, _new_ps);
// Updates particle system position
part_system_position(particle_sys, x, y);
}

● Destroy
// Destroys particle system
part_system_destroy(particle_sys);

● Step
// Checks if the owner currently exists
if (owner == noone)
{
// Checks if the move rate is not equal to the current
move rate (Drag)
if (move_rate != move_rate_target)
{
// Adjusts the move rate by lerping to the
target at the set drag rate
move_rate = lerp(move_rate,
move_rate_target, drag_rate);
}

// Checks the game is not currently paused


if (obj_game_manager.current_game_state !=
GAME_STATE.PAUSED)
{
// Adjusts the x position by the current speed
and move rate
x -= obj_game_manager.current_speed *
move_rate;
}
}
else
{
// Sets the x and y positions by the offsets and the
owners position
x = owner.x + x_offset;
y = owner.y + y_offset;
}

// Updates the particle system to the objects position


part_system_position(particle_sys, x, y);

// Checks if the game state is paused


if (obj_game_manager.current_game_state ==
GAME_STATE.PAUSED)
{
// Stops updating the particle systems
part_system_automatic_update(particle_sys, false)
}
else
{
// Resumes updating the particle systems
part_system_automatic_update(particle_sys, true)
}

// Checks if the particle system has finished


if (part_particles_count(particle_sys) == 0)
{
// Destroys the object
instance_destroy();
}

d. obj_sequence_manager
● Create
// Set sequence used
set_sequence = -1;

// Variable used for if follows owner


owner = noone;

// Sets up inital after sequence functionality


has_death = false;
stored_function = function(){}

// Function called when death set


set_death = function(_new_function)
{
// Sets death flag to true
has_death = true;
// Stores the stored function as a new one
stored_function = _new_function;
}

// Functione called when creating new sequences


create_seq = function(_new_seq, _new_layer)
{
// Sets the variable to the set sequence on a
specified layer
set_sequence = layer_sequence_create(_new_layer,
x, y, _new_seq);
}
● Step
// Checks if the object has an owner set
if (owner != noone)
{
// Adjusts the coordinates to follow its owner
x = owner.x;
y = owner.y;
}

// Checks if a sequence has been set


if (set_sequence != -1)
{
// Checks if the sequnece has finished
if (layer_sequence_is_finished(set_sequence))
{
// Destroys the sequence
layer_sequence_destroy(set_sequence);

// Checks if the sequence has a death call


if (has_death)
{
// Runs the death call
stored_function();
}

// Destroys this sequences manager object


instance_destroy();
}
else
{
// Updates the sequence position to the
objects
layer_sequence_x(set_sequence, x);
layer_sequence_y(set_sequence, y);
}
}

// Checks if the game is paused


if (obj_game_manager.current_game_state ==
GAME_STATE.PAUSED)
{
// Pauses the sequence
layer_sequence_pause(set_sequence);
}
else
{
// Checks if the sequence is paused
if (layer_sequence_is_paused(set_sequence))
{
// Resumes the sequenece
layer_sequence_play(set_sequence);
}
}

e. obj_spawn_manager
● Create
_cooldown = 10 + 1.8;
break;

case 2: // Normal enemy


instance_create_layer(_spawn_x +
204, 800, "Stage", obj_enemy);
spawn_cooldown = 0;
break;
}

// Sets the enemy cooldown to a value between 200


and 75 calulated on the current level (More enemies the
more gold collected)
enemy_cooldown = 250 - (50 *
clamp((obj_game_manager.current_level / 2), 1, 3.5));
}

// Spawns random powerup


spawn_powerup = function()
{
// Sets the x and y coordinates for powerup drop
// Y values are preset and chosen at random
var _spawn_x = room_width * 2;
var _new_y = choose(140, 315, 490, 665, 840);

// Creates instance choosing a random type


instance_create_layer(_spawn_x + 92, _new_y,
"Stage", choose(obj_pickup_boost, obj_pickup_shield));

// Resets spawn cooldown accounting for offset


spawn_cooldown = 10 + 1.7;

// Resets powerup cooldown adjusting for player


level (less powerups late game)
powerup_cooldown = 100 *
min(obj_game_manager.current_level, 5);
}

// Function for spawning a preset reward


spawn_reward = function(_reward_type)
{
// Sets up new spawn coordinates with preset x
value and random y initially
var _spawn_x = room_width * 2;
var _new_x = _spawn_x + 34;
var _new_y = random_range(100, 896);

// Switch statement for reward types


switch(_reward_type)
{
case 0: // Single Coin

// New y value (ground level)


_new_y = 896;

// Creates instance at coordinates


instance_create_layer(_new_x,
_new_y, "Stage", obj_pickup_coin);
// Sets the spawn cooldown for offsets
spawn_cooldown = 10 + 1;

break;
case 1: // 3x3 Set Coins

// Sets y position at random from


preset coordinates
_new_y = choose(100, 438, 776);

// Loops horizontally for 3


for (var _i = 0; _i < 3; _i++)
{
// Loops vertically for 3
for (var _j = 0; _j < 3; _j++)
{
// Creates coin object at
new positions

instance_create_layer(_new_x + _i * 70, _new_y +


_j * 80, "Stage", obj_pickup_coin);
}
}

// Sets the cooldown for spawn gap


with added value for horizontal length of segment
spawn_cooldown = 10 + 3.2;

break;

case 2: // 9x2 Set Coins

// Sets new y position at random from


preset values
_new_y = choose(100, 340, 580, 820)

// Loops horizontally for 9


for (var _i = 0; _i < 9; _i++)
{
// Loops vertically for 2
for (var _j = 0; _j < 2; _j++)
{
// Creates new object at
determined position
instance_create_layer(_new_x + _i * 70, _new_y +
_j * 80, "Stage", obj_pickup_coin);
}
}

// Sets the cooldown for spawn gap


with added value for horizontal length of segment
spawn_cooldown = 10 + 9.9;

break;

case 3: // 2x9 Set Coins

// Sets new y position


_new_y = 180;

// Loops horizontally for 2


for (var _i = 0; _i < 2; _i++)
{
// Loops vertically for 9
for (var _j = 0; _j < 9; _j++)
{
// Creates new coin
object at set coordinates

instance_create_layer(_new_x + _i * 70, _new_y +


_j * 80, "Stage", obj_pickup_coin);
}
}

// Sets the cooldown for spawn gap


with added value for horizontal length of segment
spawn_cooldown = 10 + 2.1;

break;

case 4: // 9x1 Wave Coins up curve

// Sets y position at random from


preset positions
_new_y = choose(300, 550, 800);
// Loops horizontally for 9
for (var _i = 0; _i < 9; _i++)
{
// Calculates position spacing
using sin curve and creates instance of object
instance_create_layer(_new_x
+ _i * 70, _new_y - sin(pi / (8 / _i)) * 160, "Stage",
obj_pickup_coin);
}
● Step
// Checks game is in play mode
if (obj_game_manager.current_game_state ==
GAME_STATE.PLAYING)
{
// Set delta time for movements that are time based.
var _delta_time = delta_time * 0.000001;

// Calculate the change in distance


var _delta_distance =
obj_game_manager.current_speed * _delta_time;

// Apply values to cooldowns


powerup_cooldown -= _delta_distance;
spawn_cooldown -= _delta_distance;
enemy_cooldown -= _delta_distance;

// Check is spawn cooldown is finished


if (spawn_cooldown <= 0)
{
// Check if enemy can spawn (prioirty)
if (enemy_cooldown <= 0)
{
// Calls the spawn enemy function
spawn_enemy();
}
// Checks if powerup can be called
else if (powerup_cooldown <= 0)
{
// Calls the spawn powerup option
spawn_powerup();
}
else
{
// Spawns a random reward with the
chance changing depending on how many times it is uses
in this function

spawn_reward(choose(0,1,1,1,1,2,2,2,3,3,4,4,5,4,6,7));
}
}
}
f. obj_splash_manager
● Create
// Checks if the platform type is mobile
if (os_type == os_android || os_type == os_ios)
{
// Sets global touch to true
global.is_touch = true;
}
else
{
// Sets global touch to false
global.is_touch = false;
}

// Makes the project fullscreen


window_set_fullscreen(true);

// Play splash sequence for menu UI


var _splash_seq = layer_sequence_create("Instances", 0, 0,
seq_splash);

// Stops all previous running audio


audio_stop_all();

// Play audio for main menu


global.music = audio_play_sound(snd_menu_music, 100,
true, 1.0);

// Check for highscore variable


if (!variable_global_exists("highscore"))
{
// Create empty variable for highscore
global.highscore = 0;

// Loads buffer for highscore


highscore_buffer =
buffer_load("ENDLESS_RUNNER_HS.sav");

// Checks if buffer exists


if(buffer_exists(highscore_buffer))
{
// Goes to the start of the buffer
buffer_seek(highscore_buffer,
buffer_seek_start, 0);

// Sets the highscore to value from the buffer


global.highscore =
buffer_read(highscore_buffer, buffer_u64);
}
else
{
// Creates highscore buffer
highscore_buffer = buffer_create(16384,
buffer_fixed, 2);

// Goes to the start of the buffer


buffer_seek(highscore_buffer,
buffer_seek_start, 0);

// Writes highscore value to the buffer


buffer_write(highscore_buffer, buffer_u64,
global.highscore);

// Saves the new empty highscore buffer


buffer_save(highscore_buffer,
"ENDLESS_RUNNER_HS.sav");
}
}

// Check if game has been played this session


if (!variable_global_exists("times_played"))
{
// Creates times played variable and sets to zero
global.times_played = 0;
}
4. Obstacles

a. obj_alert
● Create
// Start object invisible
image_alpha = 0;
// Set target alpha as visible
target_alpha = 1.0;

// Used to set owner object to


owner = noone;

// Distance used to show and hide alert


buffer = room_width * 0.25;

// Rates for fading in and out


fade_in_rate = 0.1;
fade_out_rate = 0.15;

// Checks if the alert sound already exists


if (!variable_global_exists("alert_sound"))
{
// Plays the alert sound
global.alert_sound = audio_play_sound(snd_incoming_alert, 100,
true, image_alpha);
}
else
{
// Check if the audio is playing
if (audio_is_playing(global.alert_sound))
{
// Creates a variable to store the gain level
var _max_volume = image_alpha;
// Checks through all the alerts
with (obj_alert)
{
// Checks if the alert is more visible
if (image_alpha >= _max_volume)
{
// Sets the gain to image alpha
_max_volume = image_alpha;
}
}

// Sets the sound gain


audio_sound_gain(global.alert_sound, _max_volume, 0);
}
else
{
// Plays the alert sound
global.alert_sound =
audio_play_sound(snd_incoming_alert, 100, true, image_alpha);
}
}
● Destroy
// Creates variables to check alert status
var _self = self;
var _has_alert = false;

// Checks through all the alerts


with (obj_alert)
{
// Checks if the alert is the same one
if (self != _self)
{
// Sets the has alert flag to true
_has_alert = true;
}
}

// Checks if no other alerts exist


if (!_has_alert)
{
// Stops the sound
audio_stop_sound(global.alert_sound);
}

● Step
// Checks owner exists
if (owner != noone)
{
// Checks owener is offscreen with added buffer distance
if (owner.bbox_left > room_width + buffer)
{
// Will show alert
target_alpha = 1;
}
// Checks if owner is closer than the buffer
else if (owner.bbox_left > room_width)
{
// Scales down the target alpha between 0 and 1
target_alpha = clamp(buffer / (room_width -
owner.bbox_left), 0, 1);
}
else
{
// Sets the target alpha to 0 since owner on screen and
should be invisible
target_alpha = 0;
}

// Checks if the target is higher than the current alpha value


if (target_alpha > image_alpha)
{
// Fades in at in rate
image_alpha = lerp(image_alpha, target_alpha,
fade_in_rate);
}
else
{
// Fades out at out rate
image_alpha = lerp(image_alpha, target_alpha,
fade_out_rate);
}

// Checks if game is playing


if (obj_game_manager.current_game_state ==
GAME_STATE.PLAYING)
{
// Creates a variable to store the gain level
var _max_volume = image_alpha;

// Checks through all the alerts


with (obj_alert)
{
// Checks if the alert is more visible
if (image_alpha >= _max_volume)
{
// Sets the gain to image alpha
_max_volume = image_alpha;
}
}

// Sets the sound gain


audio_sound_gain(global.alert_sound, _max_volume, 0);
}
else
{
// Fades out the alert sound
audio_sound_gain(global.alert_sound, 0, 3000);
}

// Checks if both the target and current alpha is set to zero


if (target_alpha == 0 && image_alpha == 0)
{
// Destroys the alert
instance_destroy();
}
}
else
{
// Destroys the alert since no owner exists
instance_destroy();
}
// Checks if game is paused
if (obj_game_manager.current_game_state ==
GAME_STATE.PAUSED)
{
// Stops animation
image_speed = 0;
}
else
{
// Plays animation
image_speed = 1;
}

● Animation End
// Plays the final animation after the inital one
sprite_index = spr_alert_final;

b. obj_beam
● Create
// Check for knowing if object has hit the player
has_hit = false;

// Creates an alert object at its high point with itself as owner


var _alert_high = instance_create_layer(room_width - 100, y - 100,
"GUI", obj_alert);
_alert_high.owner = self;

// Creates an alert object at its low point with itself as owner


var _alert_low = instance_create_layer(room_width - 100, y + 100,
"GUI", obj_alert);
_alert_low.owner = self;

// Beam sound effect


beam_sound = audio_play_sound(snd_force_field, 100, true, 0.0);
● Destroy
// Stops the beams sound
audio_stop_sound(beam_sound);

● Step
// Checks the game is not paused
if (obj_game_manager.current_game_state !=
GAME_STATE.PAUSED)
{
// Moves the beam at the games current speed
x -= obj_game_manager.current_speed * 1.0;

// Creates a particle emitter manager object at top position and


sets the beam effect for it
var _beam_top_particle = instance_create_layer(x, y, "Stage",
obj_particle_manager);
_beam_top_particle.owner = self;
_beam_top_particle.set_particle(ps_enemy_laser,
"StageFrontEffects");
_beam_top_particle.set_angle(180);
_beam_top_particle.set_offset(0, -128);

// Creates a particle emitter manager object at low position and


sets the beam effect for it
var _beam_bottom_particle = instance_create_layer(x, y, "Stage",
obj_particle_manager);
_beam_bottom_particle.owner = self;
_beam_bottom_particle.set_particle(ps_enemy_laser,
"StageFrontEffects");
_beam_bottom_particle.set_angle(0);
_beam_bottom_particle.set_offset(0, +128);

// Checks if the beam has gone offscreen to the left


if (x < 0 - 59)
{
// Destroys the beam
instance_destroy();
}
// Plays the animation normally
image_speed = 1;
}
else
{
// Pauses the animation
image_speed = 0;
}

// Checks the game is playing


if (obj_game_manager.current_game_state ==
GAME_STATE.PLAYING)
{
// Checks if the beam is to the right of the player
if (x > obj_player.x)
{
// Scales the gain by the distance between player and beam
to the room width
audio_sound_gain(beam_sound, 1.0 - clamp(abs(x -
obj_player.x) / room_width, 0.0, 1.0), 0.0);
}
else
{
// Scales the gain by the distance between player and beam
to a fraction of the room width
audio_sound_gain(beam_sound, 1.0 - clamp(abs(x -
obj_player.x) / (room_width * 0.33), 0.0, 1.0), 0.0);
}
}
else
{
// Fades out the beam sounds
audio_sound_gain(beam_sound, 0.0, 3000);
}

● Draw
// Draws the main beam body
draw_self();
// Draws the top beam head sprite flipped
draw_sprite_ext(spr_beam_head, 0, x, y - 128 - 22, 1, 1, 180,
image_blend, image_alpha);
// Draws the bottom beam head sprite normally
draw_sprite(spr_beam_head, 0, x, y + 128 + 22);

● →←obj_player
// Checks if beam has already hit the player
if (!has_hit)
{
// Plays impact sound
audio_play_sound(snd_force_field_impact, 100, false, 1.0);

// Calls the players kill function


other.kill_player();
// Sets the hit flag to true
has_hit = true;
}

c. obj_enemy
● Create
// Flag for knowing if hit and damaged the player
has_hit = false;
// Walking speed variable
walking_speed = 3;

// Variable for footstep state


has_stepped = false;

// Creates a shadow object to follow the enemy and sets up the sprite and
offset
var _shadow = instance_create_layer(x, y, "StageShadows",
obj_shadow);
_shadow.sprite_index = spr_enemy_shadow;
_shadow.owner = self;
_shadow.set_y_offset(150);
// Creates an alert object to the position with owner being set
var _alert = instance_create_layer(room_width - 100, y, "GUI",
obj_alert);
_alert.owner = self;

● Step
// Checks if the game is not currently paused
if (obj_game_manager.current_game_state !=
GAME_STATE.PAUSED)
{
// Moves x position by current speed
x -= obj_game_manager.current_speed * 1.0;

// Moves the x postiion again by the walking speed


x -= walking_speed;

// Checks if the enemy has gone off screen to the left


if (x < 0 - 204)
{
// Destroys the enemy
instance_destroy();
}

// Sets the animation speed to play


image_speed = 1;

// Checks the for step frame and step hasnt played for the step
if (!has_stepped && (round(image_index) == 4 ||
round(image_index) == 13))
{
// Chooses a random footstep
var _footstep = choose(snd_dino_robot_footstep_1,
snd_dino_robot_footstep_2, snd_dino_robot_footstep_3,
snd_dino_robot_footstep_4, snd_dino_robot_footstep_5,
snd_dino_robot_footstep_6);

// Sets default gain


var _gain = 1.0;

// Checks if the dino is to the right of the player


if (x > obj_player.x)
{
// Scales the gain by the distance between player
and enemy to the room width
_gain = 1.0 - clamp(abs(x - obj_player.x) /
room_width, 0.0, 1.0);
}
else
{
// Scales the gain by the distance between player
and enemy to a fraction of the room width
_gain = 1.0 - clamp(abs(x - obj_player.x) /
(room_width * 0.33), 0.0, 1.0);
}

// Plays the footstep sound


audio_play_sound(_footstep, 100, false, _gain);

// Sets step state to true


has_stepped = true;
}
// Checks is not currently on a step frame
else if (!(round(image_index) == 4 || round(image_index) == 13))
{
// Sets step state to false
has_stepped = false;
}
}
else
{
// Pauses the animation speed
image_speed = 0;
}

● →← obj_player
if (!has_hit)
{
// Plays impact sound
audio_play_sound(snd_dino_robot_impact, 100, false, 1.0);

// Calls kill player function


other.kill_player();
// Sets hit flag to true
has_hit = true;
}
5. Player

a. obj_flag_maker
● Create
// Sets the variables for flag placement and behaviours
has_dropped = false;
has_passed = false;
has_cooldown_adjusted = false;

// Inital fall speed variable


fall_speed = 0;

// Used when warping effect is applied to flag on bounce


is_warping = false;
// Sets the animation curve
warp_curve = animcurve_get_channel(ac_flag_warp, "warp");
// Variable used to track curve
warp_curve_percent = 0;

// Used to store requests within later


handle_request = -1;

// Variable used to store and display the flag distance


flag_distance = 0;

// Text alpha value


text_alpha = 1.0;

// Function used to create firework


create_firework = function()
{
// Checks flag still exisits
if (instance_exists(self))
{
// Creates firework object at position setting its delay, fuse
timer and speed
var _firework= instance_create_layer(x, y - 100, "Stage",
obj_firework);
_firework.delay = 0.02;
_firework.death = 0.55;
_firework.fire_speed = 15;
}
else
{
// Stops the repeating handle call since no longer exists
call_cancel(handle_request);
}
}

● Step
// Checks the game is not currently paused
if (obj_game_manager.current_game_state !=
GAME_STATE.PAUSED)
{
// Moves the x position by the current speed value
x -= obj_game_manager.current_speed * 1.0;

// Checks if the flag needs to drop


if (!has_dropped)
{
// Checks if the flag is still in air
if (y < 950)
{
// Adds fall speed to flag
fall_speed += 120 * delta_time * 0.000001;

// Adjusts the y position


y += fall_speed;

// Checks the y position if is now grounded


if (y > 950)
{
// Hard sets ground position
y = 950;
// Sets warping state to true
is_warping = true;

// Calls firework function since landed


create_firework();

// Sets up handle request to keep calling


fireworks at random intervals repeating until stopped
handle_request =
call_later(random_range(90, 120), time_source_units_frames,
create_firework, true);

// Sets up smoke particle effect for landing


smoke
var _smoke_particle =
instance_create_layer(x, y, "Stage", obj_particle_manager);
_smoke_particle.owner = self;
_smoke_particle.set_particle(ps_flag_smoke,
"StageShadowsEffects");

// Sets has dropped flag to true


has_dropped = true;
}
}
}

// Checks if flag is currently warping


if (is_warping)
{
// Sets temp warp rate
var _warp_rate = 1.2;
// Adjusts the curve percent by the time passed and rate
warp_curve_percent += delta_time * 0.000001 *
_warp_rate;

// Checks if the curve has finished


if (warp_curve_percent > 1.0)
{
// Sets curve value to full (100%)
warp_curve_percent = 1.0;
// Stops warping state
is_warping = false;
// Resets text alpha for flag
text_alpha = 0.0;

// Creates function called gameover for triggering


gameover
var _new_gameover = function()
{
// Stops the music
audio_stop_sound(global.music);

// Plays game over sound effect and changes


the global music to ambience
audio_play_sound(snd_game_over_popup,
100, false, 1.0);
global.music =
audio_play_sound(snd_ambience, 100, true, 1.0);

// Play game over sequence for menu UI


var _gameover_seq =
layer_sequence_create("GUI", 0, 0, seq_gameover);
}

// Creates a game over handle for calling the game


over function after 60 frames
var _go_handle = call_later(60,
time_source_units_frames, _new_gameover, false);
}

// Calculates the adjusted value from the curve


var _adjust_val =
animcurve_channel_evaluate(warp_curve, warp_curve_percent);
// Sets the y scale to follow this curve
image_yscale = 1.0 + _adjust_val;
}

// Checks if the flag has been passed and a new highscore should
occur
if (!has_passed && obj_game_manager.current_distance >
global.highscore)
{
// Creates particle effect manager and sets up a confetti
effect
var _confetti_particle = instance_create_layer(x - 50, y -
20, "Stage", obj_particle_manager);
_confetti_particle.owner = self;
_confetti_particle.set_particle(ps_confetti,
"StageShadowsEffects");
_confetti_particle.set_offset(-50, -240);

// Calls the firework function


create_firework();

// Sets has passed flag to true


has_passed = true;
}

// Checks if cooldown has been adjusted to stop coins overlaying


the flag to be passed
if (!has_cooldown_adjusted)
{
// Calculates the x position when next segment
if (x <= room_width * 2.33)
{
// Resets the spawn cooldown with space for the
flags placement
obj_spawn_manager.spawn_cooldown =
(room_width * 0.66) / 60;

// Checks all the coins within the room


with (obj_pickup_coin)
{
// Checks if coin is after the spawn point (or
just before the flag)
if (x >= room_width * 2)
{
// Destroys the coin
instance_destroy();
}
}
// Sets cooldown adjusted state to true
has_cooldown_adjusted = true;
}
}

// Plays the animation for the flag


image_speed = 1;
}
else
{
// Pauses the animation for the flag
image_speed = 0;
}

● Draw
draw_self();

draw_set_font(fnt_rowdies_22);

var _text_colour = make_color_rgb(142, 214, 67);

draw_set_color(_text_colour);

draw_set_halign(fa_center);
draw_set_valign(fa_middle);

if (!is_warping && has_dropped)


{
text_alpha = lerp(text_alpha, 1.0, 0.01);
draw_set_alpha(text_alpha);

var _string = parse_value(flag_distance) + "M";


var _text_scale = clamp(80 / string_width(_string), 0.5, 1.0);

draw_text_ext_transformed(x + 50, y - 195, _string, 10, 300,


_text_scale, _text_scale, text_alpha);
}

draw_set_color(c_white);
draw_set_alpha(1.0);
draw_set_halign(fa_left);
draw_set_valign(fa_top);

b. obj_player
● Create
// Sets the inital player position
x = 640;
y = 840;

// Sets the start y value to y


ystart = y;

// Enum states used for the player


enum PLAYER_STATE
{
IDLE,
RUN,
FLY_SMALL,
FLY_BIG,
FLY_RELEASED,
BOOST,
DEATH
}

// Sets the players current state


current_player_state = PLAYER_STATE.RUN;

// Variables used for the players movement


jump_strength = 110;
jump_threshold = 10;
gravity_strength = 0.8;
y_velo = 0.0;

// Boosting variables
is_boosting = false;
boost_cooldown = 0;
// Jump state
has_jumped = false;

// Footstep state
has_stepped = false;

// Plays jet sound with no gain


jet_sound = audio_play_sound(snd_jet_turbine, 100, false, 0.0);

// Plays air sound with no gain


air_sound = audio_play_sound(snd_jet_air, 100, true, 0.0);

// Creates a shadow to follow the player with the owner and offset setup
to the player
var _shadow = instance_create_layer(x, y, "StageShadows",
obj_shadow);
_shadow.owner = self;
_shadow.set_y_offset(100);

// Function used when the player is hit by an enemy


kill_player = function()
{
// Checks the game is playing
if (obj_game_manager.current_game_state ==
GAME_STATE.PLAYING)
{
// Checks if a shield object exists within the room
if (instance_exists(obj_shield))
{
//// Plays shield break sound
//var _shield_break =
audio_play_sound(snd_force_field_impact, 100, false, 1.0);

// With that (and all) shields


with (obj_shield)
{
// Set their life to 0 so they die
life = 0;
exit;
}
}
else
{
// Plays death sound
audio_play_sound(snd_chicken_death, 100, false,
1.0);

// Sets the player to die


obj_game_manager.current_game_state =
GAME_STATE.DYING;

// Lowers the music


audio_sound_gain(global.music, 0.1, 3000);

// Creates a boom particle effect by using a manager


object
var _boom_particle = instance_create_layer(x, y,
"Stage", obj_particle_manager);
_boom_particle.owner = self;
_boom_particle.set_particle(ps_defeat,
"StageEffects");

// Sets the player to a temp variable


var _player = self;

// Checks with all shadows in the room


with (obj_shadow)
{
// If the player is the owner
if (owner == _player)
{
// Call fade out function
fade_out(2.2);
}
}
}
}
}

● Destroy
// Stops the sounds
audio_stop_sound(jet_sound);
audio_stop_sound(air_sound);

● Step
// Checks the game is not currently paused
if (obj_game_manager.current_game_state !=
GAME_STATE.PAUSED)
{
// Set delta time for movements that are time based.
var _delta_time = delta_time * 0.000001;

// Change logic depending on the current game state.


switch (obj_game_manager.current_game_state)
{
// Logic for while the game is playing.
case GAME_STATE.PLAYING:

// Sets up temp variable for gamepad jump state


var _gamepad_jump = false;

// Checks when gamepad with id 0 (player 1) is


connected
if (gamepad_is_connected(0))
{
// Checks for jump button press
if (gamepad_button_check(0, gp_face1))
{
// Sets variable to true
_gamepad_jump = true;
}
}

// Checks for jump inputs


if (keyboard_check_direct(vk_space) ||
mouse_check_button(mb_left) || _gamepad_jump)
{
// Sets has jumped state to true
has_jumped = true;
// Addes jump values to y velocity
y_velo += jump_strength * _delta_time;
// Checks the player is curretly running
if (current_player_state ==
PLAYER_STATE.RUN)
{
// Sets the player to idle state
current_player_state =
PLAYER_STATE.IDLE;
// Changes the sprite and image index
sprite_index = spr_character_idle;
image_index = 0;

// Creates and sets up particle object


for initial jump flame
var _new_flame_particle =
instance_create_layer(x, y, "Stage", obj_particle_manager);

_new_flame_particle.set_particle(ps_inital_jump_flame,
"StageBackEffects");
_new_flame_particle.set_offset(0,
100);
_new_flame_particle.move_rate = 0;
_new_flame_particle.drag_rate =
0.05;

// Creates and sets up particle effect


for initial jump dust cloud effect
var _dust_particle =
instance_create_layer(x, y + 80, "Stage", obj_particle_manager);

_dust_particle.set_particle(ps_dust_small, "StageFrontEffects");
_dust_particle.move_rate = 0;
_dust_particle.drag_rate = 0.05;
}
// Checks if the y velocity is greater than the
jump threshold (Stronger jump effect)
else if (y_velo > jump_threshold)
{
// Sets the state to fly big
current_player_state =
PLAYER_STATE.FLY_BIG;
// Resets the player sprite
sprite_index = spr_character_idle;
}
else
{
// Sets the state to fly small
current_player_state =
PLAYER_STATE.FLY_SMALL;
// Resets the player sprite
sprite_index = spr_character_idle;
}
}
// Checks if the player is in air
else if (y < ystart)
{
// Sets the state to released (falling)
current_player_state =
PLAYER_STATE.FLY_RELEASED;
// Resets the player sprite
sprite_index = spr_character_idle;
}

// Checks if the player is boosting


if (is_boosting)
{
// Sets the games target speed to 100%
obj_game_manager.target_speed_percentage
= 1.0;
// Reduces booster cooldown
boost_cooldown -= _delta_time;

// Checks if cooldown has expired


if (boost_cooldown <= 0)
{
// Creates particle effect object for
booster off effect
var _new_aura_particle =
instance_create_layer(x, y, "Stage", obj_particle_manager);
_new_aura_particle.owner = self;

_new_aura_particle.set_particle(ps_powerup_out,
"StageFrontEffects");
// Sets boosting state to false
is_boosting = false;
// Resets the cooldown
boost_cooldown = 0;
}
}
else
{
// Sets the target spped to 50% (Normal
speed)
obj_game_manager.target_speed_percentage
= 0.5;
}

break;

case GAME_STATE.DYING:

// Checks if the player hasnt already died


if (current_player_state !=
PLAYER_STATE.DEATH)
{
// Sets the player to dead
current_player_state =
PLAYER_STATE.DEATH;
// Changes the sprite
sprite_index = spr_character_death;
// Resets the image index
image_index = 0;
// Sets the target speed to 0 and stop
obj_game_manager.target_speed_percentage
= 0.0;
}

break;

case GAME_STATE.ENDED:
// Do nothing
break;
case GAME_STATE.PAUSED:
// Do nothing
break;

case GAME_STATE.TUTORIAL:

// Checks if player can jump in tutorial yet


if (!obj_tutorial.can_jump)
{
// Checks if the player is falling
if (y < ystart)
{
// Sets player to relased state
current_player_state =
PLAYER_STATE.FLY_RELEASED;
// Resets the player sprite
sprite_index = spr_character_idle;
}

break;
}

// Sets up temp jump check for tutorial gamepad


controls
var _gamepad_jump_tutorial = false;

// Check gamepad 0 (player 1) is connected


if (gamepad_is_connected(0))
{
// Check for jump button press
if (gamepad_button_check(0, gp_face1))
{
// Set state for temp variable to true
_gamepad_jump_tutorial = true;
}
}

// Check if keyboard, mouse or gamepad has


jumped
if (keyboard_check_direct(vk_space) ||
mouse_check_button(mb_left) || _gamepad_jump_tutorial)
{
// Set has jumped variable to true
has_jumped = true;

// Add jump strenght to y velosity


y_velo += jump_strength * _delta_time;

// Check if player is running


if (current_player_state ==
PLAYER_STATE.RUN)
{
// Set their state to idle
current_player_state =
PLAYER_STATE.IDLE;

// Resets the player sprite


sprite_index = spr_character_idle;
image_index = 0;

// Creates and sets up particle object


for initial jump flame
var _new_flame_particle =
instance_create_layer(x, y, "Stage", obj_particle_manager);

_new_flame_particle.set_particle(ps_inital_jump_flame,
"StageBackEffects");
_new_flame_particle.set_offset(0,
100);
_new_flame_particle.move_rate = 0;
_new_flame_particle.drag_rate =
0.05;

// Creates and sets up particle effect


for initial jump dust cloud effect
var _dust_particle =
instance_create_layer(x, y + 80, "Stage", obj_particle_manager);

_dust_particle.set_particle(ps_dust_small, "StageFrontEffects");
_dust_particle.move_rate = 0;
_dust_particle.drag_rate = 0.05;
}
// Check if vertical jump velocity is greater
than the threshold
else if (y_velo > jump_threshold)
{
// Set player state to big jump
current_player_state =
PLAYER_STATE.FLY_BIG;
// Resets the player sprite
sprite_index = spr_character_idle;
}
else
{
// Set player state to small jump
current_player_state =
PLAYER_STATE.FLY_SMALL;
// Resets the player sprite
sprite_index = spr_character_idle;
}
}
// Check if player is in air
else if (y < ystart)
{
// Sets player state to released (falling)
current_player_state =
PLAYER_STATE.FLY_RELEASED;
// Resets the player sprite
sprite_index = spr_character_idle;
}

break;
}

// Checks the game is not currently paused


if (obj_game_manager.current_game_state !=
GAME_STATE.PAUSED)
{
// Adjust velocity by gravity
y_velo -= gravity_strength;
// Adds the velocity to the y position
y -= y_velo;

// Checks if the player is under the ground level


if (y > ystart)
{
// Set the players y position back to ground
y = ystart;
// Set the vertical speed to zero
y_velo = 0.0;

// Checks if the game is playing or in tutorial mode


if (obj_game_manager.current_game_state ==
GAME_STATE.PLAYING || obj_game_manager.current_game_state
== GAME_STATE.TUTORIAL)
{
// When the player isnt running
if (current_player_state !=
PLAYER_STATE.RUN)
{
// Reset the player to run
current_player_state =
PLAYER_STATE.RUN;
// Set player sprite to running sprite
sprite_index = spr_character_run;
}

// If player has jumped and isnt boosting


if (has_jumped && !is_boosting)
{
// Create a particle effect at the
players feet for a dust effect (jump particle effect)
var _dust_particle =
instance_create_layer(x, y + 90, "Stage", obj_particle_manager);

_dust_particle.set_particle(ps_dust_small, "StageFrontEffects");
_dust_particle.move_rate = 0;
_dust_particle.drag_rate = 0.01;

// Set has jumped state back to false


has_jumped = false;
}
}
}
// If the player is above the top of the screen
else if (y < 0)
{
// Set the player to the top of the screen
y = 0;
// Clear their vertical velocity
y_velo = 0.0;
}

// Checks if the game is playing and the player is boosting


if (is_boosting &&
obj_game_manager.current_game_state == GAME_STATE.PLAYING)
{
// Change the player state to boosting
current_player_state = PLAYER_STATE.BOOST;
// Sets the plater sprite to the boosting sprite
sprite_index = spr_character_boost;
}
}
}

● End Step
// Checks if the game is paused
if (obj_game_manager.current_game_state ==
GAME_STATE.PAUSED)
{
// Fades out the sounds
audio_sound_gain(jet_sound, 0.0, 100);
audio_sound_gain(air_sound, 0.0, 100);

// Exits this event as no new particles need to be drawn


exit;
}

// Set up temp variables for the particle effects


var _new_flame_particle = -1;
var _new_flame_glow = -1;
var _new_smoke_particle = -1;
var _new_shimmer_particle = -1;

// Check the players states


switch (current_player_state)
{
// When big jumping up
case PLAYER_STATE.FLY_BIG:

// Checks if the right sound file is playing


if (audio_get_name(jet_sound) != "snd_jet_turbine")
{
// Stops the current sound
audio_stop_sound(jet_sound);
// Plays the correct sound
jet_sound = audio_play_sound(snd_jet_turbine,
100, false, 1.0);
}
else
{
// Sets sound gain
audio_sound_gain(jet_sound, 1.0, 0);
}

// Sets sound gain


audio_sound_gain(air_sound, 1.0, 0);

// Long flame press effect


_new_flame_particle = instance_create_layer(x, y,
"Stage", obj_particle_manager);
_new_flame_particle.owner = self;
_new_flame_particle.set_particle(ps_long_press_flame,
"StageBackEffects");
_new_flame_particle.set_offset(5, 95);

// Flame glow effect


_new_flame_glow = instance_create_layer(x, y, "Stage",
obj_particle_manager);
_new_flame_glow.owner = self;
_new_flame_glow.set_particle(ps_flame_glow,
"StageFrontEffects");
_new_flame_glow.set_offset(5, 95);

// Long press smoke effect


_new_smoke_particle = instance_create_layer(x, y,
"Stage", obj_particle_manager);
_new_smoke_particle.move_rate = 0.0;
_new_smoke_particle.drag_rate = 0.04;
_new_smoke_particle.set_particle(ps_long_press_smoke,
"StageFrontEffects");
_new_smoke_particle.set_angle(180);
_new_smoke_particle.set_offset(0, 100);

// Checks if game is in tutorial mode


if (obj_game_manager.current_game_state ==
GAME_STATE.TUTORIAL)
{
// Exits as shimmers not needed
break;
}

// Sets shimmers to normal level


_new_shimmer_particle = instance_create_layer(0, 0,
"Stage", obj_particle_manager);
_new_shimmer_particle.set_particle(ps_glimmers,
"StageFrontEffects");

break;

// When small jumping


case PLAYER_STATE.FLY_SMALL:

// Checks if the right sound file is playing


if (audio_get_name(jet_sound) != "snd_jet_turbine")
{
// Stops the current sound
audio_stop_sound(jet_sound);
// Plays the correct sound
jet_sound = audio_play_sound(snd_jet_turbine,
100, false, 1.0);
}
else
{
// Sets sound gain
audio_sound_gain(jet_sound, 1.0, 0);
}

// Sets sound gain


audio_sound_gain(air_sound, 1.0, 0);

// Small press flame effect


_new_flame_particle = instance_create_layer(x, y,
"Stage", obj_particle_manager);
_new_flame_particle.owner = self;
_new_flame_particle.set_particle(ps_short_press_flame,
"StageBackEffects");
_new_flame_particle.set_offset(5, 95);

// Flame glow effect


_new_flame_glow = instance_create_layer(x, y, "Stage",
obj_particle_manager);
_new_flame_glow.owner = self;
_new_flame_glow.set_particle(ps_flame_glow,
"StageFrontEffects");
_new_flame_glow.set_offset(5, 95);

// Smoke particle effect


_new_smoke_particle = instance_create_layer(x, y,
"Stage", obj_particle_manager);
_new_smoke_particle.move_rate = 0.0;
_new_smoke_particle.drag_rate = 0.04;
_new_smoke_particle.set_particle(ps_short_press_smoke,
"StageFrontEffects");
_new_smoke_particle.set_angle(180);
_new_smoke_particle.set_offset(0, 100);

// When game state is in tutorial mode


if (obj_game_manager.current_game_state ==
GAME_STATE.TUTORIAL)
{
// Exits as shimmers not needed
break;
}
_new_shimmer_particle = instance_create_layer(0, 0,
"Stage", obj_particle_manager);
_new_shimmer_particle.set_particle(ps_glimmers,
"StageFrontEffects");

break;

// When boosting
case PLAYER_STATE.BOOST:

// Checks if the right sound file is playing


if (audio_get_name(jet_sound) != "snd_jet_speed")
{
// Stops the current sound
audio_stop_sound(jet_sound);
// Plays the correct sound
jet_sound = audio_play_sound(snd_jet_speed, 100,
true, 1.0);
}
else
{
// Sets sound gain
audio_sound_gain(jet_sound, 1.0, 0);
}

// Sets sound gain


audio_sound_gain(air_sound, 1.0, 0);

// Creates speed boosting aura effect


var _new_aura_particle = instance_create_layer(x, y,
"Stage", obj_particle_manager);
_new_aura_particle.owner = self;
_new_aura_particle.set_particle(ps_speed_booster_aura,
"StageFrontEffects");
_new_aura_particle.set_angle(270);
_new_aura_particle.set_offset(-140, 10);

// Creates speed boosting flame effect


_new_flame_particle = instance_create_layer(x, y,
"Stage", obj_particle_manager);
_new_flame_particle.owner = self;

_new_flame_particle.set_particle(ps_speed_booster_flame,
"StageBackEffects");
_new_flame_particle.set_angle(270);
_new_flame_particle.set_offset(-100, 30);

// Creates speed boosting smoke effect


_new_smoke_particle = instance_create_layer(x, y,
"Stage", obj_particle_manager);
_new_smoke_particle.owner = self;

_new_smoke_particle.set_particle(ps_speed_booster_smoke,
"StageFrontEffects");
_new_smoke_particle.set_angle(90);
_new_smoke_particle.set_offset(-100, 30);

// Creates intense shimmmering effect


_new_shimmer_particle = instance_create_layer(0, 0,
"Stage", obj_particle_manager);
_new_shimmer_particle.set_particle(ps_glimmers_intense,
"StageFrontEffects");

break;

// When player is normal running


case PLAYER_STATE.RUN:

// Sets sound gain to 0 and resets jet sound


audio_stop_sound(jet_sound);
jet_sound = audio_play_sound(snd_jet_air, 100, true, 0.0);
audio_sound_gain(air_sound, 0.0, 0);

// If the player is running fast enough (more than 5%)


if (obj_game_manager.current_speed_percentage > 0.05)
{
// Create running dust effect
_new_smoke_particle = instance_create_layer(x, y,
"Stage", obj_particle_manager);
_new_smoke_particle.move_rate = 0;
_new_smoke_particle.drag_rate = 0.005;
_new_smoke_particle.set_particle(ps_run_dust,
"StageBackEffects");
_new_smoke_particle.set_offset(-10, 85);
}

// When the game is not in the tutorial


if (obj_game_manager.current_game_state !=
GAME_STATE.TUTORIAL)
{
// Create the shimmering effect
_new_shimmer_particle = instance_create_layer(0,
0, "Stage", obj_particle_manager);
_new_shimmer_particle.set_particle(ps_glimmers,
"StageFrontEffects");
}

// Checks the for step frame and step hasnt played for the
step
if (!has_stepped && (round(image_index) == 2 ||
round(image_index) == 7))
{
// Chooses a random footstep
var _footstep = choose(snd_chicken_footstep_1,
snd_chicken_footstep_2, snd_chicken_footstep_3,
snd_chicken_footstep_4, snd_chicken_footstep_5,
snd_chicken_footstep_6, snd_chicken_footstep_7);
// Plays the footstep sound
audio_play_sound(_footstep, 100, false, 1.0);

// Sets step state to true


has_stepped = true;
}
// Checks is not currently on a step frame
else if (!(round(image_index) == 2 || round(image_index)
== 7))
{
// Sets step state to false
has_stepped = false;
}

break;
// When the player is idle
case PLAYER_STATE.IDLE:

// Sets sound gain to 0 and resets jet sound


audio_stop_sound(jet_sound);
jet_sound = audio_play_sound(snd_jet_air, 100, true, 0.0);
audio_sound_gain(air_sound, 0.0, 0);

// Game is not in tutorial


if (obj_game_manager.current_game_state !=
GAME_STATE.TUTORIAL)
{
// Create shimmering effect
_new_shimmer_particle = instance_create_layer(0,
0, "Stage", obj_particle_manager);
_new_shimmer_particle.set_particle(ps_glimmers,
"StageFrontEffects");
}

break;

// When player has relased the fly button


case PLAYER_STATE.FLY_RELEASED:

// Sets sound gain and resets jet sound


audio_stop_sound(jet_sound);
jet_sound = audio_play_sound(snd_jet_air, 100, true, 0.0);
audio_sound_gain(air_sound, 1.0, 0);

// Game is not in tutorial


if (obj_game_manager.current_game_state !=
GAME_STATE.TUTORIAL)
{
// Create shimmering effect
_new_shimmer_particle = instance_create_layer(0,
0, "Stage", obj_particle_manager);
_new_shimmer_particle.set_particle(ps_glimmers,
"StageFrontEffects");
}
break;

// When the player is dying


case PLAYER_STATE.DEATH:

// Sets sound gain to 0 and resets jet sound


audio_stop_sound(jet_sound);
jet_sound = audio_play_sound(snd_jet_air, 100, true, 0.0);
audio_sound_gain(air_sound, 0.0, 0);

// If the game has ended


if (obj_game_manager.current_game_state ==
GAME_STATE.ENDED)
{
// Exits without shimmers
break;
}

// Create shimmers as player is technically still moving


_new_shimmer_particle = instance_create_layer(0, 0,
"Stage", obj_particle_manager);
_new_shimmer_particle.set_particle(ps_glimmers,
"StageFrontEffects");

break;
}

● Draw
// Change logic depending on the current game state.
switch (obj_game_manager.current_game_state)
{
// Logic for while the game is playing.
case GAME_STATE.PLAYING:
image_speed = 2.0 *
clamp(obj_game_manager.current_speed_percentage, 0.25, 1.0);
break;

// Normal speed when dying


case GAME_STATE.DYING:
image_speed = 1.0;
break;
// Stopped animations when dead
case GAME_STATE.ENDED:
image_speed = 0.0;
break;

// Stopped animations when paused


case GAME_STATE.PAUSED:
image_speed = 0.0;
break;
}

draw_self();

● Animation End
// Checks if the player is dead
if (current_player_state == PLAYER_STATE.DEATH)
{
// Sets alpha to zero to hide
image_alpha = 0;
}
// Checks if the player is idle
else if (current_player_state == PLAYER_STATE.IDLE)
{
// Sets the animation to small flying state
current_player_state = PLAYER_STATE.FLY_SMALL;
// Resets the set sprite to idle
sprite_index = spr_character_idle;
}

c. obj_shadow(bóng tối)
● Create
// Checks if the player is dead
if (current_player_state == PLAYER_STATE.DEATH)
{
// Sets alpha to zero to hide
image_alpha = 0;
}
// Checks if the player is idle
else if (current_player_state == PLAYER_STATE.IDLE)
{
// Sets the animation to small flying state
current_player_state = PLAYER_STATE.FLY_SMALL;
// Resets the set sprite to idle
sprite_index = spr_character_idle;
}
● Step
// Checks game isnt paused
if (obj_game_manager.current_game_state != GAME_STATE.PAUSED)
{
// Checks owner has been set
if (owner != noone)
{
// Set x position to follow owner
x = owner.x;

// Temp variables for scaling the shadows size based on how high
the owner is to the ground where it exists
var _delta_y = abs(y - owner.y) - y_offset;
var _scale = 1;
var _shadow_height = 400;

// Checks the scale has changed from the original height


if (_delta_y > 0)
{
// Recalculate the scale based on the height of the owner
compared to the shadow
_scale = (_shadow_height - clamp(_delta_y, 0,
_shadow_height)) * (1 / _shadow_height);

// Sets the image alpha to the scale


image_alpha = _scale;

// Clamp the scale so its a value betwen 0.6 and 1


_scale = clamp(_scale, 0.6, 1.00);

// Set the actual image scales to 1 devided by the new scale


variable
image_xscale = 1 / _scale;
image_yscale = 1 / _scale;
}
else
{
// Sets shadow to fade out after 0.1 seconds
fade_out(0.1);
}

// Checks if shadow can fade out


if (can_fade)
{
// Sets the shadows fade level to decrease slowly over time set
fade_level -= (1 / fade_time) * delta_time * 0.000001;

// Checks if the shadow should no longer be visible


if (fade_level < 0)
{
// Sets value back to zero
fade_level = 0;
}

// Sets the images alpha to the fade level


image_alpha *= fade_level;

// Checks if the alpha is equal to 0 (invisible)


if (image_alpha == 0)
{
// Destroys the shadow object
instance_destroy();
}
}
}

d. obj_shield
● Create
// Sets the shield to initally be invisible
image_alpha = 0;
// Life variable for shield counts down till it should end
life = 0;

// State for if shield can have pulse effect when dying


can_pulse = false;

// Plays shield sound


shield_sound = audio_play_sound(snd_shield_effect, 100, true, 1.0);

// Checks if the game is not playing (collected after player dealth)


if (obj_game_manager.current_game_state !=
GAME_STATE.PLAYING)
{
// Sets the sprite into the off state to kill immediately
sprite_index = spr_shield_off;
}

● Destroy
audio_stop_sound(shield_sound);
● Step
// Checks if the game is not currently paused
if (obj_game_manager.current_game_state !=
GAME_STATE.PAUSED)
{
// Sets the shield position to the players positions
x = obj_player.x;
y = obj_player.y;

// Reduce the shields life by time passed


life -= delta_time * 0.000001;

// Sets the image to lerp towards visible state


image_alpha = lerp(image_alpha, 1.0, 0.1);

// Checks the life values to know if pulsing should be enabled


if (life > 0 && life < 2)
{
// Sets pulsing state
can_pulse = true;
}
else
{
// Unsets pulsing state as more life may have been added
can_pulse = false;
}

// Checks if shield is dead but not set to dead yet


if (life <= 0 && sprite_index != spr_shield_off)
{
// Creates power up out effect
var _new_aura_particle =
instance_create_layer(obj_player.x, obj_player.y, "Stage",
obj_particle_manager);
_new_aura_particle.owner = obj_player;
_new_aura_particle.set_particle(ps_powerup_out,
"StageFrontEffects");

// Sets sprite to off sprite


sprite_index = spr_shield_off;
image_index = 0;

// Sets the gain of shield sound to off


audio_sound_gain(shield_sound, 0.0, 100);

// Plays shield break sound


audio_play_sound(snd_shield_deactivated, 100, false,
1.0);
}

// Plays animation speed normally


image_speed = 1;
}
else
{
// Pauses animation speed
image_speed = 0;
}

if (sprite_index != spr_shield_off)
{
if (obj_game_manager.current_game_state ==
GAME_STATE.PLAYING)
{
// Sets the gain of shield sound to on
audio_sound_gain(shield_sound, 1.0, 0);
}
else
{
// Sets the gain of shield sound to off
audio_sound_gain(shield_sound, 0.0, 0);
}
}

● Draw
// Checks if game is paused
if (obj_game_manager.current_game_state ==
GAME_STATE.PAUSED)
{
// Pauses animation speed
image_speed = 0;
}
else
{
// Plays animation speed normally
image_speed = 1;
}

// Creates temp variable for blend rate


var _blend_rate = 1.0;

// Checks pulse state


if (can_pulse)
{
// Sets rate to vaule set by current life remaining and cos function
so value goes between 0 and 1
_blend_rate = cos(pi / (life % 8));
}

// Sets warn colour to near red


var _warn_colour = make_color_rgb(255, 220, 220);
// Blends the image colour to value of blend rate beween set warn colour
and white
image_blend = merge_color(_warn_colour, c_white, _blend_rate);

// Draws shield
draw_self();

● Animation End
// If the sprite animation for off state has finished
if (sprite_index == spr_shield_off)
{
// Destroy the shield object as it has died fully
instance_destroy();
}

6. UI

7. Particles systems
8. Sprites
9. UI

You might also like