Godot Version
Godot 3.5
Question
`I am currently attempting to implement a chain dash for my character in an ARPG that I am making. After implementing the current code, I ran into the problem that when the player dashes in a specific direction they animation does not stop. I used the following YouTube tutorial to help build out the initial structure and the HeartBeast ARPG tutorial for the base structure. Can someone help me figure where I went wrong with my implementation?
Tutorial: Perform multiple attacks with the same input! (Godot 3.0.6)
extends KinematicBody2D
export var MAX_SPEED = 55
export var ACCELERATION = 435
export var FRICTION = 425
export var DASH_SPEED = 2030
enum {
MOVE,
DASH,
DASH2,
DASH3
}
onready var animationPlayer = $AnimationPlayer
onready var animationTree = $AnimationTree
onready var animationState = animationTree.get("parameters/playback")
var state = MOVE
var velocity = Vector2.ZERO
var dash_vector = Vector2.DOWN
var DashPoints = 3
func _ready():
animationTree.active = true
func _physics_process(delta):
match state:
MOVE:
move_state(delta)
DASH:
Dash_state(delta)
func move_state(delta):
var input_vector = velocity
input_vector.x = Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left")
input_vector.y = Input.get_action_strength("ui_down") - Input.get_action_strength("ui_up")
input_vector = input_vector.normalized()
if input_vector != Vector2.ZERO:
dash_vector = input_vector
animationTree.set("parameters/Idle/blend_position", input_vector)
animationTree.set("parameters/Run/blend_position", input_vector)
animationTree.set("parameters/Dash/blend_position", input_vector)
animationState.travel("Run")
velocity = velocity.move_toward(input_vector * MAX_SPEED, ACCELERATION * delta)
else:
animationState.travel("Idle")
velocity = velocity.move_toward(Vector2.ZERO, FRICTION * delta)
move()
if Input.is_action_just_pressed("dash") && DashPoints == 3:
$DashResetTimer.start()
state = DASH
DashPoints == DashPoints - 1
elif Input.is_action_just_pressed("dash") && DashPoints == 2:
$DashResetTimer.start()
state = DASH2
DashPoints == DashPoints - 1
elif Input.is_action_just_pressed("dash") && DashPoints == 1:
$DashResetTimer.start()
state = DASH3
DashPoints == DashPoints - 1
func move():
velocity = move_and_slide(velocity)
func Dash_state(delta):
velocity = dash_vector * DASH_SPEED
animationState.travel("Dash")
move()
func Dash_state2(delta):
velocity = dash_vector * DASH_SPEED
animationState.travel("Dash2")
move()
func Dash_state3(delta):
velocity = dash_vector * DASH_SPEED
animationState.travel("Dash3")
move()
func Dash_animation_finished():
if animationState.get("Dash") || animationState.get("Dash2"):
velocity = Vector2.ZERO #this will stop the player from sliding after the dash
state = MOVE
elif animationState.get("Dash3"):
velocity = Vector2.ZERO
state = MOVE
func _on_DashResetTimer_timeout():
DashPoints = 3
When is “Dash_animation_finished()” called?
It is called on a Method track in the animationplayer
Can you put print statements in the if-clauses inside the dash_animation_finished-method to check if they are being called?
So, I changed my approach to implementing the dash. instead of multiple states i put the dash on a timer that resets if the player presses the dash key when the animation is finished. i know its spaghetti code but it works for now. I’m open to critiques to better streamline the code
extends KinematicBody2D
export var MAX_SPEED = 55
export var ACCELERATION = 435
export var FRICTION = 425
export var DASH_SPEED = 1000
export var DASH_COOLDOWN = 1.0 #cooldown timein seconds
enum {
MOVE,
DASH,
DASH2,
DASH3
}
onready var animationPlayer = $AnimationPlayer
onready var animationTree = $AnimationTree
onready var animationState = animationTree.get("parameters/playback")
onready var dashResetTimer = $DashResetTimer
var state = MOVE
var velocity = Vector2.ZERO
var dash_vector = Vector2.DOWN
var dashPoints = 1
var can_dash = true #flag to manage dash availabilty
func _ready():
animationTree.active = true
dashResetTimer.wait_time = DASH_COOLDOWN
dashResetTimer.one_shot = true
func _physics_process(delta):
match state:
MOVE:
move_state(delta)
DASH:
Dash_state(delta)
func move_state(delta):
var input_vector = velocity
input_vector.x = Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left")
input_vector.y = Input.get_action_strength("ui_down") - Input.get_action_strength("ui_up")
input_vector = input_vector.normalized()
if input_vector != Vector2.ZERO:
dash_vector = input_vector
animationTree.set("parameters/Idle/blend_position", input_vector)
animationTree.set("parameters/Run/blend_position", input_vector)
animationTree.set("parameters/Dash/blend_position", input_vector)
animationState.travel("Run")
velocity = velocity.move_toward(input_vector * MAX_SPEED, ACCELERATION * delta)
else:
animationState.travel("Idle")
velocity = velocity.move_toward(Vector2.ZERO, FRICTION * delta)
move()
if Input.is_action_just_pressed("dash"):
if state == DASH:
#if already dashing, check if the animation is done
if !animationState.is_playing():
#Reset dash Points and cooldown timer if already dashing
dashResetTimer.stop() #stop the timer
dashResetTimer.start() #Restart the timer
dashPoints = 1 #Reset dash Points
elif can_dash and dashPoints > 0:
start_dash()
func move():
velocity = move_and_slide(velocity)
func start_dash():
state = DASH
dashPoints += 1 #addpoints to get another dash
dashPoints -= 1 #take pointe to help loop dash
can_dash = false
dashResetTimer.start()
func Dash_state(delta):
velocity = dash_vector * DASH_SPEED
animationState.travel("Dash")
move()
func _on_DashResetTimer_timeout():
dashPoints = 1
can_dash = true
state = MOVE # Return to MOVE state after dash cooldown
func Dash_animation_finished():
if state == DASH:
velocity = Vector2.ZERO
state = MOVE
can_dash = true
if Input.is_action_just_pressed("dash") and dashPoints > 0:
start_dash() #start another dash if the dash key is pressed again
It looks cleaner then your last code.
So it works now?