How to make animation play to the end on just one button tap(not holding)??

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Katoshi

Hi everyone,

so I have a problem with my code. As you can see below in my Input(event) function I’ve made a if check for pressing “action” key. The “if” should check if button was pressed and then play atack animation. The problem is that the animation is playing from start to the end only when I keep atack button pressed. When button is released the animation stops playing in the middle. I want to make it play till the last frame even if button is tapped/pressed for a short period of time.

UPDATE: Problem solved. I’ve used the frame counter and after last frame set bool to false. Everything works. Thank you.

Here’s the code:

extends KinematicBody2D

const ACCEL = 1500
const MAX_SPEED = 500
const FRICTION = -500
const GRAVITY = 4000
export var JUMP_SPEED = -1500
const MIN_JUMP = -500

var acc = Vector2()
var vel = Vector2()
var anim = "idle"
var atack_anim = "idle"

func _ready():


pass

func _input(event):
if event.is_action_pressed("ui_up") and is_on_floor():
	vel.y = JUMP_SPEED
if event.is_action_released("ui_up"):
	if vel.y < MIN_JUMP:
		vel.y = MIN_JUMP

if event.is_action_pressed("atack") and is_on_floor():
	set_physics_process(false)
	
	atack_anim = "atack"
	
	$sprite.play(atack_anim)
	
if event.is_action_released("atack"):
	
	set_physics_process(true)
	
pass
func _physics_process(delta):
if is_on_floor():
	acc.y = 0
else:
	acc.y = GRAVITY

acc.x = int(Input.is_action_pressed("ui_right")) - int(Input.is_action_pressed("ui_left"))
acc.x *= ACCEL

if acc.x == 0: #if player not moving then stop motion
	acc.x = vel.x * FRICTION * delta
	
vel += acc * delta
vel.x = clamp(vel.x, -MAX_SPEED, MAX_SPEED)

	
move_and_slide(vel, Vector2(0, -1))
if abs(vel.x) < 10:
	vel.x = 0
	
#set animation

if vel.x > 0:
	$sprite.flip_h = false
elif vel.x < 0:
	$sprite.flip_h = true	

if vel.y < 0 and is_on_floor() == false:
	anim = "jump_up"
else:
	anim = "jump_fall"
	if is_on_floor() and vel.x == 0:
		anim = "idle"
	elif is_on_floor() and vel.x != 0:
		anim = "running"
		
$sprite.play(anim)


pass

hmm, You’ve said _process(delta): but I am using _physics_process(delta): so I assume that you meant _physics_process(delta):, correct me if I am wrong. I’ve tried to do it your way but still getting it wrong. I’ve created bool named state and probably I don’t know where to set it back to false.
Below you can see updated code:

extends KinematicBody2D

const ACCEL = 1500
const MAX_SPEED = 500
const FRICTION = -500
const GRAVITY = 4000
export var JUMP_SPEED = -1500
const MIN_JUMP = -500

signal hit

var acc = Vector2()
var vel = Vector2()
var anim = "idle"
var state = false

func _ready():


    pass

func _input(event):

    if event.is_action_pressed("ui_up") and is_on_floor():
        vel.y = JUMP_SPEED
    if event.is_action_released("ui_up"):
        if vel.y < MIN_JUMP:
            vel.y = MIN_JUMP


    if event.is_action_pressed("atack") and is_on_floor():

        state = true


    #if event.is_action_released("atack"):


    pass



func _physics_process(delta):

    if is_on_floor():
        acc.y = 0
    else:
        acc.y = GRAVITY

    acc.x = int(Input.is_action_pressed("ui_right")) - int(Input.is_action_pressed("ui_left"))
    acc.x *= ACCEL

    if acc.x == 0: #if player not moving then stop motion
        acc.x = vel.x * FRICTION * delta

    vel += acc * delta
    vel.x = clamp(vel.x, -MAX_SPEED, MAX_SPEED)


    move_and_slide(vel, Vector2(0, -1))
    if abs(vel.x) < 10:
        vel.x = 0

    #set animation



    if vel.x > 0:
        $RayCast2D.rotation_degrees = -90
        $sprite.flip_h = false
    elif vel.x < 0:
        $RayCast2D.rotation_degrees = 90
        $sprite.flip_h = true   

    if vel.y < 0 and is_on_floor() == false:
        anim = "jump_up"
    else:
        anim = "jump_fall"
        if is_on_floor() and vel.x == 0:
            anim = "idle"
        elif is_on_floor() and vel.x != 0:
            anim = "running"

    if state:
        anim = "atack"


    $sprite.play(anim)



    pass

Katoshi | 2018-04-10 19:45

Did you do it? can you show me the script now or explain exactly how did u do it? I have the same problem but I can’t solve it, Thank you.

BrunoFreezee | 2018-06-11 01:16

:bust_in_silhouette: Reply From: Two-Tone

The issue is that the if statement will only run while the button is pressed. What you should be doing is setting a bool to true when that if statement is run, then in _process(delta): check to see if that bool is set to true. If it is, then you play the animation. Once the animation is done, set the bool back to false.

Updated code up

Katoshi | 2018-04-08 10:42