The Godot Community Forums are back up and running! Please read the the announcement post for important information on what happened. Thanks!

# Recording the time between the moment when the player is in a free fall and touching the ground

Posts: 35Member

Hello! I want to record, in a variable, the time between the moment when the player is in a free fall and the moment when he touches the ground, in order to implement the health loss, when jumping from a great height.

How should I do this?

• Posts: 3,129

I'm not sure, but I think this will measure the time the player has been in the air (assuming a KinematicBody2D):

``````var in_air_time = 0

func _physics_process(delta):
if (is_on_floor()):
if (in_air_time > 0):
# Make the player take damage here!
print ("player was in the air for ", in_air_time, " seconds!")
in_air_time = 0
else:
in_air_time += delta
``````

I'm not sure, but I think this will measure the time the player has been in the air (assuming a KinematicBody2D):

``````var in_air_time = 0

func _physics_process(delta):
if (is_on_floor()):
if (in_air_time > 0):
# Make the player take damage here!
print ("player was in the air for ", in_air_time, " seconds!")
in_air_time = 0
else:
in_air_time += delta
``````
• Posts: 35Member

Awesome explanation!

Yes, this code measures very well the time spent in the air.

Thanks!

• Posts: 1,053Moderator

Nice solution.

• Posts: 50Member
edited September 9

If you're implementing fall damage, I think an easier and more realistic way to do so would be to damage the player based on their downward velocity when they hit the ground. It might not be necessary for your game, but this would allow you to implement things like pools of water that cushion the player's fall.

• Posts: 35Member
edited September 9

Good idea!

Now, I don't have any pool of water in my game, but I will consider this solution. )

• Posts: 35Member
edited September 23

@Azedaxen , I just met the necessity to implement the damage based on downward velocity instead of time spent in the air.

When I jump off the top of the tree trunk, and then land on the same tree trunk, but nearer the ground (basically, I land on a flight zone) and then I peacefully get off the tree , when I touch the ground, the player receives damage from the time spent in the air, a few seconds ago, when he is not even falling.

It turns out that if I stay on the base of the trunk for a minute, when I touch the ground, I will receive damage from time spent in the air a minute ago. It is weird xD

Even if this solution works very well, in order to get rid of this bug, I have to modify it.

Do you guys know how to record the downward velocity when the player touches the ground?

I tried a modification of the previous solution:

``````    if is_on_floor():
if (in_air_time > 0):
print(velocity.y)
in_air_time = 0
elif !flying:
in_air_time += delta
``````

but this solution measures the velocity when the player is already on the ground. The velocity is, of course, 0. ))

I have to record the velocity just before landing.

• Posts: 50Member
edited September 26

@Tudor said:
Do you guys know how to record the downward velocity when the player touches the ground?

Sorry, I would've seen this sooner but I've been busy.

Ultimately, this depends on how your character controller is programmed. For instance, my character has separate variables for horizontal and vertical velocity. The reason I did this was to make it easier to handle gravity and jumping separate from the WASD movement that the player inputs. Because of this, I also have convenient access to a `vertical_movement` property. My fall damage code would look something like this:

``````if grounded:
if vertical_move <= -25.0:
var falldamage = lerp(50, 100, abs(vertical_move)/terminal_velocity)
# Player health is handled elsewhere
``````

In this example, the player starts to take fall damage if they are falling at least as fast as half of their terminal velocity, (50) and hitting the ground at terminal velocity is fatal. `lerp` is used to ramp the fall damage to be anywhere from a minimum of 50 to a maximum 100 based on downward speed, where `vertical_move/terminal_velocity` is a percentage with 100% being terminal velocity, used to interpolate between these two values.

Edit: To further elaborate on this system, the way gravity works in my game is that the player's vertical_move is constantly being subtracted from if they are not on the ground, clamped to the terminal velocity. When they are on the ground, vertical_move is set to 0, so the check for a certain falling speed will only happen once. Setting the fall speed to 0 should happen after the fall damage check in order for this to work correctly.

What sort of variables do you use to handle gravity?

• Posts: 35Member
edited September 27

@Azedaxen said:
Ultimately, this depends on how your character controller is programmed.
What sort of variables do you use to handle gravity?

In my game's character controller, the "velocity" variable is a Vector3(), the "gravity" is a float, and I also use a boolean variable "has_contact", to check if the player is on floor:

``````    var velocity = Vector3()
var gravity = -9.8 * 3
var has_contact = false
``````

How I handle gravity:

``````    var n = \$Tail.get_collision_normal()

if (is_on_floor()):
has_contact = true

var floor_angle = rad2deg(acos(n.dot(Vector3(0, 1, 0))))
if floor_angle > MAX_SLOPE_ANGLE:
velocity.y += gravity * delta

else:
if !\$Tail.is_colliding():
has_contact = false
velocity.y += gravity * delta
``````

where "Tail" is the player's Raycast.

The rest of the "velocity" variable (x and z directions) are used for handle WASD movement system.

• Posts: 77Member

i would do it lil bit differently: i would take the velocity.y wich represents the speed the player falls and then calculate the dmg according to this..

for example:
if velocity.y > 1000 && is_on_floor():
..take dmg..