Platformer Jumping Issues

Im working on a Platforming shooter and for the Life of me right now I cant figure out how to make the player jump!

granted Im working in acceleration as well so it complicates things… My code is somthing like :

byte gravity = 1;
byte jumpspeed = 10;
byte verticalAcceleration;

public void jump(){
  int y = player.getY;

  player.setY(y-verticalAcceleration); //Since negY is up

  if(verticalAcceleration <= 0){
     isFalling = true;
     isJumping = false;
  }

verticalAcceleration =  jumpSpeed - gravity;

}

I know that dosent quite work but if I had if figured out I wouldnet be asking for help!

There seems to some confusion between speed and acceleration in your code.

  • Location - where your character is
  • Speed - rate of change of location
  • Acceleration - rate of change of speed

try something like this:


	float location = 0; // lets assume ground level is 0

	float speed = 0;

	float accel = -9.8f;// gravity

	/**
	 * Call this every frame to update your location
	 * 
	 * @param deltaSeconds
	 *           The time period since the last frame, in seconds
	 */
	public void advance( float deltaSeconds )
	{
		speed += accel * deltaSeconds;
		location += speed * deltaSeconds;

		if( location < 0 )
		{ // we've hit the ground
			location = 0;
			speed = 0;
		}
	}

	/**
	 * Call this when the jump key is pressed
	 */
	public void jump()
	{
		if( location == 0 )
		{
			// this should cause us to jump about a meter high
			speed = 10;
		}
		else
		{
			// it's difficult to jump if you aren't standing on the ground
		}
	}

This may be closer to what you want. If nothing seems to happen after calling startJump(), try increasing the jumpspeed value. And if it’s still not working, try printing out the player’s y-position each frame (or step through the code in a debugger).
Simon

Edit: Posted before seeing Ryan’s reply. His looks better than mine. ::slight_smile:

final int gravity = 1;
final int jumpspeed = 10;
int verticalSpeed = 0;

// called to start a jump
public void startJump() {
  verticalSpeed = jumpspeed;
  isJumping = true;
  isFalling = false;
}

// called once per frame
public void jump() {
  int y = player.getY;
  player.setY(y-verticalSpeed); //Since negY is up

  if(verticalSpeed <= 0){
     isFalling = true;
     isJumping = false;
  }

  verticalSpeed -= gravity;
}

Im having trouble understanding your code… I feel like the Falling action and the Jumping are combined. I also have a state based collision system

touching GREEN isGrounded = true
touching blue isHitCeiling = true

so the player falls if isGrounded is false as soon as it turns true the player stop falling, and if isHitCeiling becomes true the player will immediately start falling.


float jumpSrartOne = 0; //this is the currrent Y of the player when on a platform. the Player stops falling when isGrounded = true
float jumpStartTwo = 0; //this is the current Y of the player then the player initializes a second jump


//these states change with collision between "floor" rectangles and the player.
boolean isGrounded; //True if player is on the ground
boolean isJumpOne; //True if player has jumped OR is no longer touching a "ground block"
boolean isJumpTwo; //True if player has jumped while in the air
boolean isFloating;   //True if payer has jumped twice and presses jump again
boolean isHitCeiling; //True if player has touched a ceiling block 

boolean jumpOneOut; //when true player cant initialize another single jump until grounded
boolean jupTwoOut; //when true player cant initialize another double jump until grounded



final float GRAVITY = 9.8;
final float SINGLE_JUMP_POWER = 10;
final float DOUBLE_JUMP_POWER = 5;

public void update(){
    //this is called every frame
    if(player.getY >= jumpStartOne+maxSingleJump){
          jumpOneOut = true;
    }

    if(player.getY >= jumpStartTwo+maxDoubleJump){
          jumpTwoOut = true;
    }

    if(isGrounded){
           //do Nothing
      }else if(isJumpOne && !jumpOneOut){
           singleJump();
      }else if(isJumpTwo && !jumpTwoOut){
            doubleJump();
      }else if(isFloating){
            //float();
      }else{
            //fall();
      }
}


public void jump(){
     //called on jump key pressed
     if(isGrounded){
         isJumpOne = true;
     }else if(isJumpOne){
         isJumpTwo = true
     }else if(isJumpTwo){
         isFloating = true;
     }else if(isFloating){
         isFloating = false; //shuts off floating to free fall again 
     }
}

public void groundPlayer(){
      //called when player touches a floor
      isJumpOne = false;
      isJumptwo = false;
      isFloating = false;
      isGrounded = true;
}

public void singleJump(){
        //working on single jump logic
}

public void doubleJump(){
       //working on double jump logic
}

public void float(){
      //working on Float logic.
}

public void fall(){
    //working on Fall logic
}

also fun fact my game takes a heavy influence from Vectorman for the sega genesis and My art style looks closer to the Scott Pilgrim game for the 360 Arcade. if you want to know what my inspiration was, and want to look em up.

When you reach the top of a jump, and you start moving down instead of up, then the behaviour is identical to falling. At least that’s how it works in the real world. How it works in your game is entirely up to you.

Beyond that, it’s not really clear to me what you’re stuck on (or if you’re stuck at all).

It’s probably stating the obvious, but you should get the code for a basic jump working before you start adding code for double-jumps, floating, hitting-the-ceiling, etc.

Simon

I got it! hahahaha fall is cause by Gravity which constantly increases verticalSpeed unless player isGrounded, then jump only needs to change verticalSpeed’s value in order to jump. then gravity will slowly change it back to falling, until isGrounded which sets verticalSpeed to 0.

Thank you for putting up with my crazy, I think better when I try to explain what im thinking. I get this part now.


speed += accel * deltaSeconds;
location += speed * deltaSeconds;

My thing is, how do I make That translate to pixels per frame?

You don’t, you simply render the sprite at (int)location.x

If you want to jump to a certain height, you have to either calculate the initial acceleration, or do some trial and error to find the value.

Edit: Ok I tried to implement this. This is my code:

	public void update(float deltaMilliseconds){
		float deltaSeconds = (deltaMilliseconds/100);
		verticalSpeed += GRAVITY * deltaSeconds;
		float location = verticalSpeed * deltaSeconds;
		
		r.setY(location);
		System.out.println(location);
	}

My results are interesting, because the delta value waivers back and forth… sometimes making the location change in the opposite direction rapidly Example:


0.66247994
0.11759999
0.72128
1.9315802
0.63504
28.92176
0.21364
3.4251

Check out the maths here then think of your character as a real thing in real time with real weight & gravity - that way it’ll move like it’s real! Don’t worry about frames; when you draw transform the location from ‘real’ coordinates to ‘screen’ coordinates (pixels) and draw as it is in real time.

PS use real numbers! (float)

Ill look into it, certain things I might leave out for simplicity sake, if anything I use Phys2D or somthing

Going a little further with Ryan’s code:

Position The object’s X/Y location at any given time, draw the object and calculate collision from here.
Velocity How fast the object is moving, in X/Y.
Acceleration Forces that change the velocity, like gravity or jumping.

Position is never directly updated. Velocity changes position.
Velocity is never directly updated. Acceleration changes velocity.

This means that you change an object’s position only be applying an acceleration. Jumping is a big upward acceleration. Gravity is a constant downward acceleration.

I get that, I actually have something working now. AND it includes Double Jumping and Floating… i’m working on Understanding how to play with it now and trying to make it more… friendly… its state based but Shoot me.

My issue is how to make the player not Fall Halfway through the floor. and how to make the jumps have longer hang time.

I also Realized I COMPLETELY failed in my last code snipit… I have the Values Initializing in the function. resetting them every time

private float x = 0f;
	private float y = 0f;
	
	//these states change with collision between "floor" rectangles and the player.
	private boolean isGrounded = false; //True if player is on the ground
	private boolean isJumpOne; //True if player has jumped OR is no longer touching a "ground block"
	private boolean isJumpTwo; //True if player has jumped while in the air
	private boolean isHovering;   //True if payer has jumped twice and presses jump again
	private boolean isHitCeiling; //True if player has touched a ceiling block 
	
	private Vector2f position = new Vector2f(x,y);
	private Rectangle boundingBox = new Rectangle(x,y,64,128);
	
	private final float MAX_LEFT_FORCE = 9.8f;
	private final float MAX_RIGHT_FORCE = 9.8f;
	private final float MAX_SINGLE_JUMP_FORCE = 9.8f;
	private final float MAX_DOUBLE_JUMP_FORCE = 9.8f;


	private final float GRAVITY = 9.8f;
	
	private float gravityMod;
	private float jumpForce = 0;
	
	private float leftForce = 0;
	private float rightForce = 0;
	
	private float verticalVelocity = 0f;
	private float horizontalVelocity = 0f;

	
	
	public void update(float deltaMiliseconds){
		float deltaSeconds = (deltaMiliseconds/1000);
		verticalVelocity += (GRAVITY * gravityMod) * deltaSeconds;
		verticalVelocity += jumpForce * deltaSeconds;
		position.y += verticalVelocity *deltaSeconds;
		horizontalVelocity += leftForce * deltaSeconds;
		horizontalVelocity += rightForce * deltaSeconds;
		position.x += horizontalVelocity *deltaSeconds;
		boundingBox.setX(position.x);
		boundingBox.setY(position.y);
	}
	
	public void jump(){
		if(isGrounded){
			jumpForce = -2;
			isGrounded = false;
			isJumpOne = true;
		}else if(isJumpOne){
			jumpForce = -2;
			isJumpOne = false;
			isJumpTwo = true;
		}else if(isJumpTwo){
			gravityMod = .1f;
			isJumpTwo = false;
			isHovering = true;
		}else if(isHovering){
			gravityMod = 1f;
			isHovering = false;
		}else{
			
		}
	}

Any Opinions? Suggestions?