1 Instance a scene
2 Apply gravity to the player
3 Allow the player to jump
After watching (learning outcomes)…
Learn how to instance a scene, change the main scene of the game, make the player fall and let the player jump!
(Unique Video Reference: 5_HD_GDT)
We would love to know…
What you found good about this lecture?
What we could do better?
Remember that you can reply to this topic, or create a new topic. The easiest way to create a new topic is to follow the link in Resources. That way the topic will…
Being new kid on the street is just hard :-). I was not entirely sure if this is a bug or not until I’ve found that Github Issue … Hope this post will save some time to other new kid ;-).
How odd. I know that move_and_slide() can be a little buggy from time to time. A couple of things to check.
(1) Did you scale the collision shape or use the extant? If you scaled it, it’ll behave oddly.
(2) Try reducing the Safe Margin in the Player’s inspector to 0.01 or less and seeing if that works.
I did try to reduce Safe Margin, and the behaviour was even worse for some reason. Adding the motion.y = 150 it’s a hack, but it’s the only thing that seems to work to me, for now.
I don’t shure, but it seems I understand what is the problem. When the player on a floor you change motion.y to 0. So now if the player moves, it moves along the floor, just on its level but don’t touch it, because motion.y = 0. So at the next _physics_process player think it doesn’t on the floor and so add gravity and now it moves a bit lower, touch the floor and again knows it is on the floor. Maybe when player on a floor you should not do
motion.y = 0
but
motion.y = GRAVITY * delta
so it always touchs the floor when on it but does not speed up. And it seems to work good.
EDIT: The downside of my suggested method:
You never have motion.y = 0 although the player is not moving. This could be a problem in the script of the AnimationPlayer node if you rely on that for animation. In our case it works just fine because we only check motion.y < 0:
@Yann_Burrett I would suggest to use this code for the fall method:
func fall(delta):
if is_on_floor():
motion.y = 0 # to prevent the player from accelerating while on the ground
motion.y += GRAVITY * delta # always accelerate so we always get a fresh collision for is_on_floor()
# old version:
func fall():
if is_on_floor():
motion.y = 0
else:
motion.y += GRAVITY * delta
Why?
is_on_floor() should reliably return true, whether the player stays on the ground or just fell down on it
no “silent acceleration” while moving on the ground as demonstrated by Yann in the lecture starting around 7:55 min
A little background info on is_on_floor:
is_on_floor() just needs a fresh collision, otherwise it will not be set to true.
I’ve always been under the impression that you set your velocity to the (left over) velocity that is returned from the move_and_slide call. This seems to eliminate the need for any odd manipulation of the motion.y and makes the is_on_floor() check much more reliable. I’m no expert on the inner workings of KinematicBody, but I believe this method is also required to get slope feature of the node working as well.
func _physics_process(delta):
_get_input()
_fall(delta)
_run(delta)
_jump(delta)
_set_animation()
vel = move_and_slide(vel, UP)
func _fall(delta):
vel.y += GRAVITY
func _jump(delta):
if is_on_floor() and jump_input:
vel.y = -jump_speed
This is my workaround for the is_on_floor() Headache
It works pretty well.
No I can Jump like a Real Bunny!
Please let me know if it’s ok, cause I’m a noob in GoDot!
extends KinematicBody2D
var motion = Vector2(0,0)
const SPEED = 1000
const GRAVITY = 300
const UP = Vector2(0,-1)
const JUMP_SPEED = 3000
func _physics_process(delta):
apply_gravity()
jump()
move()
motion = move_and_slide(motion, UP)
# print (motion.y, " ", motion.x)
func move():
if Input.is_action_pressed("left") and !Input.is_action_pressed("right"):
motion.x = -SPEED
elif Input.is_action_pressed("right") and !Input.is_action_pressed("left"):
motion.x = SPEED
else:
motion.x = 0
func jump():
if Input.is_action_just_pressed("jump") and touching_ground():
motion.y -= JUMP_SPEED
func apply_gravity():
if !is_on_floor():
motion.y += GRAVITY
# This is my implementation for the fact that when moving left - right and not pressing jump, sometimes, is_on_floor() returns
# false.
func touching_ground(): # We substitute the is_on_floor() with touching_ground()
if is_on_floor(): # If is_on_floor True -> definitely is touching ground so return directly True!
return true
else: # Else test to be shure that is on the ground
if test_move(.get_transform(), Vector2(0,5)): # We make a test move down 5 pixels to see if it's colliding
print("Grounded") # So you can see that on movement stays grounded
return true # If the move test is true, then is_on_floor is mistaken so we return true
else: # If it's not colliding 5 (u can try ti tweak between 2 and 5) pixels down, then is in the air, not touching ground, so we return false.
print("NOT Groundes") # See when is not touching ground
return false # Definitely is not touching ground,return false