diff --git a/src/game/player.c b/src/game/player.c index 0d47a68..67cfe64 100644 --- a/src/game/player.c +++ b/src/game/player.c @@ -300,6 +300,33 @@ void player_update(Entity *self, float dt, const Tilemap *map) { return; } + /* ── Double-tap down for free downward jetpack ── */ + if (!body->on_ground && input_pressed(ACTION_DOWN)) { + if (pd->down_tap_timer > 0) { + /* Second tap — trigger free downward dash */ + pd->down_tap_timer = 0; + pd->dash_timer = PLAYER_DASH_DURATION; + pd->dash_dir = vec2(0.0f, 1.0f); + + /* Brief invincibility during dash */ + pd->inv_timer = PLAYER_DASH_DURATION; + self->flags |= ENTITY_INVINCIBLE; + + /* Jetpack burst downward */ + Vec2 exhaust_pos = vec2( + body->pos.x + body->size.x * 0.5f, + body->pos.y + body->size.y * 0.5f + ); + particle_emit_jetpack_burst(exhaust_pos, pd->dash_dir); + audio_play_sound(s_sfx_dash, 96); + return; + } + pd->down_tap_timer = 0.3f; /* window for second tap */ + } + if (pd->down_tap_timer > 0) { + pd->down_tap_timer -= dt; + } + if (input_pressed(ACTION_DASH) && pd->dash_charges > 0) { pd->dash_charges--; stats_record_dash(); @@ -478,6 +505,7 @@ void player_update(Entity *self, float dt, const Tilemap *map) { /* ── Landing detection ───────────────────── */ if (body->on_ground && !pd->was_on_ground) { + pd->down_tap_timer = 0; /* reset double-tap on landing */ /* Just landed — emit dust at feet */ Vec2 feet = vec2( body->pos.x + body->size.x * 0.5f, diff --git a/src/game/player.h b/src/game/player.h index 42e187e..a23fc5f 100644 --- a/src/game/player.h +++ b/src/game/player.h @@ -67,6 +67,8 @@ typedef struct PlayerData { AimDir aim_dir; /* current aim direction */ bool looking_up; /* holding up without moving */ float look_up_timer; /* how long up has been held */ + /* Down-arrow double-tap (free downward jetpack) */ + float down_tap_timer; /* time since last mid-air down press */ /* Death / Respawn */ float respawn_timer; /* countdown after death anim finishes */ Vec2 spawn_point; /* where to respawn */