Jump script - kinematic body

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By edimemune
:warning: Old Version Published before Godot 3 was released.

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?

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

rustyStriker | 2017-09-13 09:01

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

avencherus | 2017-09-13 16:45

not related but hey there romanian fellow

Anastasia | 2020-01-06 13:33

:bust_in_silhouette: Reply From: avencherus

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: AnimationPlayer — Godot Engine (stable) documentation in English