derkork / godot-statecharts

A state charts extension for Godot 4
MIT License
761 stars 39 forks source link

Confussion about best practices implementing JumpBuffer #134

Closed mycroftsnm closed 1 month ago

mycroftsnm commented 1 month ago

Hi, this is not really an issue but a question about the best way to implement JumpBuffer in a 2dPlatformer

I have a parallel state with Movement and Jump Status (let ignore the dash for simplification), i do this in that way because i need to track the if the player can jump independently of the player being grounded. can jump at any time once until its grounded or touchs the enemys head.

image

image

So, when the player jumps, The JumpStatus compound switches to 'Can Not Jump' state, and if try to jump again it transition to the JumpBuffered state, which has 'expiration' transition to falling and a transition to jump with Guard being 'Can Jump' enabled, my idea is: if its on Jump Buffered and suddenly its allowed to jump (either by grounded or touch enemys head) Do Jump auto.

But its not working, probably because when landing it transition to Grounded so its not in JumpBuffered anymore, but i dont get how to implement it well using statecharts and without adding a lot of condition.

The other way is to implement via code, setting a variable jump_buffer = 0.3, decreasing it by delta every frame and when entering CanJump state send 'jump' event if jump_buffer > 0.0 , but i think thats a ''hacky'' way if im using stateChart i should do all the logic with states, right?

I would really like to make everything with stateChart, i readed the manual and statecharts.dev entirely and i think is a really good way of working, but i constantly feel like i dont really understand how to implement it well, Thanks :)

derkork commented 1 month ago

Given the requirements above I would probably go with something like this:

image

We have Jump Control state which controls the whole jumping affair. This has two sub-states one Can Jump which is active whenever the player can jump. We only will process jump inputs in this state (similar to how it is done in the Ninja Frog Demo). To avoid having to add a ton of transitions to each of the sub-states, we add most transitions to the Jump Control as these transitions apply no matter in which sub-state the player currently is. So whenever the player is grounded we will transition to Jump Anytime no matter where we are. Whenever we get airborne or touch a mole's head, we transition to Jump within 0.3s (our jump buffer) no matter where we are. Similarly, whenever we jump, we move to the Cannot Jump state and the player cannot jump anymore.

Finally you notice another transition on the hit_mole_head event when we are int he Jump within 0.3s state. This isn't really needed because we already have a transition on the outermost Jump Control state that can handle this. However you said you wanted to automatically jump when you hit a mole head while being in the jump buffer state and this is a way to do this. The state chart library will try to run transitions depth-first, so it will first look at the innermost active state if a matching transition is available and then work upwards. So the library will take this inner transition when you are in the jump buffer state and hit a mole head. Now we can add a subscription to the taken signal on this transition to trigger the auto jump, so whenever this transition is taken, we run code that automatically lets the player jump.

If stuff is set up this way, the only thing our code needs to do is sending events when the player gets airborne, hits a molehead, lands or jumps. Also we implement jumping by subscribing to the state_processing or state_input signals and then checking for jump input only when we are in the Can Jump state. Finally we need to add a handler for the taken signal of our extra transition to implement the auto-jump.

mycroftsnm commented 1 month ago

Thank you so much for your explanation, i explained myself very badly , with bufferJump i was referring to the situation when you press the jump button before being able to jump. However your approach taught me and my brain clicked, so i adapted it to my requirements (and it worked) :)

image

So we can close the issue, thanks for this amazing plugin and for your help.

btw, which software do you use to make those diagrams? looks clean and help me a lot

derkork commented 1 month ago

The diagrams are made with Excalidraw - its free and works directly in the browser. There is also an addon for Obsidian if you happen to use that.