0 votes

I'm following a tutorial and I want to add a feature myself where you can slash the enemy. So far I'm working on the animation (called "Attack 1"), though I have a problem.
It only plays the first frame, then just switches to the idle animation. For some reason the other animations work fine, so I don't understand what's wrong. How do I get it to play the rest of the animation???
(for reference here's the player script)

extends KinematicBody2D
const FLOOR = Vector2(0, -1) 
const GRAVITY = 30         
const JUMP_HEIGHT = -800
const SPEED = 300
const FIREBALL = preload("res://fireball.tscn")
var vel = Vector2()
var ground = false
func _physics_process(delta):
    if Input.is_action_pressed("ui_left"):
       vel.x = -SPEED
       $AnimatedSprite.play("Run")
       $AnimatedSprite.flip_h = true
        if sign($Position2D.position.x) == 1:
          $Position2D.position.x *= -1 
    elif Input.is_action_pressed("ui_right"):
        vel.x = SPEED 
        $AnimatedSprite.play("Run")
        $AnimatedSprite.flip_h = false
        if sign($Position2D.position.x) == -1:
          $Position2D.position.x *= -1
    else:
       vel.x = 0
    if ground == true:
       $AnimatedSprite.play("Idle")
    if Input.is_action_pressed("ui_up"):
    if ground == true:
        vel.y = JUMP_HEIGHT
        ground = false
               vel.y += GRAVITY

        if Input.is_action_just_pressed("shoot"):
      var fireball = FIREBALL.instance()
      if sign($Position2D.position.x) == 1:
        fireball.set_pos(1)
    else:
        fireball.set_pos(-1)
    get_parent().add_child(fireball)
    fireball.position = $Position2D.global_position
    if Input.is_action_just_pressed("slash"):
        $AnimatedSprite.play("Attack 1") # <---- Bug
    else:
        $AnimatedSprite.play("Idle")


    if is_on_floor():
       ground = true
    else:
        ground = false
    if vel.y < 0:
        $AnimatedSprite.play("Jump")
    else:
        $AnimatedSprite.play("Fall")

   vel = move_and_slide(vel, FLOOR)

(I apologize for the improper indentation, it was hard to manually indent everything X( )

asked Jun 9 in Engine by owlisGODOT (29 points)

To properly paste code in the forum.

  1. copy properly formatted code from your text editor
  2. paste it into the forum message
  3. select it
  4. Press the {} button in the forum message toolbar

That'll indent everything properly for forum display...

2 Answers

0 votes
Best answer

The immediate problem I see is that your Attack 1 animation is being triggered by Input.is_action_just_pressed, which is only true in the single frame where the action button was pressed. So, in that one frame, it'll start to play the animation, but in the very next frame, that call will return false. Based on your code, that next frame would process the code in the else block, which causes the Idle animation to play again.

The most obvious thing to do is simply remove the else: block all together. By the looks of it, you'll already play the idle animation if you're grounded (higher in your code), so that might work for you.

That said, your input processing code is likely much more complex (and redundant) than necessary, which makes working this out more difficult than necessary...

answered Jun 9 by jgodfrey (5,540 points)
selected Jun 11 by owlisGODOT

The code was complex because I was following a tutorial... I've already fixed it, but I hope this answer can help others.

0 votes

it's hard to handle too many if/elses, you should avoid them, they generates lots of bugs

I've made a simple code, I didn't check if it's working but you can try out this way, there's some tips that can help you improve your codes

extends KinematicBody2D

const gravity = 50
var vel = Vector2.ZERO
var speed = 200
var jump_force = 500
enum {move, attack}

var state = move

func _physics_process(delta):
    vel.y += gravity * delta

    match state:
        move:
            move()
        attack:
            attack()

    vel = move_and_slide(vel, Vector2.UP)

func move():
    var direction = Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left") #gives positive or negative 1
    if direction != 0:
        $animation.play("run")
        $animation.flip_h = direction < 0 #flip accordingly the direction
        vel.x = direction * speed

    if is_on_floor(): ###### --------------- insted ground var
        if !direction:
            $animation.play("idle")
            vel.x = 0
    else:
        pass #jump things

func attack():
    pass #attack code / $animation.play("atttack")

Hope this helps you, Good luck

answered Jun 10 by BrunoFreezee (78 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.