Godot 101 - Part 10: RayCasts (and Jumping)
Thu, Apr 6, 2017This is part 10 of “Godot 101”. In this installment, we’ll learn about how to detect when a character is on the ground, so we can jump, by using the RayCast2D node. If you haven’t already read through the previous parts, please start with Part 1.
About this series
Godot 101 is an introduction to the Godot game engine and how it works. If you’ve never used a game engine before, or if you’re just new to Godot, this is the place to start. If you’re new here, a quick note about this website: we’re called KidsCanCode because we teach programming and game development to kids, but if you’re an adult you’re welcome here, too. We don’t believe in dumbing-down the material for kids, and game development is hard - so it will probably be challenging no matter what your age.
You can watch a video version of this lesson here:
Getting Jumpy
Jumping is an important part of any platform game, but there are some things to consider when it comes to implementation. At first glance, it’s very simple:
JUMP_SPEED = -1000
func _fixed_process(delta):
# ...
if Input.is_action_pressed("ui_up"):
vel.y = JUMP_SPEED
The problem here is that tapping the key will jump, but holding it down sends the player flying up off the screen. As long as the key is down, we continue to move upward.
Instead, we want to only allow a jump if the player is standing on the ground.
One approach to this would be to create a variable called “can_jump” and toggle it between true/false
: when you land, it’s true
, and when you jump, it’s false
. This is a very common strategy and works just fine.
However, we’re going to use a RayCast2D to detect the ground beneath the player’s feet.
Casting Rays
Add one of these nodes to the player scene and name it “ground_ray
”. You will see a blue arrow pointing downward from the center of the player. Let’s adjust its location by changing Pos
to (0, 50)
and its length by changing Cast To
to (0, 20)
. You should see this:
Now to use this in the code, add this to player.gd
:
onready var ground_ray = get_node("ground_ray")
JUMP_SPEED = -1000
func _fixed_process(delta):
# ...
if Input.is_action_pressed("ui_up") and ground_ray.is_colliding():
vel.y = JUMP_SPEED
Now we only jump when standing on the ground, but what happens if we hold the key?
Ideally, the player should jump one time when the jump key is pressed, then not again until it’s pressed again. To do this, we can change the way we check for the key:
func _ready():
set_process_input(true)
func _input(event):
if event.is_action_pressed("ui_up") and ground_ray.is_colliding():
vel.y = JUMP_SPEED
Enabling input processing means that whenever an input event occurs, the _input()
function will be called. We then use that event to trigger the jump, instead of doing it every frame in _fixed_process()
.
One-way Collisions
Head over to the main scene and duplicate the platform instance so that you have two platforms arranged like this:
If you run, everything works fine, and you can jump to the upper platform. But what about when you’re standing under it? In some games, you’d like to allow the player to jump up through the platform and land on the top. Godot has you covered.
In the platform scene, find the following section in the platform
node:
The One Way Collision
section lets us set the object to only detect collisions in one direction. Set Direction
to (0, 1)
(collide with things moving downward) and Max Depth
to 16
(this is how far into the platform an object is allowed to penetrate before the one way collision takes effect). Now you should have this:
Varying the Jump
Many games allow the player to vary the height of the jump depending on how long they hold down the jump key or how quickly they release it. We can do that easily using the _input()
function:
MIN_JUMP = -500
func _input(event):
if event.is_action_released("ui_up"):
vel.y = clamp(vel.y, MIN_JUMP, vel.y)
Now, if the player releases the jump key, we check the velocity. If it’s less than -500 (going up faster) then we clamp it to -500, cutting the jump short.
Wrapping Up
In the next installment, we’ll add animations to the player.