Skip to content

Instantly share code, notes, and snippets.

@RandyGaul
Last active July 28, 2025 23:52
Show Gist options
  • Save RandyGaul/31d9c7d6ad7d15c994a362e8353158ed to your computer and use it in GitHub Desktop.
Save RandyGaul/31d9c7d6ad7d15c994a362e8353158ed to your computer and use it in GitHub Desktop.
Climbing example of 2d platformer coroutine use case
function Player:climb()
self.climbing = true
self:set_facing(self.climbable_wall_facing)
-- Initially zero out all y-vel to "latch" onto the wall.
if not self.climb_sliding then
self.vy = 0
end
self.vx = 0
self.climbing_needs_reset = true
joypad_rumble(1, 0.15, 0.15, 0.25)
yield()
-- Handles all cases to exit the climbing state.
local was_climbing_on = collide_at(self, self.climbable_wall_facing * climb_pixel_grace, 0)
local function should_stop_climbing()
if self.input_jump:just_pressed() then
self:wall_jump()
return true
end
-- Exit if there's no more wall.
local dx = self.climbable_wall_facing * climb_pixel_grace
local climb_on = collide_at(self, dx, 0)
if not climb_on then
-- Start a little hop to just above the ledge for convenience if you've climbed up something.
self.vy = self.vy + 15
self.vx = self.vx + 75*sign(dx)
self.climbing = false
self.climbing_fall_grace_timer = fall_grace_time
assert(was_climbing_on)
self:climb_onto_ledge(was_climbing_on)
return true
else
was_climbing_on = climb_on
end
-- Exit if let go of climbing trigger.
if not self.input_climb:down() then return true end
end
-- This happens if you slide down a wall and touch the ground.
::climb_again::
-- Climbing state.
while true do
yield()
if should_stop_climbing() then
goto stop_climbing
end
if not self.on_ground and on_interval(0.4) then
joypad_rumble(1, 0.15, 0.15, 0.1)
end
if self.on_ground then
self.climbing_elapsed = 0
end
-- Climbing.
local sign_x, sign_y = self.input_move:sign()
if sign_y >= 0 or sign_y <= 0 then
local down_boost = 1
if sign_y < 0 then down_boost = 1.5 end
self.vy = approach(self.vy, climb_speed * sign_y * down_boost, climb_accel * DELTA_TIME)
else
self.vy = approach(self.vy, 0, climb_accel * DELTA_TIME)
end
-- Grace period to hang on the wall before sliding.
self.climbing_elapsed = self.climbing_elapsed + DELTA_TIME
if self.climbing_elapsed > climb_time then break end
end
self.climb_sliding = true
self.vy = min(self.vy, 0) -- Prevent weird upwards sliding.
-- Sliding down the wall state.
while true do
if should_stop_climbing() then
goto stop_climbing
end
if self.on_ground then
goto climb_again
end
-- Slide down wall.
self.vy = approach(self.vy, -wall_slide_speed, wall_slide_accel * DELTA_TIME)
if on_interval(0.2) then
joypad_rumble(1, 0.25, 0.25, 0.2)
end
::continue::
yield()
end
::stop_climbing::
self.climbing_fall_grace_timer = fall_grace_time
self.climbing = false
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment