0 votes

Hello, this is my first time on this website, I have been using godot engine to learn more on it's tools and making games in general but when I tried making a mock project to practice with sprite movement and sprite animation, I've hit a roadblock and unfortunately took a while to consider asking for help.

My problem is about being able to change the animation depending on whether the key is pressed or not. I've learned how to move the sprite and activate the animation but I'm trying to give logic to it so depending where it's facing and if the movement key is not pressed, it will go in an idle animation instead of staying in it's walking animation.

My question is,
How do I change the animation through user input on GDScript so that when I stop pressing the key, it defaults back to it's idle animation? I've tried searching the same questions to this problem with the answers not giving any fruitful results. I've tried with looped animations and it kept looping the animation forever without changing the animation while the non-looped animation couldn't be looped through GDScript to my best of my little knowledge in general. What should I add or change in my code to make it possible? Maybe my arrangement of nodes in my scene is wrong? I appreciate any answers that could nudge me in the right direction.

I'll attach my current work scene and my current code below.

My current work scene setup

extends KinematicBody2D

func _ready():
    set_process(true)
    set_process_input(true)

const playerspeed = 150
var anim = ""
var new_anim = anim

func _process(delta):
    var userpos = get_pos()

    if (Input.is_action_pressed("ui_up")):
        userpos.y += -playerspeed*delta
        new_anim = "go_up"
    if (Input.is_action_pressed("ui_down")):
        userpos.y += playerspeed*delta
        new_anim = "playermovement"
    if (Input.is_action_pressed("ui_left")):
        userpos.x += -playerspeed*delta-2
        new_anim = "go_left"
    if (Input.is_action_pressed("ui_right")):
        userpos.x += playerspeed*delta+2
        new_anim = "go_right"



    if (new_anim!=anim):
        anim=new_anim
        get_node("Sprite/anim").play(anim)

    set_pos(userpos)
in Engine by (15 points)

Hi,

I'm also new to godot, I've just discovered godot this week and I also trying it. I did this yesterday and I thinks it's similar to what you need.

For sure my code it's only a big pile of shitl lol, but I hope it could help you.

extends RigidBody2D

var walking_speed = 32;
var running_speed = 64;

var facing = "down";
var max_speed = walking_speed;

func _ready():
    set_process_input(true);
    set_fixed_process(true);
    pass

func _fixed_process(delta):
    limit_movement_speed();
    update_sprite();

func _input(event):
    var input_dir = Vector2(0, 0);

    if Input.is_action_pressed("ui_right"): input_dir += Vector2(1,0);
    if Input.is_action_pressed("ui_left"): input_dir += Vector2(-1,0);
    if Input.is_action_pressed("ui_up"): input_dir += Vector2(0,-1);
    if Input.is_action_pressed("ui_down"): input_dir += Vector2(0,1);

    if Input.is_action_pressed("ui_run"): max_speed = running_speed;
    else: max_speed = walking_speed;

    if input_dir.length() != 0:
        set_applied_force(input_dir.normalized() * max_speed * 10);
    else:
        set_applied_force(input_dir);

func limit_movement_speed():
    if get_linear_velocity().length() > max_speed:
        set_linear_velocity(get_linear_velocity().normalized() * max_speed);

func update_sprite():
    var animator = get_node("animator");

    var angle = round(rad2deg(get_linear_velocity().angle()) / 90) * 90;
    if angle < 0: angle += 360;

    if angle == 90: facing = "right";
    elif angle == 270: facing = "left";
    elif angle == 0: facing = "down";
    elif angle == 180: facing = "up";

    var state = "idle"
    if get_linear_velocity().length() > 5: state = "walking";

    var animation = state + "_" + facing;

    if animator.get_current_animation() != animation:
        animator.play(animation);

2 Answers

+2 votes
Best answer
onready var ANI = get_node("AnimationPlayer")

func _ready():
   set_fixed_process(true)

func _fixed_process(delta):
   var State = "Idle"

   var IsKeyPressed = Input.is_action_pressed("action")

   if IsKeyPressed:
      State = "Walk"

   if ANI.get_current_animation() != State:
      ANI.play(State)

I'm assuming you know how to use actions and the Input Map. If you don't, I'd recommend reading the tutorial provided by Godot, here.

by (1,111 points)
selected by

This is exactly the solution to my problem, thank you very much and everyone else who answered as well!

0 votes

I am not sure if its what you mean but you can use method called queue of AnimationPlayer class.

Its will, well, queue the animation (passed by string name). Animation will start right after current one is finished.

http://docs.godotengine.org/en/latest/classes/class_animationplayer.html

by (56 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 Frequently asked questions and 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.