Fat Pint Games
Fat Pint Games › Asset Documentation › Matrix Engine
Matrix Engine logo

Control the flow of time in your project for Gamemaker.

GameMaker Asset

Matrix Engine

A compact time-management engine for GameMaker that keeps alarms, timers, animation speed and time-dilation transitions working together through one global game-speed value.

GameMaker 2023.0+Alarm ManagementTimer ManagementTime Dilation

Features

Licence

You may use the Matrix Engine in personal or commercial projects.

Credit is not required, but is appreciated.

How to Use

Place obj_alarm_manager into a room at the start of your game, before any Matrix Engine alarms or timers are created.

The object is persistent and only needs to be created once.

Important: Do not create any alarms or timers before obj_alarm_manager exists.

Main Functions

The asset contains four related groups of functions: alarm management, timer management, time dilation and image-speed management.

Alarm Management

alarm_set_ext()

Create a new alarm or update an existing alarm.

alarm_get_ext()

Get the current remaining duration of an alarm in frames.

alarm_set_state()

Temporarily activate or pause an alarm.

alarm_get_state()

Check the current state of an alarm.

alarm_exists()

Check whether a specified alarm exists.

alarm_destroy()

Destroy a specified alarm.

alarm_check_game_paused()

Return whether the game is paused. Only alarms and timers flagged to work while paused will continue ticking.

Timer Management

timer_create()

Create a new timer or reset an existing timer.

timer_get_elapsed()

Get the total active time elapsed since the timer started.

timer_set_state()

Temporarily activate or pause a timer.

timer_get_state()

Check the current state of a timer.

timer_exists()

Check whether a specified timer exists.

timer_destroy()

Destroy a specified timer.

timer_exceeded_frames()

Check whether a timer has exceeded a specified number of frames.

Time Dilation

dilation_set_speed()

Set the game speed instantly or transition over a number of real frames.

dilation_get_speed()

Get the current game speed.

dilation_is_transitioning()

Check whether a speed transition is currently taking place.

dilation_get_target_speed()

Get the speed that the game is currently transitioning towards.

Image Speed

Object animation speeds must also be updated so that animations look correct at the current game speed.

image_speed_set()

Set the image speed an object should use at 100% game speed.

image_speed_step()

Apply the speed adjustment. This is typically called once from the object's Step event.

image_speed_set() may be called from anywhere. image_speed_step() is usually best called once per Step event.

Alarm Function Arguments

Arguments marked Optional do not need to be supplied.

alarm_set_ext()

ArgumentRequiredDescription
_nameYesA string used to label the purpose of the alarm.
_framesYesThe number of frames the alarm should last when game speed is 100% (1).
_instance_idOptionalThe instance ID that the alarm belongs to.
_repeat_countOptionalHow many times the alarm repeats before being destroyed.
_funcOptionalThe function, or variable referencing a function, that triggers when the alarm reaches zero.
_argsOptionalAn array of arguments passed into the triggered function.
_works_when_pausedOptionalWhether the alarm continues ticking and can trigger while the game is paused.
_stateOptionalThe initial state: alarm_state.paused or alarm_state.active.

alarm_get_ext(), alarm_get_state(), alarm_exists() and alarm_destroy()

ArgumentRequiredDescription
_nameYesThe name assigned to the alarm.
_instance_idOptionalThe instance ID that the alarm belongs to.

alarm_set_state()

ArgumentRequiredDescription
_nameYesThe name assigned to the alarm.
_stateYesThe desired state: alarm_state.active or alarm_state.paused.
_instance_idOptionalThe instance ID that the alarm belongs to.

Timer Function Arguments

timer_create()

ArgumentRequiredDescription
_nameYesA string used to label the purpose of the timer.
_instance_idOptionalThe instance ID that the timer belongs to.
_works_when_pausedOptionalWhether the timer continues counting while the game is paused.
_stateOptionalThe initial state: timer_state.paused or timer_state.active.

timer_get_elapsed(), timer_get_state(), timer_exists() and timer_destroy()

ArgumentRequiredDescription
_nameYesThe name assigned to the timer.
_instance_idOptionalThe instance ID that the timer belongs to.

timer_set_state()

ArgumentRequiredDescription
_nameYesThe name assigned to the timer.
_stateYesThe desired state: timer_state.active or timer_state.paused.
_instance_idOptionalThe instance ID that the timer belongs to.

timer_exceeded_frames()

ArgumentRequiredDescription
_nameYesThe name assigned to the timer.
_framesYesThe elapsed frame count to compare against.
_instance_idOptionalThe instance ID that the timer belongs to.

Time Dilation and Image Speed Arguments

dilation_set_speed()

ArgumentRequiredDescription
_game_speedYesThe desired game speed. 0 is frozen, 1 is normal speed and 2 is double speed.
_framesOptionalThe number of real frames used to transition to the desired speed.

image_speed_set()

ArgumentRequiredDescription
_image_speedYesThe image speed the object would use when game speed is 100%.

Usage Examples

The following examples show common game scenarios for every Matrix Engine function. Function and timer names are only examples and may be replaced with names that suit your project.

Alarm Management Examples

alarm_set_ext()

Enemy area scan

alarm_set_ext("scan", MATRIX_SEC * 5, id, 3, scan_area);

This instance executes scan_area() every 5 in-game seconds. It triggers 3 times before the alarm is destroyed.

Delayed boss attack with arguments

alarm_set_ext(
    "meteor_strike",
    MATRIX_SEC * 2,
    id,
    0,
    launch_meteor,
    [target_x, target_y]
);

After 2 in-game seconds, the boss calls launch_meteor(target_x, target_y) once.

alarm_get_ext()

Display a reload countdown

var _frames_remaining = alarm_get_ext("shotgun_reload", id);
var _seconds_remaining = ceil(_frames_remaining / MATRIX_SEC);

Gets the remaining reload duration so it can be displayed as seconds in the user interface.

Warn before a shield expires

if (alarm_get_ext("energy_shield", id) <= MATRIX_SEC)
{
    shield_flash_warning = true;
}

Starts a warning effect when the shield alarm has 1 in-game second or less remaining.

alarm_set_state()

Pause a hacking sequence

alarm_set_state("hack_complete", alarm_state.paused, id);

Pauses the hacking alarm without removing its remaining duration.

Resume a trap countdown

alarm_set_state("floor_trap", alarm_state.active, id);

Reactivates a previously paused floor-trap alarm.

alarm_get_state()

Check whether crafting is paused

if (alarm_get_state("craft_item", id) == alarm_state.paused)
{
    draw_text(x, y - 32, "Crafting Paused");
}

Checks the current state before displaying a paused message.

Only allow another pause while active

if (alarm_get_state("door_close", id) == alarm_state.active)
{
    alarm_set_state("door_close", alarm_state.paused, id);
}

Confirms the door alarm is active before pausing it.

alarm_exists()

Prevent duplicate enemy spawns

if (!alarm_exists("spawn_reinforcements", id))
{
    alarm_set_ext("spawn_reinforcements", MATRIX_SEC * 8, id, 0, spawn_squad);
}

Creates the reinforcement alarm only when an alarm with that name and instance ID does not already exist.

Show whether a buff is active

rage_buff_active = alarm_exists("rage_buff", id);

Uses the alarm's existence as a simple way to track whether the rage buff is still active.

alarm_destroy()

Cancel a self-destruct sequence

alarm_destroy("self_destruct", id);

Immediately removes the self-destruct alarm.

Remove a cancelled quest reminder

if (quest_cancelled)
{
    alarm_destroy("quest_reminder");
}

Destroys a global quest reminder when the related quest is cancelled.

alarm_check_game_paused()

Check the current pause condition

if (alarm_check_game_paused())
{
    draw_text(32, 32, "Paused");
}

Returns true when the pause condition used by the Matrix Engine is currently met.

Timer Management Examples

timer_create()

Track survival time

timer_create("survival_time");

Creates a global timer that begins counting active in-game frames immediately.

Track a player's sprint duration

timer_create("sprint_duration", id);

Creates an instance-specific timer for the player currently sprinting.

timer_get_elapsed()

Display survival seconds

var _survival_seconds = floor(timer_get_elapsed("survival_time") / MATRIX_SEC);

Converts the timer's elapsed frames into whole in-game seconds.

Scale a charge attack

var _charge_frames = timer_get_elapsed("charge_attack", id);
charge_power = clamp(_charge_frames / (MATRIX_SEC * 3), 0, 1);

Increases charge power over 3 in-game seconds.

timer_set_state()

Pause dialogue reading time

timer_set_state("dialogue_read_time", timer_state.paused);

Pauses the timer without losing the time already accumulated.

Resume a race timer

timer_set_state("lap_time", timer_state.active, id);

Resumes the lap timer for the specified racer instance.

timer_get_state()

Show whether a lap timer is running

lap_timer_running =
    timer_get_state("lap_time", id) == timer_state.active;

Stores whether the racer's lap timer is currently active.

Resume a paused mission clock

if (timer_get_state("mission_clock") == timer_state.paused)
{
    timer_set_state("mission_clock", timer_state.active);
}

Checks the timer's state before resuming it.

timer_exists()

Create a combo timer once

if (!timer_exists("combo_time", id))
{
    timer_create("combo_time", id);
}

Prevents a new combo timer from being created every frame.

Check whether a speedrun has started

speedrun_active = timer_exists("speedrun_clock");

Stores whether the global speedrun timer currently exists.

timer_destroy()

Clear a completed lap timer

timer_destroy("lap_time", id);

Removes the timer after the racer completes the lap.

Reset a failed challenge

if (challenge_failed)
{
    timer_destroy("no_damage_challenge");
}

Destroys the global challenge timer when the challenge fails.

timer_exceeded_frames()

Finish a weapon reload

if (timer_exceeded_frames("rocket_reload", MATRIX_SEC * 8, id))
{
    rocket_ready = true;
}

Makes the rocket launcher available after 8 active in-game seconds.

Unlock a survival achievement

if (timer_exceeded_frames("survival_time", MATRIX_SEC * 300))
{
    achievement_unlock("survive_five_minutes");
}

Unlocks an achievement after the player survives for 5 in-game minutes.

Time Dilation Examples

dilation_set_speed()

Instant slow motion

dilation_set_speed(0.25);

Immediately slows the game to 25% speed.

Smooth return to normal speed

dilation_set_speed(1, MATRIX_SEC * 2);

Transitions back to normal speed over 2 real-time seconds.

dilation_get_speed()

Display the current speed percentage

var _speed_percent = round(dilation_get_speed() * 100);
draw_text(32, 32, "Game Speed: " + string(_speed_percent) + "%");

Converts the current speed multiplier into a percentage for the user interface.

Play an effect while time is slowed

if (dilation_get_speed() < 1)
{
    draw_set_alpha(0.35);
    draw_rectangle(0, 0, room_width, room_height, false);
    draw_set_alpha(1);
}

Draws a visual overlay whenever the game is running below normal speed.

dilation_is_transitioning()

Disable repeated transition input

if (!dilation_is_transitioning())
{
    dilation_set_speed(0.4, MATRIX_SEC);
}

Starts a new slow-motion transition only when another transition is not already in progress.

Show a transition indicator

if (dilation_is_transitioning())
{
    draw_text(32, 64, "Time speed changing...");
}

Displays a message while the current speed is moving towards its target.

dilation_get_target_speed()

Display the target speed

var _target_percent = round(dilation_get_target_speed() * 100);
draw_text(32, 96, "Target Speed: " + string(_target_percent) + "%");

Displays the speed currently being approached by a transition.

Choose an appropriate sound effect

if (dilation_get_target_speed() < dilation_get_speed())
{
    audio_play_sound(snd_time_slow, 0, false);
}
else
{
    audio_play_sound(snd_time_restore, 0, false);
}

Chooses a sound depending on whether time is transitioning slower or faster.

Image Speed Examples

image_speed_set()

Set a walk animation

image_speed_set(0.2);

Set the image speed of an object to 0.2 at normal game speed and applies the current time-dilation multiplier.

Change animation speed by state

if (is_sprinting)
{
    image_speed_set(0.35);
}
else
{
    image_speed_set(0.15);
}

Updates the intended animation speed without assigning directly to GameMaker's built-in image_speed variable.

image_speed_step()

Keep a player animation synchronised

Step Event
image_speed_step();

Reapplies the current time-dilation speed every frame. Should be called in the step event of an object (or parent object) that animates

Synchronise only while animated

Step Event
if (sprite_get_number(sprite_index) > 1)
{
    image_speed_step();
}

Updates time-scaled image speed only when the current sprite contains more than one frame.

Object Movement and Image Speed

Time-scaled movement

Any movement that should respond to time dilation must be multiplied by SPEED_MOD. This macro represents global.speed_modifier.

At normal speed, SPEED_MOD is 1. At half speed it is 0.5, and at double speed it is 2. Multiplying movement by this value keeps objects moving at the same relative rate as the rest of the game.

Horizontal movement

Step Event
x += move_speed * SPEED_MOD;

The object moves by its regular movement speed multiplied by the current game-speed modifier.

Directional movement

Step Event
x += lengthdir_x(move_speed, direction) * SPEED_MOD;
y += lengthdir_y(move_speed, direction) * SPEED_MOD;

Both movement axes are scaled so the object remains synchronised during slow motion, pauses and increased speed.

Important: Do not multiply movement that is deliberately meant to occur in real time, such as certain pause-menu animations or interface movement.

Time-scaled image speed

Whenever an instance's animation speed should respond to time dilation, use image_speed_set(_speed) instead of assigning directly to the built-in image_speed variable.

For example, replace:

image_speed = 0.2;

with:

image_speed_set(0.2);

The value supplied to image_speed_set() is the animation speed the object should use while the game is running at normal speed.

Any object whose animation is affected by time dilation must also call image_speed_step() once every frame. The object's Step event is usually the best location:

Apply animation time dilation

Step Event
image_speed_step();

This ensures the instance's built-in image_speed continually matches the current game speed and keeps the animation visually synchronised as time dilation changes.

Recommended pattern: Call image_speed_set() whenever the object's intended animation speed changes, and call image_speed_step() from code that runs once every frame.

Additional Information

Additional Information for HTML Builds

In an HTML build, the game may freeze when executing a fallback check that uses:

if (asset_get_type(_instance_id) == asset_object)

This fallback is used in case an object type was passed instead of an instance ID. For HTML builds, comment out blocks that use this check.

After removing the fallback, ensure that every function receives a valid instance ID whenever an instance-specific alarm or timer is required.