[5.4.9] Implementing "Coyote Time": Ensuring Smooth Platform Jumping Even at the Last Second

dale_coop

Moderator
Staff member
Have you ever encountered that frustrating scenario where you're sprinting toward the platform's edge, fully aware that you need to jump, and you indeed press the A button at the very last moment, but still find yourself plummeting? It's as though the game failed to acknowledge your input. What an exasperating experience!

It's precisely for this particular situation that modern games incorporate the "coyote time," allowing the jump button to be registered a few frames after your character has left the platform. This not only enhances the gameplay experience but also fosters a greater sense of fairness.

In this tutorial, I will explain a straightforward method to implement the "coyote time" feature in your platformer game:

coyoteTime.gif
(the Player can still jump a few frames after leaving the platform)



0) BACKUP YOUR PROJECT (optional but important)

Before every big modification, new feature implementation, in your project, it's very important to backup your NESmaker project.
Select the NESmaker folder and copy/paste it. Then rename the new folder adding today's date for example.



1) COYOTE TIMER VARIABLE

In the "Project Settings > User Variables", add a "coyoteTimer" with an initial value "0":

2023-10-01 12_28_31-Project Settings.png



2) HANDLE GAME TIMER

In the "Project Settings > Script Settings", edit the Handle Game Timer script and add that block of code:
Code:
    LDA coyoteTimer
    BEQ +continue
        DEC coyoteTimer
    +continue:

Note: if your Handle Game Timer is blank, you can either create a new script and assign it to the Handle Game Timer element... or choose to add that code in the "Sprite Post-draw" or "Sprite Pre-draw" instead of the "Handle Game Time" script.



3) COYOTE TIMER PHYSICS

In the "Project Settings > Script Settings", edit the Handle Physics script, locate the "isSolidSoLand:" line (near the end of the script)... and just AFTER that line, add that block of code:
Code:
    CPX player1_object
    BNE +skip
        LDA #$06  ;; here, the delay of the Coyote Time
        STA coyoteTimer
    +skip:

Your script should look like that, now:
2023-10-01 16_51_55-● doHandlePhysics_PlatformBase_fixedAndSeamFix.asm - Visual Studio Code.png
Note: of course, I used 06 (frames) because it feels good for my project. You can try different small values to see how it feels.



4) JUMP ON COYOTE TIMER

Lastly, in your Scripts > Input Scripts, edit your Jump input script, locate the "JMP +skipJumping" line (near the last part of the script) and just BEFORE that line, add:
Code:
    LDA coyoteTimer
    BEQ +continue
        LDA #$00
        STA coyoteTimer
        JMP +doJump
    +continue:

Your code should look like that, now:
2024-02-22 11_10_32-Window.png

Voilà, now you the last second jump should feel better!

Don't hesitate to tweak that feature for your needs (the code we added in the Physics, the “#$06" can be adjusted as you want).
Also, maybe some initializations (LDA #$00 STA coyoteTimer will be needed in your handle hurt script or in the handle screen loads... you'll see, depending of your projects)
 
Last edited:

Jonny

Well-known member
Thanks Dale. I'm hoping this might also solve that my jumping on the spot feels a bit hit and miss too. Might be something else though, will see...
 

dale_coop

Moderator
Staff member
Thanks Dale. I'm hoping this might also solve that my jumping on the spot feels a bit hit and miss too. Might be something else though, will see...
It should, yes. When I added that, for the first tome, to my son's game KUBO3 (who has a ton of difficult/hazardous plateform jumps), it was like night and day.
 
just tried implementing this in metroidvania, but it comes up with this




D:\nesmaker\NESmaker_4_5_9\NESmaker_4_5_x\GameEngineData>asm6 MainASM.nes game.nes demo.txt
pass 1..
GameData/Variables/UserVariables.asm(12): Illegal instruction.
GameData\InitializationScripts\hudVarInits.asm(17): Illegal instruction.
demo.txt written.

D:\nesmaker\NESmaker_4_5_9\NESmaker_4_5_x\GameEngineData>pause
Press any key to continue . . .


might this only be for the platformer module?
 

Jonny

Well-known member
What's on line (12) and line (17)? I had this error recently and unfortunately I forgot what it was! Could be something like having the same variable name in userVariables and zeropage. I'll try to remember what it was...
 

dale_coop

Moderator
Staff member
just tried implementing this in metroidvania, but it comes up with this




D:\nesmaker\NESmaker_4_5_9\NESmaker_4_5_x\GameEngineData>asm6 MainASM.nes game.nes demo.txt
pass 1..
GameData/Variables/UserVariables.asm(12): Illegal instruction.
GameData\InitializationScripts\hudVarInits.asm(17): Illegal instruction.
demo.txt written.

D:\nesmaker\NESmaker_4_5_9\NESmaker_4_5_x\GameEngineData>pause
Press any key to continue . . .

might this only be for the platformer module?

Looks like you have an incorrect user variable name (make you sure you didn't use any space character or special character)... also you might have the same issue in your HUD elements.
 

Jonny

Well-known member
Works great. Just wondering, did you implement anything else so player has a buffer before reaching ground where they can still jump? I noticed on SkateCat you can almost double jump slightly if you're almost, but not quite touching the ground.

I'm using varJump and jumpThroughPlatform.
 

dale_coop

Moderator
Staff member
For SkateCat, I modified the jump script to check the ground further away (the CheckCollisionPoint line)... because Seiji wanted to be able to do (and not do) a few things during the game.
 

Jonny

Well-known member
For SkateCat, I modified the jump script to check the ground further away (the CheckCollisionPoint line)... because Seiji wanted to be able to do (and not do) a few things during the game.
I tried SBC some from temp1 which should be Y axis. I couldn't make it any different. I've added some input scripts for HOLD A so player jumps continuously when held. Seems ok, but still testing how that feels.
 

dale_coop

Moderator
Staff member
In fact, you shouldn't SBC, but rather ADC a greater value to temp1 (like that it will check further/deeper/sooner for the solid ground tiles).
 

dale_coop

Moderator
Staff member
I noticed an issue with the One Way Solid tiles that don't work anymore.
I managed to fix that, in the Step 4, you need to place the code, not after the "SwitchBank #$1C" line but BEFORE the "JMP +skipJumping" line (around the last part of the script).

I updated the tutorial.
 
Top Bottom