|
|
|
|
Reply From: |
bloodsign |
You can go to your AnimationPlayer node. On the right panel of Godot Editor, right next to the [Inspector] Tab, there’s a [Node] Tab.
You should see a list of Signals under there. If you select AnimationPlayer node on your scene tree, you will see a signal on that list named:
animation_finished(anim_name:String)
Double click on it to open a new window and connect it to your script on your scene tree.
It should create a function inside your script.
func _on_AnimationPlayer_animation_finished(anim_name):
pass
This function gets called everytime an animation is finished (if it’s not on loop- I think)
from there you can do something like:
func _on_AnimationPlayer_animation_finished(anim_name):
match anim_name:
"attack":
can_idle = true
#EDIT: On second note,
if Input.is_action_just_pressed("attack"):
can_idle == false
$AnimationPlayer.play("attack")
yield($AnimationPlayer, "animation_finished")
can_idle == true
Why is your can_idle line of code using double equals? That’s for comparing and not assigning.
Shouldn’t it be:
can_idle = false
can_idle = true
Thanks for helping me! I solved it by doing what you said. But I don’t understand why that match thing on func _on_AnimationPlayer_animation_finished
.can solve overriding problems.
Edit: it is not about what I want, but what if I want to attack while I am not on the floor? (in other words, while in the air) When I attack in the air, jumping motion overrides attacking motion( now I blocked attacking while in the air.).
Here is my code that I changed some:
extends KinematicBody2D
const UP = Vector2(0, -1)
const gravity = 15
const speed = 100
const jump = -300
const accel = 20
var motion = Vector2()
var facing_right = true
var can_idle = true
func _on_AnimationPlayer_animation_finished(anim_name):
match anim_name:
“attack”:
can_idle = true
func _physics_process(_delta):
motion.y += gravity
var friction = false
motion.x = clamp(motion.x, -speed, speed)
if facing_right == true:
$Sprite.scale.x = 1
else:
$Sprite.scale.x = -1
if Input.is_action_pressed("right") && can_idle == true:
motion.x += accel
facing_right = true
$AnimationPlayer.play("run")
elif Input.is_action_pressed("left") && can_idle == true:
motion.x -= accel
facing_right = false
$AnimationPlayer.play("run")
else:
if can_idle == true:
$AnimationPlayer.play("idle")
motion.x = lerp(motion.x, 0, 0.2)
if is_on_floor():
if Input.is_action_pressed("jump"):
motion.y = jump
if Input.is_action_just_pressed("attack"):
can_idle = false
$AnimationPlayer.play("attack")
motion.x = lerp(motion.x, 0, 0.95)
yield($AnimationPlayer, "animation_finished")
can_idle = true
else:
if motion.y < 0:
$AnimationPlayer.play("jump")
elif motion.y > 0:
$AnimationPlayer.play("fall")
motion = move_and_slide(motion, UP)
acola1234 | 2021-02-12 01:43
hmm, I would suggest you use an enum of states to keep track of what your player’s current state is. Or at least after you have finished working on your movement logic(refactor it)
At any rate, regarding the jumping animation overriding your attack animation:
if is_on_floor():
if Input.is_action_pressed("jump"):
motion.y = jump
if Input.is_action_just_pressed("attack"):
can_idle = false
$AnimationPlayer.play("attack")
motion.x = lerp(motion.x, 0, 0.95)
yield($AnimationPlayer, "animation_finished")
can_idle = true
else:
if motion.y < 0:
$AnimationPlayer.play("jump")
elif motion.y > 0:
$AnimationPlayer.play("fall")
I think part of the reason is simply because on this line of code:
if is_on_floor():
if Input.is_action_pressed("jump"):
motion.y = jump
Once your motion.y changed or rather your player’s contact on the floor is broken (on the third line of this code snippet), the logic jumps towards the else:
else:
if motion.y < 0:
$AnimationPlayer.play("jump")
elif motion.y > 0:
$AnimationPlayer.play("fall")
Thus, your action input animation is overridden since the logic is no longer on the is_on_floor() block(since your player is now off the ground).
There are several ways you could go about this, but a quick suggestion would be to separate the logic of attacking from your jumping. In this way, you should be able to attack in any state(jumping, falling, on_floor)
rather than putting your attack logic inside is_on_floor() block.
By any chance were you trying to achieve something similar to this?
Imgur: Godot Jumping & Attacking GIF
Here’s a quick approach I just tried right now:
Disclaimer: it is by no means an elegant approach (embarrassingly sits in a corner)
var jump_force = 300
var jump_delay = 0.1
var jump_time_lapsed = 0
var jumping = false
onready var anim = $AnimationPlayer
func _physics_process(delta):
motion.y += gravity
if Input.is_action_just_pressed("ui_up"):
if is_on_floor():
jumping = true
if jumping:
jump_time_lapsed += delta
#don't jump yet, since in my animation there's a wind up/squat/squash
#before jumping.
anim.play("jump")
if (jump_time_lapsed>jump_delay):
motion.y -= jump_force
jumping = false
if Input.is_action_just_pressed("ui_accept"):
anim.play("attack")
motion = move_and_slide(motion,Vector2.UP)
func _on_AnimationPlayer_animation_finished(anim_name):
match anim_name:
"jump":
jump_time_lapsed = 0
anim.play("idle")
Although, I would highly suggest to start using states since it would come handy in the long run.
bloodsign | 2021-02-12 10:06
I saw it too late… I really appreciate your helps and suggestions!! I’ll try what you suggested right away! Thanks for your helps again
acola1234 | 2021-02-14 10:14