How do I implement fall damage?


(Nate ) #1

Hey guys! I have coded this successfully or just about a few different ways and each of my methods ends up having some minor issues. I was wondering what you guys thought. Basically if my player falls for too long without coming in contact with a platform, upon hitting the ground or a platform if fallenY is too high, the player explodes into blood and organs lol

Can someone walk me through some pseudo code? Thank you! Like I said I have it working FOR THE MOST part in a few different ways, but every time I think I have it down, I find an issue with it.

Here is what I currently have:

if (ySpeed >= 0 && isJumping == true || isJumping == false && !collide("level", x, y))
	{
		hasFallen ++;
	}
	
	if (isOnGround == true)
	{
		hasFallen = 0;
	}
	
	if (collideTypes(["level"], x, y + 1) && hasFallen >= 115)
	{
		death = true;
		xSpeed = 0;
		ySpeed = 0;
	}

(Nate ) #2

I think I have it working better now, I may not need help! This is my latest configuration minus the killing code but that part is easy so it doesn’t really matter.

if (isOnGround == true)
	{
		playerFalls = 0;
		playerClimbs = 0;
		playerIsFalling = false;
	} 
	
	if (ySpeed >= 0 && isOnGround == false)
	{
		playerFalls ++;
	}
	
	if (ySpeed <= 0 && isOnGround == false && playerIsFalling == false)
	{
		playerClimbs ++;
	}
	
	if (ySpeed >= 0 && playerClimbs == 0 && isOnGround == false)
	{
		trace("the player is actually falling with nothing getting in the way");
		playerIsFalling = true;
		
	}

(Brad Davies) #3

If your platform code is solid, it should be a simple addition really. As soon as your players ySpeed goes +ve (i.e. they start falling) I would increase a timer by FP.elapsed per frame, and then when they do finally re-collide with the ground, if their timer is over 3 seconds, just insta-kill them. Some example code (Exluding some platform code Im not going to go over)

if(ySpeed>0) killTimer+=FP.elapsed;
if(collideGround)
{
    ySpeed=0;
    if(killTimer>3) instakill();
    else killTimer=0;
}

Alternatively, instead of tracking the Entity’s LENGTH of time falling, you could easily figure out the DISTANCE they have fell, which may be more suitable. You could do something similar (Track the sum of ySpeed x-additions since ySpeed has been +ve and they started falling).


(Nate ) #4

Thank you! The thought of using a timer had occurred to me, but I did not implement one for this yet. I will give this a whirl! Thanks!


(Abel Toy) #5

Why don’t you just check if ySpeed is higher than the death value when it collides with the ground?


(Zachary Lewis) #6

If the player didn’t have a terminal velocity, this method would work. If the player did have a terminal velocity (which provides better air control and prevents falling from getting out of control), the timer method would be better.

As an alternative, you could also store the location the player left the ground (or began to fall in the case of a jump) and do a distance check upon landing. This would be a good solution if you had player modifiers that made him fall faster or slower but didn’t change the height of death.


(Nate ) #7

Zach I like your idea a lot, that is what I wanted to do originally but have not previously done something similar so I wasn’t sure how to implement it.

For example, I like the distance of 500-550ish pixels, if the player falls that many pixels and hits the ground or a platform, DEATH.

How would I go about doing this distance check? That is what I was trying to fake with my counters and messing with my ySpeed.


(Abel Toy) #8

You’d need to have a variable that would be called height of fall. Everytime your player player starts a fall, you store the y position. Then, when it touches the floor, you check the distance between current and the stored y position. If it’s larger than the height of death, you die.

To check if a player has a started a fall, I’d do something like this (untested code):

protected const DEATH_HEIGHT:Number = 500;
protected var _fallY:Number = -1000; //-1000 will be the default value for fallY not set. It's safe because it's waaaay outside the screen

override public function update():void
{
	super.update();
	
	//update code
	
	if(onFloor) //this assumes onFloor is a boolean variable that's only true when the player is colliding with the floor
	{
		if(_fallY > -1000 && (y - _fallY) > DEATH_HEIGHT)
		{
			die();
		}

		_fallY = -1000;
	}
	else if(_fallY == -1000) 
	{
		_fallY = y;
	}

	//more update code
}