How to make fall damage for a 2d platformer

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By GodotUser21

I am trying to make my character die from fall damage. So I use this code

	velocity.y += gravity * delta
fall_strength += 1

But there is one big issue. It is that as long as I am not on the floor, I take damage. I was thinking of storing the y position of the player in a variable after a jump was made and subtracting the y position after the character hits the floor. (the y position will be stored in another variable when the character hits the floor)
Since I just started with Godot, I do not know how to do this.

Also, another concern is with the negative numbers since if my character drops from a negative number, e.g. drop from y = -145 and lands on a negative number when hits the floor, e.g. y = -230, it will give me a positive number. And when my character drops from a positive number, e.g. y = 500, and lands on the ground that is a positive number, e.g. 100, means I cannot put a fixed height limit that my character can fall

How should I tackle this issue?

:bust_in_silhouette: Reply From: petermoyle

This video should help you.

You should be able to just use the velocity.y to determine if the player should take fall damage rather than storing an extra fall_strength variable and distance fallen. velocity.y will constantly increase based on your gravity.

if velocity.y is positive it means your player is falling, if it’s above a particular threshold then you can apply fall damage, you could also set different thresholds of instant death vs damage.

Does this work for a kinematic body 2d???

GodotUser21 | 2022-09-08 09:10

Yes, you don’t have to do the full state system in the video.

Have you got the code that detects when the player lands on the ground?

share your full code for func _physics_process(delta): if you like and I can give better advise.

petermoyle | 2022-09-08 09:27

Edited this response as i got my positive and negative mixed up, velocity.y will be a positive number when falling.

petermoyle | 2022-09-08 09:50

_physic_process(delta) function:

func _physics_process(delta):
	get_input()
	shrink()
	if is_on_floor():
		jumps_made = 0 #double jump
		fall_strength = 0
	velocity.y += gravity * delta
	fall_strength += 1
	fall_damage_taken()
	jump()
	velocity = move_and_slide(velocity, Vector2.UP)
	print(fall_strength)

detection when on floor:

func fall_damage_taken():
	if fall_strength >= 90:
		will_die = true
	if fall_strength < 90 and not is_on_floor():
		will_die = false
	if will_die == true and is_on_floor() and PlayerGlobal.reached_checkpoint != true:
		pass #play death animation
		move_last_checkpoint()
		print("fall damage taken")
		will_die = false
	elif will_die == true and is_on_floor() and PlayerGlobal.reached_checkpoint== true:
		move_last_checkpoint()
		print("fall damage taken")
		will_die = false

GodotUser21 | 2022-09-08 11:27

have a look at the code i provided in my other answer. It should give you everything you need.

petermoyle | 2022-09-08 11:42

Probably something like:

func _physics_process(delta):
	get_input()
	shrink()
	
	velocity.y += gravity * delta
	
	if is_on_floor():
		jumps_made = 0 #double jump
		if fall_strength > 0:
			fall_damage_taken()
		fall_strength = 0
	else:
		fall_strength = velocity.y
	jump()
	velocity = move_and_slide(velocity, Vector2.UP)

func fall_damage_taken():
	if fall_strength >= 90:
		will_die = true
	if will_die == true:
		if PlayerGlobal.reached_checkpoint == true:
			move_last_checkpoint()
		else:
			print("move back to start?")
		will_die = false

petermoyle | 2022-09-08 12:02

Wow! Thanks so much for the help :smiley:

GodotUser21 | 2022-09-08 12:27

No worries, if you plan on playing a death animation you will need to move the “move_last_checkpoint()” to inside an animation finished event.

petermoyle | 2022-09-08 13:00

:bust_in_silhouette: Reply From: petermoyle

add a new var falling_speed = 0

	velocity.y += GRAVITY * delta
	
	
	if is_on_floor():
		on_ground = true
		if falling_speed > 300:
			print("instant death")
		elif falling_speed > 230:
			print("take damage")
		falling_speed = 0
	else:
		on_ground = false
		falling_speed = velocity.y
		if velocity.y < 0:
			$AnimatedSprite.play("jump")
		else:
			$AnimatedSprite.play("fall")
	
		
	velocity = move_and_slide(velocity, FLOOR,true)