celeste-momentum-platforming is a skill from the Summer skill library: a guide your AI agent reads when the task matches, so it builds the good version on the first try. Celeste-style 2D precision platformer movement — momentum running, coyote time, variable jumps, dash, wall jump/slide, climb stamina, pixel corner correction.
When your agent uses it
- Make the platformer movement feel like Celeste
- Add coyote time, variable jump height, and a dash to my 2D platformer
- Add wall jumps, wall slides, or climb stamina to a 2D character
- My 2D platformer controller feels unfair or unresponsive
Install
summer setup installs every skill for your agent. To add only this one:
claude-code for your agent, such as codex or cursor. See Skills for every option.
The skill
Outcome
A 2D character controller for Summer Engine that reproduces the tuning architecture and forgiveness mechanics of Celeste’s player movement: momentum-based running with distinct ground/air acceleration, variable-height jumping with coyote time, a multi-directional dash with cooldown and residual speed, wall interaction (jump, slide, climb with stamina), and pixel-scale corner corrections that make near-miss inputs succeed instead of fail.When to Use
- Building a precision 2D platformer in Summer Engine where movement feel is the core gameplay.
- Porting or prototyping Celeste-style mechanics (dash, wall jump, climb stamina).
- Tuning an existing platformer controller that feels “unfair” or unresponsive — the forgiveness systems below are the primary fix.
Core Principle
Celeste’s movement is a single controller class driven by an explicit integer state machine, with all feel-critical numbers as a flat compile-time constants table at the top of the class. The released source (Player.cs, 5,471 lines) defines states Normal=0, Climb=1, Dash=2, Swim=3, Boost=4, RedDash=5, HitSquash=6, Launch=7, Pickup=8, DreamDash=9 (+ a Summit state), each with Begin/Update/End callbacks. State transitions are direct integer assignments.
The second principle: forgiveness at the pixel and millisecond scale. The code repeatedly nudges the player 2–6 pixels or grants 50–200 ms windows so that inputs which are almost correct still succeed. Most of the “tight” feel comes from these windows.
Tuning Constants (verbatim from Player.cs)
Celeste’s units are pixels/second for speeds and pixels/second² for accelerations at its native resolution; times in seconds. When porting, preserve the ratios more than the absolute numbers if your pixels-per-meter differs.Gravity & Falling
Running
Jumping
Wall Interaction
Super Variants
Dash
Climb / Stamina
Other
Scene / Node Shape
Reference Implementation Skeleton (GDScript)
Player.cs. The constants, state IDs, and confirmed behaviors (corner correction loops, variable-jump window logic, forced wall-jump timers, stamina costs, squish safety) are extracted directly from the source.
Confirmed Behavioral Patterns to Replicate
- Corner correction: on near-miss collisions (rising jump, dash), loop through ±4 px perpendicular offsets, test for clearance, and shift the player to the first clear position. Do not fail the move; nudge it through.
- Variable-jump window:
varJumpTimerruns up to 0.2 s; a ceiling grace of 0.05 s prevents premature cancellation at the apex. The window zeroes on specific collision conditions, not on a raw timer expiry alone. - Forced wall-jump time: for 0.16 s after a wall jump, horizontal input does not override the forced 130 px/s push. This prevents immediate re-stick to the wall.
- Wall speed retention: a 0.06 s timer retains horizontal speed across wall interactions;
NormalEndresets it along withwallBoostTimerandhopWaitX. - Squish safety: if crushed, try (in order) ducking, repositioning to target, wiggle-nudging; only kill the player if all fail. Never instakill on a recoverable geometric overlap.
- Jump-through assist: one-way platforms apply a -40 (gentle upward) assist speed during pass-through.
- Dash floor snap / jump-thru nudge: after downward dashes, snap up to 3 px to the floor; horizontal dashes nudge up to 6 px through jump-throughs.
Implementation Steps
- Create the constants table first, exactly as listed. Keep it at the top of the player script as the single tuning surface (mirroring Player.cs structure).
- Implement the state machine as an enum + match, with per-state begin/update/end functions. Start with NORMAL, DASH, CLIMB; add BOOST, HIT_SQUASH, LAUNCH as encounters require.
- Implement gravity/fall tuning (apex float via HalfGravThreshold, fast-fall, MaxFall clamp) and run acceleration (RunAccel/RunReduce/AirMult).
- Implement jump + coyote time + variable jump height + jump cut on release.
- Implement wall probing (3 px), wall jump with forced-time lock, and wall slide.
- Implement dash with 8-way aim, cooldown, residual EndDashSpeed, and corner correction.
- Implement climb stamina with the three cost rates and tired threshold.
- Add forgiveness pass: upward corner correction on jump, dash nudges, jump-through assist, wall speed retention, squish-safety cascade.
- Rescale units if your game’s pixels-per-meter differs from Celeste’s native resolution: preserve ratios (e.g., DashSpeed ≈ 2.67× MaxRun; RunAccel ≈ 11× MaxRun).
Tunables
All constants in the tables above. The highest-leverage feel knobs, in order:JUMP_GRACE_TIME(coyote) andVAR_JUMP_TIME— responsiveness.RUN_ACCELvsAIR_MULT— ground crispness vs air drift.DASH_SPEED/DASH_TIME/END_DASH_SPEED— dash punch and recovery.WALL_JUMP_FORCE_TIMEandWALL_JUMP_H_SPEED— wall jump commitment.HALF_GRAV_THRESHOLD— apex float amount.
Failure Modes & Gotchas
- Skipping coyote time or variable jump makes the controller feel unfair even if every other value matches. These two forgiveness systems carry most of the “tight” perception.
- Letting horizontal input override the wall-jump force window causes players to snap back onto the wall immediately.
- Applying RunAccel in the air without AirMult gives full ground control mid-air and destroys momentum feel.
- Hard-failing near-miss collisions instead of corner-correcting (±2–6 px probes) turns visual grazes into deaths.
- Instakilling on squish — the source cascades duck → reposition → wiggle → die. Replicate the cascade.
- Treating stamina costs as per-frame instead of per-second drains the pool ~60× faster.
- Copying pixel values without rescaling if your game’s world scale differs — use ratios.
- Over-abstracting the controller. The source is deliberately one flat class with a constants table; splitting it into many components before the feel is dialed makes tuning iterations slow.
Verification
After implementing, test each forgiveness system explicitly:- Walk off a ledge and press jump up to ~100 ms later — should still jump (coyote).
- Tap vs. hold jump — distinct short and full arc heights (variable jump).
- Jump diagonally into a ceiling corner within ~4 px of clearance — should slip past, not bonk (corner correction).
- Wall jump and hold toward the wall — should still be pushed away for ~0.16 s.
- Dash into a wall edge within ~4 px — should correct rather than stop dead.
- Climb until stamina hits 0 — transition to slip/fall, not instant drop.
- Land from a dash — residual speed ≈ 160 px/s (or ×0.75 for upward), not zero.
- Get crushed by a moving platform — duck/wiggle recovery before any death.
Confidence
extracted — All tuning values, state IDs, and confirmed behavioral patterns come from Celeste’s publicly released Player.cs. Where the skeleton fills in standard platformer patterns (for example jump-cut-on-release), it is a structural translation, not extracted code. Not yet verified inside Summer Engine.
Related skills
design-mechanic: Design one mechanic in detail (input, feedback, failure modes, tunables) as a doc plus a script stub.game-feel: Add juice: hit-flash, trauma camera shake and audio ducking, one hit fires all three.debugging-game-feel: Debug features that work but feel wrong: floaty jumps, mushy combat, sluggish camera.
Source:
library/skills/celeste-momentum-platforming/SKILL.md, rendered from summer-engine@4.3.0 on npm.
