1
\$\begingroup\$

In Scene Player, I changed the sprite to animated sprite and created two modes, stand and walk, and wrote these scripts to move the player. But when I play the scene, the characters don't show their animations. I don't know what is problem.

func _physic_ptocess(delta):  
  if Input.is_action_pressed("ui_right"):
    acceleration_player.x = player_speed
    $Sprite.play("walk")
    $Sprite.flip_h = false


  if Input.is_action_pressed("ui_left"):
    acceleration_player.x = -player_speed
    $Sprite.play("walk")
    $Sprite.flip_h = true


  if Input.is_action_pressed("ui_up"):
    acceleration_player.y = -player_speed
    $Sprite.play("walk")


  if Input.is_action_pressed("ui_down"):
    acceleration_player.y = player_speed
    $Sprite.play("walk")


  else:
    $Sprite.play("stand")
\$\endgroup\$
0

1 Answer 1

1
\$\begingroup\$

Look at this code:

if Input.is_action_pressed("ui_down"):
    acceleration_player.y = player_speed
    $Sprite.play("walk")


else:
    $Sprite.play("stand")

I want you to focus on the else branch:

if Input.is_action_pressed("ui_down"):
    # ...
else:
    $Sprite.play("stand")

It says that if you are not pressing the action "ui_down" the animation will be "stand". In which case the rest of calls to play do not matter.

I suppose a solution is to make most of these if into elif. But then you won't be able to combine vertical and horizontal input. Instead...


I want to encourage to separation of concerns. Let us separate the visuals which is what you care about:

if Input.is_action_pressed("ui_right"):
    acceleration_player.x = player_speed

if Input.is_action_pressed("ui_left"):
    acceleration_player.x = -player_speed

if Input.is_action_pressed("ui_up"):
    acceleration_player.y = -player_speed

if Input.is_action_pressed("ui_down"):
    acceleration_player.y = player_speed

# visuals

if abs(acceleration_player.x) < 0.00001 and abs(acceleration_player.y) < 0.00001:
    $Sprite.play("stand")
else:
    $Sprite.play("walk")
    if acceleration_player.x < 0:
        $Sprite.flip_h = true
    else:
        $Sprite.flip_h = false

Note: the reason I check abs(acceleration_player.x) < 0.00001 instead of acceleration_player.x == 0.0 is just in case the value does not hit 0.0 exactly due to floating point errors, which I don't know if they are possible or not in your code. I would have used is_zero_approx in Godot 3.2 or newer.

I submit to your consideration to leave only the check for acceleration_player.x in the conditional. In particular if "walk" does not represent an appropriate animation for vertical motion.

By the way the second part can be more compact if you want:

    $Sprite.flip_h = acceleration_player.x < 0
\$\endgroup\$
4
  • \$\begingroup\$ Thank you Only when I write this code.... ( if is_zero_approx(acceleration_player.x) and is_zero_approx(acceleration_player.y): $Sprite.play("stand") ) it gives this error for this part: " method 'is_zero_approx' is not declared in the current class"and does not allow me to play the scene. (Godot 3.1) \$\endgroup\$
    – Nina Monti
    Commented Apr 18, 2023 at 11:05
  • \$\begingroup\$ Even when the player has no speed, it moves very slowly and never shows a standing position. Even and never stop. \$\endgroup\$
    – Nina Monti
    Commented Apr 18, 2023 at 12:48
  • \$\begingroup\$ @NinaMonti I had forgotten that is_zero_approx wasn't available in Godot 3.1, that is why I changed it to abs(...) < 0.00001 so use that. You might want to tweak the threshold if it is never standing. How do you decelerate is beyond this question. \$\endgroup\$
    – Theraot
    Commented Apr 18, 2023 at 18:32
  • \$\begingroup\$ Thanks.I see and edited my codes. \$\endgroup\$
    – Nina Monti
    Commented Apr 18, 2023 at 20:23

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .