|
|
|
|
Reply From: |
Midonk |
Hey there, for a more robust (but more complex) statemachine, I recommand you this article. No more booleans, a clean design pattern, this is the elegant way you’re looking for
Hi, thanks for taking the time to answer my question. Unfortunately, I am already using this exact state machine, but it doesn’t solve the problem I described in my original question.
It is true, that you don’t need flags in such a state machine when dealing with simple states like MOVE and JUMP, but the states in my game often contain a longer sequence of instructions between actions that have to be looped and actions that should only be called once. The internet is full of questions about “how to run code only once” and the general answer seems to be" use a boolean flag". This method does indeed work, but I hoped or suspected that there might be a different solution that I cannot see due to my lack of experience.
what kind of behaviour do you wish to create that needs loops and everything ?
Midonk | 2022-01-05 12:09
For example, what I wrote in my original question. Movement of the enemy to the current player position has to be handled inside a process or physics process loop, or it won’t move the full distance. But when the enemy arrives and attacks the player, the attack and deduction of the player’s health should happen only once.
Here is the actual code of the “Enemy Attack State” in the turn based Battle Statemachine:
if enemy.position.distance_to(player) > 30:
enemy.move_and_slide(enemy.velocity)
if enemy.position.distance_to(player) < 30:
if executed_once == false:
enemy.attack_position = _enemy.position
var _applied_dmg = enemy.stats.dmg_dealt - player.armor
if _applied_dmg > 0:
player.TakeDamage(_applied_dmg)
else:
player.TakeDamage(0)
enemy.play_attack_animation()
executed_once = true
yield(enemy.animationplayer,"animation_finished")
battlemode.transition_to("EnemyReturn")
In this example, movement has to be in the loop, TakeDamage() and the call to start the attack animation may only be performed once, and the yield afterwards only works when it’s in the loop again (otherwise executed_once = true gets postponed and the whole thing breaks).
Maybe you didn’t understand well the state pattern ? You should split your logic into 1 state Move
and another Attack
. The thing is you could move toward the player then, when another “component” of your logic detect that the player is close enough, the statemachine is requested to switch to Attack
state and imadiately after the state end, the state goes back to Move
Understand that ONE state should make ONE thing
Midonk | 2022-01-05 20:07
Ok, thanks for clarifying. That is the way I use a state machine for my main character’s movement and simple states. The battle state machine has about 15 states already, so I guess I either have to split it up even more or continue using flags.