Search code examples
animationtimergame-enginegodotgdscript

GDscript: Shoot bullet after Animation Complete


I am creating a simple 2d Platform Game, My problem is that in one of my animations, the bullet/Bone needs to be created after the animation is complete. Right now it creates the Bone and starts the animation at the same time.

I have tried putting the creation of the Bone projectile under onanimation_complete, but then it will only allow me to shot if my character is facing the left (direction given by key press "a"). Is there something I'm missing?

Here is the code if it helps. Thanks!

extends KinematicBody2D

const WALK = 40
const SPRINT = 70
const GRAVITY = 10
const JUMP = -250
const FLOOR = Vector2(0, -1)

const BONE = preload("res://Bone.tscn")

var is_attacking = false

var velocity = Vector2()
var on_ground = true

func _physics_process(delta):
    if Input.is_action_pressed("D"):
        if is_attacking == false:
            velocity.x = WALK 
            $Player_Animation.play("Player_Run")
            $Player_Animation.flip_h = true
            if sign($Position2D.position.x) == -1:
                $Position2D.position.x *= -1

    elif Input.is_action_pressed("A"):
        if is_attacking == false:
            velocity.x = -WALK 
            $Player_Animation.play("Player_Run") 
            $Player_Animation.flip_h = false
            if sign($Position2D.position.x) == 1:
                $Position2D.position.x *= -1

    else:
        velocity.x = 0
        if on_ground == true && is_attacking == false:
            $Player_Animation.play("Player_Idle")

    if Input.is_action_just_pressed("Space"):
        if is_attacking == false:
            if on_ground == true:
                velocity.y = JUMP
                on_ground = false

    if Input.is_action_just_pressed( "ui_focus_next") && is_attacking == false:

        is_attacking = true
        $Player_Animation.play("Player_Attack")
        var bone = BONE.instance()
        if sign($Position2D.position.x) == 1:
            bone.set_bone_direction(-1)
        else:
            bone.set_bone_direction(1)
        get_parent().add_child(bone)
        bone.position = $Position2D.global_position

    velocity.y = velocity.y + GRAVITY

    if is_on_floor():
        on_ground = true
    else:
        if is_attacking == false:
            on_ground = false
            if velocity.y < 0:
                $Player_Animation.play("Player_Jump")
            else:
                $Player_Animation.play("Player_Fall")

    velocity = move_and_slide(velocity, FLOOR)



func _on_Sprite_animation_finished():
    is_attacking = false

Solution

  • Probably the easiest solution would be to add a bullet delay in the form of a timer node. It would work basically like this: Play animation and start timer simultaneously. If timer reaches 0 while animation is playing, trigger projectile. You set the timer for exact amount of time that elapses from the start of the animation until the time you want the projectile to appear. I've used this technique with great success in other animations. In fact, it's possible to trigger many effects at various points during the animation.

    http://docs.godotengine.org/en/3.0/classes/class_timer.html