Attention | Topic was automatically imported from the old Question2Answer platform. | |
Asked By | arthurZ |
I have this script that is working fine, except for the attack animation which I believe is being overridden by the idle or running animations. The attack animation is only showing the first frame every time I press Ctrl and then goes to idle or run animations. Any tips on how to fix this?
extends KinematicBody2D
onready var ground_ray = get_node("ground_ray")
onready var ground_ray2 = get_node("ground_ray2")
onready var anim = get_node("AnimationPlayer")
const UP = Vector2(0, -1)
const GRAVITY = 10
const ACCELERATION = 50
const MAX_SPEED = 180
const JUMP_HEIGHT = -380
var motion = Vector2()
var acc = Vector2()
func _physics_process(delta):
motion.y += GRAVITY
var friction = false
acc.x = int(Input.is_action_pressed("ui_right")) - int(Input.is_action_pressed("ui_left"))
if acc.x == 1:
$Sprite.flip_h = false
motion.x = min(motion.x+ACCELERATION, MAX_SPEED)
if anim.current_animation != "run" && (ground_ray.is_colliding() || ground_ray2.is_colliding()):
anim.play("run")
elif acc.x == -1:
$Sprite.flip_h = true
motion.x = max(motion.x-ACCELERATION, -MAX_SPEED)
if anim.current_animation != "run" && (ground_ray.is_colliding() || ground_ray2.is_colliding()):
anim.play("run")
else:
if anim.current_animation != "idle" && (ground_ray.is_colliding() || ground_ray2.is_colliding()):
anim.play("idle")
friction = true
if Input.is_action_just_pressed("ui_up") && (ground_ray.is_colliding() || ground_ray2.is_colliding()):
motion.y = JUMP_HEIGHT
if (ground_ray.is_colliding() || ground_ray2.is_colliding()):
if friction == true:
motion.x = lerp(motion.x, 0, 0.2)
if Input.is_action_just_pressed("ui_ctrl"):
if anim.current_animation != "combo 1":
anim.play("combo 1")
else:
if motion.y <= JUMP_HEIGHT*0.45:
if anim.current_animation != "jump":
anim.play("jump")
if motion.y >= 0:
motion.y += 8
if motion.y >= JUMP_HEIGHT*0.45 && motion.y <= JUMP_HEIGHT*(-0.45):
if anim.current_animation != "maxHeight":
anim.play("maxHeight")
if motion.y > JUMP_HEIGHT*(-0.45):
if anim.current_animation != "fall":
anim.play("fall")
if friction == true:
motion.x = lerp(motion.x, 0, 0.2)
motion = move_and_slide(motion, UP)
I think the problem is that after you attacked, the next time you enter physics process you will met other cases and another animation will start. For example, you press control, so play attack animation, but in next physics process call process call, idle conditions met, so idle is run.
Another thing, Have you tried changing all this:
if Input.is_action_just_pressed("ui_ctrl"):
if anim.current_animation != "combo 1":
anim.play("combo 1")
for this:
if Input.is_action_just_pressed("ui_ctrl"):
anim.current_animation = "combo 1"
You can set animations like that so you don’t have to check if animation is already being played.
For your problem, i think you should ad abool variable like is_attacking
which you set to true when start the attack animation, and set to false when finish. If is attacking, then don’t try to change animation.
p7f | 2019-01-21 12:00
Hi. I set the flag attack and changed the if statements, the combo animation works now, but can be stopped at any time. Do you know how I can prevent “combo 1” animation from being interrupted? Any Animation Player command? Thank you for your response.
arthurZ | 2019-01-21 15:18
Can you share me the project so i see in depth? I would use tha atack flag to prevent any other animations to be loaded, and connect animation finished signal to a function that, if the animation finished was the attack, then se attack flag to false.
p7f | 2019-01-21 15:23
Here are the last changes. The combo 1 animation is playing almost well, the only problem is that if I press Ctrl again it restart the combo 1 animation.
extends KinematicBody2D
onready var ground_ray = get_node("ground_ray")
onready var ground_ray2 = get_node("ground_ray2")
onready var anim = get_node("AnimationPlayer")
const UP = Vector2(0, -1)
const GRAVITY = 10
const ACCELERATION = 50
const MAX_SPEED = 180
const JUMP_HEIGHT = -380
var motion = Vector2()
var acc = Vector2()
var attack = false
func _physics_process(delta):
motion.y += GRAVITY
var friction = false
acc.x = int(Input.is_action_pressed("ui_right")) - int(Input.is_action_pressed("ui_left"))
if acc.x == 1 && !attack:
$Sprite.flip_h = false
motion.x = min(motion.x+ACCELERATION, MAX_SPEED)
if anim.current_animation != "run" && (ground_ray.is_colliding() || ground_ray2.is_colliding()):
anim.play("run")
elif acc.x == -1 && !attack:
$Sprite.flip_h = true
motion.x = max(motion.x-ACCELERATION, -MAX_SPEED)
if anim.current_animation != "run" && (ground_ray.is_colliding() || ground_ray2.is_colliding()):
anim.play("run")
else:
if anim.current_animation != "idle" && !attack && (ground_ray.is_colliding() || ground_ray2.is_colliding()):
anim.play("idle")
friction = true
if Input.is_action_just_pressed("ui_up") && anim.current_animation != "combo 1" && (ground_ray.is_colliding() || ground_ray2.is_colliding()):
motion.y = JUMP_HEIGHT
if (ground_ray.is_colliding() || ground_ray2.is_colliding()):
if friction == true:
motion.x = lerp(motion.x, 0, 0.2)
if Input.is_action_just_pressed("ui_ctrl"):
attack = true
anim.play("combo 1")
yield(anim, "animation_finished")
attack = false
else:
if motion.y <= JUMP_HEIGHT*0.45:
if anim.current_animation != "jump":
anim.play("jump")
if motion.y >= 0:
motion.y += 8
if motion.y >= JUMP_HEIGHT*0.45 && motion.y <= JUMP_HEIGHT*(-0.45):
if anim.current_animation != "maxHeight":
anim.play("maxHeight")
if motion.y > JUMP_HEIGHT*(-0.45):
if anim.current_animation != "fall":
anim.play("fall")
if friction == true:
motion.x = lerp(motion.x, 0, 0.2)
motion = move_and_slide(motion, UP)
arthurZ | 2019-01-21 17:34
hi:
Change anim.play("combo 1")
by `anim.current_animation = “combo 1”. Have you tried that?
If not you can check current animation as you did before.
p7f | 2019-01-21 17:41
This worked very well. Do you think yield works as good as signal to notified about finished animation? Thanks again man.
if Input.is_action_just_pressed("ui_ctrl"):
attack = true
anim.current_animation = "combo 1"
yield(anim, "animation_finished")
attack = false
arthurZ | 2019-01-21 17:57
I think in this case yield is better! We should post an answer so this does not remain unsolved, and then you should select it. Would you do it, so you can add the finished version of the code? Or you prefer me to do so?
p7f | 2019-01-21 18:01
You can make it. Thanks.
arthurZ | 2019-01-21 18:12
hey, i think that if you use yield, you don’t need attack flag anymore… can you please test it?
p7f | 2019-01-21 18:15
I test it, and without attack flag we comeback to the first issue, the combo 1 animation just plays the first frame and the idle or run animation overrides it. I just don’t understand why it overrides if I am using the anim.current_animation = "combo 1"
to avoid it.
arthurZ | 2019-01-21 18:44