AI Game Dev

Coyote time: the jump fix players never notice

To show the difference, we started from our double-jump game with coyote time switched off. Claude Code turned it on and tested it. Play both versions and see what we measured.

Tested with Phaser 3.80.1 · Claude Code 2.1.311

A frame from the platformer. The orange square has just run off the right edge of the lowest platform and hangs slightly below its top, the moment a coyote jump is still allowed. Five platforms with yellow coins sit around it.

Before you start

  • The platformer from the double jump tutorial, or any Phaser platformer of your own.
  • Claude Code, started in the game's folder.
  • The skill at the end of this page, in the folder's .claude/skills/platformer-feel/. Then type the prompt below.
What we asked“Add coyote time to the jump, so I can still jump for a moment after running off a ledge. Test it.”

What happened

You
Add coyote time to the jump, so I can still jump for a moment after running off a ledge. Test it.
  • Used the platformer-feel skill
  • Read the skill's notes on coyote time and testing
  • Read index.html
  • Checked that Playwright and headless Chrome work
Claude
Coyote time is already implemented. It's disabled because COYOTE_TIME = 0, so all I need to change is the value. Every other timer in this file is in ms, so I'll keep ms to match.
  • Changed COYOTE_TIME from 0 to 100
Claude
Next, a scripted Playwright test that drives the real page. It runs off a ledge and presses jump at fixed delays after the last frame on the ground.
  • Wrote tests/coyote.test.js
  • First runs: the test pressed jump before the ledge, then timed out with coyote time off
  • Fixed the test twice
  • Ran it 3 times with 100 ms and with 0 ms: all checks pass, no console errors
Claude
Coyote time now works: you can still jump for 100 ms (0.1 s) after running off a ledge. The game already had the code for it, but it was switched off (COYOTE_TIME = 0). The fix is one line: COYOTE_TIME = 100. I kept it in ms like the other timers in the file, such as JUMP_BUFFER = 110. 100 ms is the usual default; anything from about 60 to 150 ms works, and longer starts to feel floaty. The test opens the real game in a headless browser, runs the player off a ledge, and presses Space a set time after the last frame on the ground. With 100 ms, a press about 67 ms after the ledge gives a full ground jump and keeps the double jump. A press about 217 ms after only gets the air jump. Jumping and pressing again 50 ms later gives the air jump, not a second ground jump. With 0 ms, the 67 ms press only gets the air jump, so the test fails with coyote time off. The '50 ms' press lands at about 67 ms because of a frame of input delay. The existing code already measures time instead of frames, clears the timer on every jump, and counts a coyote jump as a ground jump, so your double jump is kept. Jump buffering (110 ms) and tap-for-a-small-hop were already in the game, so I left them alone.

To show the difference, we started from our double-jump game with coyote time switched off.

Coyote time lets you jump for a short moment after you run off a ledge. You press jump when your eyes say you’re at the edge, and the game gives you that jump even though the square has already left the ground.

In the demo below, the tinted strip past the edge is the ground coyote time adds: 0.10 s at the game’s run speed of 260 px/s, or 26 px.

An explainer we built for this page. Press jump a moment after the square leaves the edge, with coyote time on and then off; slow motion makes it easier to see. The two games below are the real ones from the Claude Code session.

The game from the double jump tutorial had coyote time from the start, at 90 ms. We set it to 0 and changed nothing else. Standing jumps still worked, at the same 107 px. Then we asked Claude Code, with the platformer-feel skill, to add coyote time.

To try it, run off the edge of a platform and press jump a moment late.

Before: coyote time off. A late press only gets the weaker air jump, and your double jump is gone.

After: Claude's version. The same press is a full ground jump, and you can still double jump. For both games we only added the start screen and loaded Phaser from this site.

We measured both versions ourselves with Playwright in headless Chrome. The square stands on the lowest platform, runs right off its edge, and we press jump a set time after the last frame it was on the ground. We ran each case three times and got the same result every time.

Press after leaving the ledgeBeforeAfter
0.05 sAir jump (500 px/s up), double jump used upGround jump (560 px/s up), double jump kept
0.20 sAir jump, double jump used upAir jump, double jump used up

Claude picked COYOTE_TIME = 100 ms, the skill’s default of 0.10 s. The skill gives 0.06 to 0.15 s as the good range and says longer feels floaty. Claude kept milliseconds because every other timer in the file uses them, though the skill asks for seconds. The rest of the coyote code was already in the game: the timer runs on real time, every jump clears it, and a coyote jump counts as a ground jump. So the change was one number.

Get the skill. It also covers jump buffering and variable jump height.

Recorded with a clean Claude Code: no personal skills, plugins or MCP servers, just the skill on this page.

The skill that made it work

It tells Claude what coyote time should and shouldn't allow, and to test it with scripted presses, once with it on and once with it off.

platformer-feel
  1. Keep every movement number as a named constant at the top of the player code, in seconds and pixels per second (not frames), so the user can tune them.
  2. Add the three core helpers unless the user says not to: coyote time (a short moment to still jump after running off a ledge), jump buffering (a jump pressed just before landing still happens on landing) and variable jump height (tap for a small hop, hold for a full jump). Read each helper's reference file before you build it.
  3. Test with scripted input, not by reading the code. Each helper needs one test that fails without it and passes with it.
  4. When you finish, list each helper with its number and what the test showed, in plain words.

Save it as .claude/skills/platformer-feel/SKILL.md in your project.

Was this useful?