Jumping Physics

Started by
3 comments, last by BeerNutts 10 years, 8 months ago

Hello, I am working on some physics in my game and more specifically jumping. When I it the jump button I set a bool m_bJumped to true so that in the update function I can alter the Y velocity:


if(event.key.code == sf::Keyboard::Z && m_sfVelocity.y == 0) m_bJumped = true;

Then in the update function:


...

if(m_bJumped == true) {
		
	m_sfVelocity.y = -300 * deltaT.asSeconds();
	m_bJumped = false;
}

...

m_sfVelocity.y += 5 * deltaT.asSeconds();

...

if(checkCollision(std::floor(m_sfEntity.getPosition().x / 32), std::floor((m_sfEntity.getPosition().y + 
                   m_sfSize.y + m_sfVelocity.y) / 32), lvl) == true) 
m_sfVelocity.y = 0;



The check collision function checks to see if the tile below the player is solid and if so to set the Y velocity to 0 so it will stop moving down. The jumping works but is is very random. Some times it jumps 7 tiles and some times it jumps 9. One time it jumped all 20 tiles. How do I make the jumping more stable? Thanks.

EDIT: The deltaT is a sf::Time object that is passed in every frame.

Advertisement

You don't need to multiply -300 by deltaT.asSeconds(). You want the jump velocity to be a constant (-300) and then use delta time to update it (as you are).

You are seeing the effect of slightly different frame times which is making the velocity start at different values.

"There will come a time when you believe everything is finished. That will be the beginning." -Louis L'Amour

So your using delta time...

I would do it like this


int AmountTimeGoingUpOnJump= 250;//Miliseconds THIS WILL VARY ON YOUR DECISION
bool isJumping = false;//If this is true, increase his velocity until he meats max treshold, else decrease it until he meats max treshold or meats a solid surface
int unitPosX, unitPosY;
SomeTimeHoldingClass StartJumpTime;//Time when the jump started
SomeTimeHoldingClass GetCurrentTime();//returns current time
 
//Now the user presses "Z" call startJump.
StartJump(){StartJumpTime = GetCurrentTime();}
LoopJump(){if(CurrentTime - StartJumpTime > AmountTimeGoingUpOnJump){isJumping = false;/*No velocity increase, also somwhere check if nothing bellow him to decrease velocity*/} 
else {isJumping = true, /*make his velocity increase*/}}

if(m_bJumped == true) {
        
    m_sfVelocity.y = -300 * deltaT.asSeconds();
    m_bJumped = false;
}

Also as it stands m_bJumped=false sould be set when the "unit" meats ground so you prevent air jumps

m_sfVelocity.y += 5 * deltaT.asSeconds();

Here you sould check for max velocity if you want.

I mean the more you jump the faster you go?

You go half way speeding(Going up only X amount of time) then you still going up but slowing down, until the velocity goes from + to - and then you start to decline

You don't need to multiply -300 by deltaT.asSeconds(). You want the jump velocity to be a constant (-300) and then use delta time to update it (as you are).

You are seeing the effect of slightly different frame times which is making the velocity start at different values.

I changed it to this and the jump is a lot more stable.

So your using delta time...

I would do it like this


int AmountTimeGoingUpOnJump= 250;//Miliseconds THIS WILL VARY ON YOUR DECISION
bool isJumping = false;//If this is true, increase his velocity until he meats max treshold, else decrease it until he meats max treshold or meats a solid surface
int unitPosX, unitPosY;
SomeTimeHoldingClass StartJumpTime;//Time when the jump started
SomeTimeHoldingClass GetCurrentTime();//returns current time
 
//Now the user presses "Z" call startJump.
StartJump(){StartJumpTime = GetCurrentTime();}
LoopJump(){if(CurrentTime - StartJumpTime > AmountTimeGoingUpOnJump){isJumping = false;/*No velocity increase, also somwhere check if nothing bellow him to decrease velocity*/} 
else {isJumping = true, /*make his velocity increase*/}}

if(m_bJumped == true) {
        
    m_sfVelocity.y = -300 * deltaT.asSeconds();
    m_bJumped = false;
}

Also as it stands m_bJumped=false sould be set when the "unit" meats ground so you prevent air jumps


m_sfVelocity.y += 5 * deltaT.asSeconds();

Here you sould check for max velocity if you want.

I mean the more you jump the faster you go?

You go half way speeding(Going up only X amount of time) then you still going up but slowing down, until the velocity goes from + to - and then you start to decline

This would work and thank you for the suggestion, but I wanted the entity to act like a projectile. Thanks for the help.

You almost have it just right I believe. However, I would re-think the logic behind allowing the player to jump. Currently, you allow them to jump if their y velocity is 0.

What happens when the player reaches his jumping apex , just before he starts to fall? Well, the velocity might be 0. and he'd have the ability to jump again right there.

My suggestion would be to allow a player to jump when he's touching the ground. And, why not go ahead and set his y velocity when you set the jump variable to true? Something like this:

void TPlayer::Update(float deltaSeconds)
{
  ...
  if (IsJumpButtonPressed() && IsPlayerOnGround()) {
    Velocity.Y += JUMP_VELOCITY;
  }
  ...
  // Apply gravity
  Velocity.Y -= GRAVITY_VELOCTY * deltaSeconds;
  ...
  // Later in the code, you adjust the player's position and also check if he's on the ground
  Position.X += Velocity.X;
  Position.Y += Velocity.Y;
 
  if (IsPlayerOnGround()) {
    Velocity.Y = 0;
  }

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

This topic is closed to new replies.

Advertisement