Home > Software design >  Problem with coding multi-frame jump animation (GDScript)
Problem with coding multi-frame jump animation (GDScript)

Time:12-04

So I am a beginner programmer using GDScript and got stuck with playing jump animation. All my animations are like 2 frames and where easy to code, but my jump is multi-frame and I couldn't find a tutorial to help.

Also I'm not comfortable with anim.tree -s, I prefer to hard code them in.

My code (I know its basic):

extends KinematicBody2D

const SPD = 100
const GRV = 15
const JUMPF = -350
const SPD_B = 50

var valocity = Vector2(0,0)


func _process(delta):
    if Input.is_action_pressed("ui_right"):
        valocity.x = SPD
        $AnimatedSprite.play("walk")
        $AnimatedSprite.flip_h = false
    elif Input.is_action_pressed("ui_left"):
        valocity.x = -SPD
        $AnimatedSprite.play("walk")
        $AnimatedSprite.flip_h = true
    else:
        $AnimatedSprite.play("idle")
    
    valocity.y = valocity.y   GRV
    
    if Input.is_action_pressed("ui_sprint") and Input.is_action_pressed("ui_right"):
        valocity.x = SPD   SPD_B
        $AnimatedSprite.play("run")
        $AnimatedSprite.flip_h = false
    elif Input.is_action_pressed("ui_sprint") and Input.is_action_pressed("ui_left"):
        valocity.x = -SPD   -SPD_B
        $AnimatedSprite.play("run")
        $AnimatedSprite.flip_h = true
    
    if Input.is_action_just_pressed("ui_up") and is_on_floor():
        valocity.y = JUMPF
    
    valocity = move_and_slide(valocity, Vector2.UP)
    
    valocity.x = lerp(valocity.x, 0, 0.3)
    
    
func _on_Area2D_body_entered(body):
    get_tree().reload_current_scene()

SPD_B is speed bonus for sprint Game is 2d platformer

I tried anim.tree but couldn't use it. It was to confusing. Also I tried to code it like other but it didn't work. Any help is appreciated.

CodePudding user response:

I presume you would insert a line $AnimatedSprite.play("jump") or similar to play your jump animation. Correct?

Then the issue is that it gets replaced by the "walk" (or "run") or "idle" animation the next frame.

Well, do you want those animations to play while the character is on the air (not is_on_floor())? If you don't, then don't. usually the animations that play on the air are for jumping and falling, not for walking/running nor for idle.

That could be for example:

if is_on_floor():
    if Input.is_action_pressed("ui_right"):
        valocity.x = SPD
        $AnimatedSprite.play("walk")
        $AnimatedSprite.flip_h = false
    elif Input.is_action_pressed("ui_left"):
        valocity.x = -SPD
        $AnimatedSprite.play("walk")
        $AnimatedSprite.flip_h = true
    else:
        $AnimatedSprite.play("idle")

    # …

Now, presumably you still want air control (allow the player to move with the directions while it is on the air)… Thus I suggest to separate the animation concern.

So, one block of code will set the motion. And another will set the animations. Something like this:

if Input.is_action_pressed("ui_right"):
    valocity.x = SPD
elif Input.is_action_pressed("ui_left"):
    valocity.x = -SPD

# …

if is_zero_approx(valocity.x):
    $AnimatedSprite.play("idle")
elif valocity.x > 0.0:
    $AnimatedSprite.play("walk")
    $AnimatedSprite.flip_h = false
elif valocity.x < 0.0:
    $AnimatedSprite.play("walk")
    $AnimatedSprite.flip_h = true

The above code also makes it easy for the animation to change to "idle" automatically when the speed falls to zero. For example if you have some deceleration code such as valocity.x *= 0.7 (which, notice, is not frame rate independent, but you get the idea).

And then it is easy to have a set of animations for the air and another for ground:

if Input.is_action_pressed("ui_right"):
    valocity.x = SPD
elif Input.is_action_pressed("ui_left"):
    valocity.x = -SPD

# …

if is_on_floor():
    if is_zero_approx(valocity.x):
        $AnimatedSprite.play("idle")
    elif valocity.x > 0.0:
        $AnimatedSprite.play("walk")
        $AnimatedSprite.flip_h = false
    elif valocity.x < 0.0:
        $AnimatedSprite.play("walk")
        $AnimatedSprite.flip_h = true

    # …
else:
    $AnimatedSprite.play("jump")
    # …

You can, of course, define a thresholds for using the "run" animation instead of the "walk" animation. For example:

if is_on_floor():
    if is_zero_approx(valocity.x):
        $AnimatedSprite.play("idle")
    elif valocity.x > SPD:
        $AnimatedSprite.play("run")
        $AnimatedSprite.flip_h = false
    elif valocity.x < -SPD:
        $AnimatedSprite.play("run")
        $AnimatedSprite.flip_h = true
    elif valocity.x > 0.0:
        $AnimatedSprite.play("walk")
        $AnimatedSprite.flip_h = false
    elif valocity.x < 0.0:
        $AnimatedSprite.play("walk")
        $AnimatedSprite.flip_h = true

And of course, you would have to call `move_and_slide``, and also insert the code for jumps, gravity, and so on.

  • Related