0 votes

I am working on a game and I need to make the player (a ball - kinematic body) jump on space key press.
Here is what I've done:

extends KinematicBody2D

export var viteza = 30
var animNod
var jumped = false

func _ready():
    animNod = get_node("AnimatedSprite")
    set_fixed_process(true)

func _fixed_process(delta):

    var corp = get_collider()
    if corp != null:
        if corp.is_in_group("sol"):
            jumped = false

    #MISCARE

    delta *= 10
    var misc = Vector2(0,1)

    if(Input.is_key_pressed(KEY_D) or Input.is_key_pressed(KEY_RIGHT)):
        misc[0] = 1

    if(Input.is_key_pressed(KEY_A) or Input.is_key_pressed(KEY_LEFT)):
        misc[0] = -1

    misc = misc * (delta * viteza)

    self.move(misc)

    #ANIMATIE

    var newAnim = "idle"

    if(Input.is_key_pressed(KEY_D) or Input.is_key_pressed(KEY_RIGHT) or Input.is_key_pressed(KEY_A) or Input.is_key_pressed(KEY_LEFT)):
        newAnim = "mers"

    #Jump --->

    if((Input.is_key_pressed(KEY_SPACE) or Input.is_key_pressed(KEY_W)) and not jumped):
        jumped = true
        var hVector = Vector2(0, -1)
        var hSpeed = 0
        var jH = 50
        hVector = hVector * (delta * hSpeed)
        newAnim = "saritura"
        var height = get_pos()[1]
        while get_pos()[1] > height - jH:
            self.move(hVector)

    #<--- Jump

    animNod.play(newAnim)

It doesn't work. It teleports at that position, it doesn't go smooth. And the animation doesn't play. How to make it work?

asked Sep 13 in Engine by edimemune (60 points)

if you move it in the same frame multiple times you will be "teleported" and wont see the motion... try doing a velocity - gravity thing where you grant it a certain velocity and after each frame the velocity changed by the acceleration(aka gravity) so it will be more motion like

As an aside. For vectors you're perfectly fine referencing the XY components for readability. Such as: misc.x = -1

1 Answer

0 votes

There is a variety of things going wrong here. I think you would find learning about Finite State Machines (FSMs) to be very valuable for this kind of state changing for characters.

As @rustyStriker says, you don't want to do all the iterations in one frame. That's instant. You want to apply a velocity frame by frame, and here you would need some logic to make use of your "jumped" state. if (jumped): apply forces here

The forces should be made to decay so the player eventually is overcome by the gravity vector and hits the floor. Then this state turns the jump flag off so you can read the keys again for another jump.

Then I wonder about your line that says hVector = hVector * (delta * hSpeed)

Your hSpeed is set to 0. So everything multiplied by 0 is zero, so you're always going to get a 0, 0 hVector.

Lastly, the animation should be put into the state checking. Because what happens here is that jump fully resolves in one frame, and so you might get to see the jump animation for 1/60th of second? Until the next frame, at which point it passes over the input/jump branch, and plays the other animation.

This means too that you should be checking the state of the animation, as you don't want to keep restarting it from 0 by constantly calling play(). There is an get_current_animation() method you can consult, and various others depending on how you wish to structure your logic.

That is the general gist of it. More complete information on the animation methods can be found in the docs: http://docs.godotengine.org/en/stable/classes/class_animationplayer.html#class-animationplayer-get-current-animation

answered Sep 13 by avencherus (3,659 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.