Godot Version
4.2.2
Question
Hi, everyone, i need some help, you see, im trying to add to my game a knockback effect, like those you see in some old games, like megaman, i already posted a question about the same proyect, but I ran into another problem, the character detects the knockback two times, so what happens is that I can crash with the enemy, while I walk, he throws me back, but if I press jump, the throwing effect is applied again, this also happens if for example the enemy walks towards me, he throws me, but if I press walk, he throws me again., i dont know if is because the states of the state machine or something, like it detects, the same colision for all the states, i tried to lock it using a global boolean variable to lock this, but it dont work, this is the code of the state machine:
class_name CharacterStateMachine
extends Node
@export var rising_gravity : int = 15
@export var fast_falling_gravity : int = 20
@export var _character : CharacterBody2D
@export var current_state : State
var _states : Array[State]
func _ready():
for child in get_children():
if (child is State):
_states.append(child)
child._character = _character
else:
push_warning("Child " + child.name + "is not in State for this Character")
func _physics_process(delta):
if(current_state.next_state != null):
switch_states(current_state.next_state)
current_state.state_process(delta)
func check_if_can_move():
return current_state.can_move
func switch_states(new_state : State):
if(current_state != null):
current_state.on_exit()
current_state.next_state = null
current_state = new_state
current_state.on_enter_state()
func check_if_can_jump():
return current_state.can_jump
func check_if_is_stunned():
return current_state.can_be_stunned
func apply_gravity():
if(current_state.apply_gravity):
if(!_character.is_on_floor()):
_character.velocity.y += rising_gravity
if(_character.velocity.y > 0):
_character.velocity.y += fast_falling_gravity
_character.move_and_slide()
func check_if_can_be_stunned():
return current_state.can_be_stunned
func _input(_event : InputEvent):
current_state.state_input(_event)
and this for example is the air state, where it detects the colision two times:
class_name AirState
extends State
@onready var lurker_enemy = get_tree().get_first_node_in_group("Enemies")
@export var brax_actions_animation_player : AnimationPlayer
@export var brax_state_machine_functions : CharacterStateMachine
@export var brax_sprite : Sprite2D
@export var idle_state : State
@export var walking_state : State
@export var attack_state : State
@export var stunned_state : State
func state_process(delta):
_apply_state_gravity()
_movement_mid_air()
_when_on_floor_after_fall()
func state_input(_event : InputEvent):
if (_character.velocity.y < 0 and _event.is_action_released("JUMP")):
_character.velocity.y *= 0.5
elif _event.is_action_pressed("NORMAL_ATTACK"):
_attack()
func _apply_state_gravity():
brax_state_machine_functions.apply_gravity()
func _when_on_floor_after_fall():
if _character.is_on_floor():
if _character.velocity == Vector2.ZERO:
next_state = idle_state
elif Input.is_action_pressed("RIGHT"):
next_state = walking_state
elif Input.is_action_pressed("LEFT"):
next_state = walking_state
func _attack():
brax_actions_animation_player.play("air_attack")
next_state = attack_state
func _movement_mid_air():
if brax_state_machine_functions.check_if_can_move():
if Input.is_action_pressed("RIGHT"):
brax_sprite.flip_h = false
_character.velocity.x = mid_air_speed
elif Input.is_action_pressed("LEFT"):
brax_sprite.flip_h = true
_character.velocity.x = -mid_air_speed
elif Input.is_action_just_released("RIGHT"):
_character.velocity.x = 0
elif Input.is_action_just_released("LEFT"):
_character.velocity.x = 0
func _on_getting_hit_body_entered(body):
if body == lurker_enemy:
next_state = stunned_state
func _on_getting_hit_body_exited(body):
if body == lurker_enemy:
can_be_stunned = false
and this one is the walk state:
class_name WalkingState
extends State
#Enemigos que seran detectados por el jugador
@onready var lurker_enemy = get_tree().get_first_node_in_group("Enemies")
@export var brax_state_machine_functions : CharacterStateMachine
@export var brax_sprite : Sprite2D
#Estados Cambio
@export var idle_state : State
@export var air_state : State
@export var dash_state : State
@export var attack_state : State
@export var stunned_state : State
@export var brax_jump_sound_effect : AudioStreamPlayer2D
@export var brax_actions_animation_player : AnimationPlayer
func state_process(delta):
_apply_state_gravity()
_walk()
_stop_walk()
_after_falling_of_a_platform()
_attack_while_walking()
func state_input(_event : InputEvent):
if (_event.is_action_pressed("JUMP") and brax_state_machine_functions.check_if_can_jump()):
_jump()
if (Input.is_action_pressed("RIGHT") and _event.is_action_pressed("DASH")):
next_state = dash_state
if (Input.is_action_pressed("LEFT") and _event.is_action_pressed("DASH")):
next_state = dash_state
func _walk():
if brax_state_machine_functions.check_if_can_move():
if Input.is_action_pressed("RIGHT"):
brax_sprite.flip_h = false
_character.velocity.x = walk_speed
if Input.is_action_pressed("LEFT"):
brax_sprite.flip_h = true
_character.velocity.x = -walk_speed
func _stop_walk():
if (Input.is_action_just_released("RIGHT") and not _character.velocity.x < 0):
_character.velocity = Vector2.ZERO
elif (Input.is_action_just_released("LEFT") and not _character.velocity.y > 0):
_character.velocity = Vector2.ZERO
elif _character.velocity == Vector2.ZERO:
next_state = idle_state
func _apply_state_gravity():
brax_state_machine_functions.apply_gravity()
func _after_falling_of_a_platform():
if _character.velocity.y > 0 :
next_state = air_state
func _attack_while_walking():
if Input.is_action_just_pressed("NORMAL_ATTACK"): #Detener el movimiento mientras brax ataca al moverse
_character.velocity.x = 0
next_state = attack_state
func _jump():
brax_jump_sound_effect.play()
_character.velocity.y = base_jump_height
next_state = air_state
func _on_getting_hit_body_entered(body):
if body == lurker_enemy:
next_state = stunned_state
func _on_getting_hit_body_exited(body):
if body == lurker_enemy:
next_state = idle_state
i would appreciate the help, seriously, thanks