HT Games

Implementing Jump Mechanics in GameMaker (GML)

Here's a production-ready jump implementation for GameMaker (GMS2.3+), covering coyote time, jump buffer, variable height, and one-way platforms.

Player Create Event

// Movement
hsp = 0; vsp = 0; walk_spd = 4.5; run_spd = 6.5; accel = 0.4; decel = 0.35; grav = 0.5; term_vel = 14; jump_force = -10.5; jump_hold_force = -0.3; // variable height
coyote_frames = 6; jump_buffer_frames = 6; coyote = 0; jbuf = 0; on_ground = false; on_ice = false;
// State
state = "idle";

Player Step Event

// --- INPUT ---
var left = keyboard_check(vk_left) || keyboard_check(ord("A"));
var right = keyboard_check(vk_right) || keyboard_check(ord("D"));
var jump_pressed = keyboard_check_pressed(vk_space) || keyboard_check_pressed(ord("W"));
var jump_held = keyboard_check(vk_space) || keyboard_check(ord("W"));
var run_held = keyboard_check(vk_shift);

// --- BUFFERS ---
if (jump_pressed) jbuf = jump_buffer_frames; else if (jbuf > 0) jbuf--;
if (on_ground) coyote = coyote_frames; else if (coyote > 0) coyote--;

// --- HORIZONTAL ---
var target_spd = (run_held ? run_spd : walk_spd);
if (left) hsp = max(hsp - accel, -target_spd);
else if (right) hsp = min(hsp + accel, target_spd);
else hsp = lerp(hsp, 0, decel);

// Ice modifier
if (on_ice) { accel = 0.1; decel = 0.02; } else { accel = 0.4; decel = 0.35; }

// --- JUMP INIT ---
if (jbuf > 0 && coyote > 0) {
    vsp = jump_force;
    on_ground = false;
    coyote = 0;
    jbuf = 0;
    audio_play_sound(snd_jump, 10, false);
    // Particle puff
    effect_create_below(ef_smoke, x, y, 0, c_white);
}

// --- VARIABLE JUMP HEIGHT ---
if (!jump_held && vsp < jump_force * 0.3) {
    vsp = jump_force * 0.3; // cutoff
}

// --- GRAVITY ---
vsp = min(vsp + grav, term_vel);

// --- COLLISION (Horizontal) ---
var _x = x + sign(hsp);
repeat(abs(hsp)) {
    if (!place_meeting(_x, y, obj_solid)) x = _x;
    else { hsp = 0; break; }
    _x += sign(hsp);
}

// --- COLLISION (Vertical) ---
var _y = y + sign(vsp);
on_ground = false; // reset, set below if landed
repeat(abs(vsp)) {
    if (!place_meeting(x, _y, obj_solid)) y = _y;
    else {
        vsp = 0;
        if (sign(vsp) > 0) { // moving down
            on_ground = true;
            // One-way platform check
            if (place_meeting(x, y+1, obj_oneway) && vsp >= 0) {
                // allow pass-through if falling fast? usually handled by obj_oneway collision mask
            }
        }
        break;
    }
    _y += sign(vsp);
}

// --- STATE / ANIM ---
if (!on_ground) state = (vsp < 0 ? "jump" : "fall");
else if (hsp != 0) state = (run_held ? "run" : "walk");
else state = "idle";
sprite_index = sprite_get("spr_player_" + state);

Advanced Features (Add as Needed)

  • Double Jump: Add jumps_used var. Reset to 0 on on_ground. Allow if jumps_used < max_jumps && jbuf > 0.
  • Wall Jump / Slide: Check place_meeting(x+sign(hsp), y, obj_solid) + !on_ground → reset jumps_used, set vsp = jump_force * 0.8, flip hsp.
  • Dash: if (keyboard_check_pressed(vk_shift) && dash_cooldown <= 0) { hsp = sign(hsp) * 20; dash_cooldown = 60; }
  • Moving Platforms: Store platform_hsp, platform_vsp on collision → add to player x/y after collision resolution.

Debug Visualizer (Draw GUI)

draw_text(10, 10, "vsp: " + string(vsp));
draw_text(10, 30, "on_ground: " + string(on_ground));
draw_text(10, 50, "coyote: " + string(coyote));
draw_text(10, 70, "jbuf: " + string(jbuf));

This structure scales to Celeste/Hollow Knight feel. Tune grav, jump_force, coyote_frames per game feel.


https://www.htfbw.com © HT Games