0 votes

So I'm a noob and I'm trying to make it so when the player hits an enemy, they're repelled back and a certain animation of the AnimatedSprite plays, I have a function called "ouch" on my enemy;

     func _on_sidechecker_body_entered(body):   
     print("Ow!")
     body.ouch(position.x)

that triggers when you touch the side of the enemy, the repulsion works, its knocks you back when you touch it, and the print("ow!) works, but I can't get the animation to play. I tried using the "ouch" function to reassign my "anim" variable, but I think it might be getting overridden by some of my if statements. Any help would be appreciated, here's my player code, I thought the "anim = "hurt"" under my func ouch would work but it doesn't.

 extends KinematicBody2D
var Velocity = Vector2(0,0)
var anim = "idle"
var cigs = 0
const Speed = 300
const Gravity = 35
const Jumpforce = -850

func _physics_process(delta):

    if Input.is_action_pressed("Right"):
        Velocity.x = Speed
        $Sprite.flip_h = false
        anim = "walk"
    elif Input.is_action_pressed("Left"):
        Velocity.x = -Speed
        $Sprite.flip_h = false
        anim = "walkleft"
    else:
        $Sprite.flip_h = false
        anim = "idle"
    if not is_on_floor():
        $Sprite.flip_h = false
        anim = "air"
    $Sprite.play(anim)

    Velocity.y = Velocity.y + Gravity
    if Input.is_action_pressed("Jump") and is_on_floor():
        Velocity.y = Jumpforce
    if Input.is_action_pressed("Left") && !is_on_floor():
        $Sprite.flip_h = true

    Velocity = move_and_slide(Velocity,Vector2.UP)

    Velocity.x = lerp(Velocity.x,0,0.2)

    func _on_Area2D_body_entered(body):
        get_tree().change_scene("res://level.tscn")
    func bounce():
        Velocity.y = Jumpforce * 0.7
    func add_cigs():
        cigs = cigs + 1
    func ouch(var enemyposx):
        anim = "hurt"
            $Sprite.play(anim)
        if position.x < enemyposx:
            Velocity.x = -1000
        elif position.x > enemyposx:
            Velocity.x = 1000
        Input.action_release("Left")
        Input.action_release("Right")
Godot version 3.3.3
in Engine by (16 points)

1 Answer

0 votes

Hello,

Firstly, note the AnimatedSprite node already has an animation property that is the direct equivalent of the anim property you are recreating.

You are right about the problem in your code: the ouch function sets the animation to hurt only once but your physics_process resets it the frame after.

The solution to your problem depends on wether your hurt anim is a loop (the animation changes after a given time, potentially looping) or a one-shot (the animation finishes after a given number of frames).

If your animation is a loop, a solution would be to use a Timer to force playing the animation for a minimal duration. By using a one-shot timer and firing at hurt time you can then check in your _physics_process if the timer (say HurtTimer) is stopped or not, interpreting this as wether you're allowed to change the animation to idle/movement/... or not.

If you are dealing with a "fixed" animation, you should use a boolean flag that store the current hurt state (var is_hurt := false) and check it before changing anim. You would set it to true at hurt time and to false when your sprite fires its animation_finished signal.

by (728 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.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.