[solved] Implementing 2D platformer wall jumping

Hey JGO, I got bored and decided to goof around and make a player that has physics. (Mass, gravity, velocity etc)

I’m wondering how would I implement wall jumping?

(Video on what I’m talking about: Short youtube video)

Here’s a picture, if anyone needs code snippets from the platformer let me know :slight_smile:

Code snippets:


/** Update method */
public void tick() {
	// Handles w,a,s,d, space_bar etc
	processInput();

	// Handles jumping/falling/velocity etc
	processPhysics();

	// Handles collision (x<=1 etc)
	processCollision();
}



/** Process collision method */
private void processCollision() {
	// Player has somehow reached top of level o.0
	if(y <= 0) {
		y = 0;
		jumping = false;
		jumpTimeSoFar = - 1;
		jumpTimeStart = - 1;
		jumpTicks = 0;
		fallTimeSoFar = - 1;
		fallTimeStart = System.currentTimeMillis();
		falling = true;
	}
	if(x <= 1) {
		// Player is touching the left wall
		x = 1;
		leftWallCollision = true;
	}
	if((x + width) >= (Launcher.WIDTH - 11)) {
		// Player is touching the right wall
		x = (Launcher.WIDTH - 11) - width;
		rightWallCollision = true;
	}
}

Thanks for any help/feedback JGO, I only found 1 post on our forums relating to wall jumping and I took all the knowledge I can from it and am now stuck :S

If player is colliding with a wall and he presses a certain key / key combination, increase / decrease x and y velocities, or change the speed (depends on how you use those values)

First time getting wall jumping to work / trying to get it to work.

Thanks trollwarrior1 it’s working now ^___^


// Wall jumping implementation
if(jumpKeyDown && falling) {
	if(rightWallCollision && movingLeft && ! movingRight) {
		performWallJump();
	} else if(leftWallCollision && movingRight && ! movingLeft) {
		performWallJump();
	}
}



private void performWallJump() {
	falling = false;
	fallTimeSoFar = - 1;
	fallTimeStart = - 1;
	jumpTicks = 0;
	jumpTimeSoFar = - 1;
	jumpTimeStart = System.currentTimeMillis();
	jumping = true;
}

Should I use System.nanoTime() for my jump/fall starting time?
Thanks for the feedback :slight_smile:

No. Count game ticks.

Never use system timing calls for timiing game logic.

I involve delta for movement, didn’t know I needed delta when keeping track of a operations start/end time. :o :o


private void handleJumping() {
	jumpVelocity = 0.0001 * delta;
	// Some code to simulate mass/gravity etc
	y -= jumpVelocity;
	jumpTicks += jumpVelocity;
	jumpTimeSoFar = System.currentTimeMillis() - jumpTimeStart;
}

Well think of this way, I am in a dungeon that contains 32 monster spawners that spawn monsters randomly at intervals between 5-10 seconds.

Now I pause my game, go away for 5 minutes and unpause it. Suddenly 32 monsters :p. Use delta.

I would just keep track of the System.currentTimeMillis() when paused and continue that time once unpaused, I wouldn’t poll on the stored System.currentTimeMillis() time assigned before the pause.

Can you advise me on how to involve delta with the timing operation on my jump/fall start time? o.0

Updated my reply, I don’t know what I’m doing XD

First off, I would like to know why in the hell you want to keep track of the time when you started to jump and started to fall, that seems weird. Unless you are putting some sort of delay between jumps or whatever.

Imo the best way to handle such things is using a FSM and components for your entity, such as ActionJump, ActionAttack etc. I’ll write up an example, give me 10 :p.

Ok here is what I came up with, I kinda forgot why I was doing this and started to actually code a class…

Standard FSM to handle the states, the FSM is probably familar to you but regardless I implemented it because it allows you to manage components of entities nicely:


public class Player {

	/* That's right, we on the moon */
	float gravity = 1.622f;

	/*
	 * States are just purely data, they do not do anything on their own.
	 */
	public enum PlayerState {
		RUNNING, JUMPING, FALLING;
	}

	/*
	 * This is the current state the player will be in, we change this to
	 * determine what our update method does
	 */
	PlayerState currentState;

	/*
	 * I presume you know this basic stuff, putting it in here mostly for sugar
	 * to give the class a more solid look
	 */
	public float acceleration;
	public float maxSpeed;
	public Vector2 velocity = new Vector2();

	JumpAction jumpAction;

	public Player() {
		jumpAction = new JumpAction(this);
	}

	public void update(float delta) {
		/* Push the player down with gravity */
		velocity.y -= gravity;

		/*
		 * Check jump attempts, since we can jump in any state (maybe, assuming
		 * we can do 1 jump even when falling), jump the wee bastard
		 */
		if (Gdx.input.isKeyPressed(Keys.SPACE)) {
			currentState = PlayerState.JUMPING;
			jumpAction.execute();
		}

		/*
		 * Now we do a switch statement on our current state and decide what to
		 * do
		 */
		switch (currentState) {
		case RUNNING:
			/*
			 * We probably shouldn't do this here but whatever, check for input
			 * and apply acceleration in the correct direction
			 */
			if (Gdx.input.isKeyPressed(Keys.A)) {
				if (Math.abs(velocity.x) < maxSpeed)
					velocity.x += -acceleration;
			} else if (Gdx.input.isKeyPressed(Keys.D))
				if (Math.abs(velocity.x) < maxSpeed)
					velocity.x += acceleration;

			break;
		case JUMPING:
			jumpAction.update(delta);

			// Do other things, maybe check for certain collision types or wait
			// for callbacks on certain surfaces. Whatever really, depends how
			// OOP you want to be.

			/*
			 * Ama gonna check if the Y velocity has started to go down as
			 * opposed to up, then like add fall damage or something
			 */
			if (velocity.y < 0)
				currentState = PlayerState.FALLING;

			break;
		case FALLING:
			// Maybe update a falling component
			// Check for collisions so we can flag the chracter as grounded and
			// change back to another state
		default:
			break;
		}
	}

}

The JumpAction class, handles jump timing and the jump itself. It could do a lot more, such as setting flags on the entity for jumps. After all, it is in charge of jumps:


public class JumpAction {
	
	Player player;
	
	/*
	 * This is the amount of time we have been in this state, don't mix up this
	 * with the FSM, it has nothing to do with it. It is simply the timing mechanism
	 * for the state of this action
	 */
	float stateTime;

	public JumpAction(Player player) {
		this.player = player;
	}
	
	public void execute(){
		/* Apply an upwards force to the players velocity, instantly */
		player.velocity.y = 10;
	}
	
	public void update(float delta){
		/* There, timing done. Is that simple */
		stateTime += delta;
		
		// Do something with this timing thing
	}

}

I keep track of when the fall started & how long it’s been happening so I can simulate mass/gravity/velocity.

  • The longer the fall continues the faster we will fall. (Mass)
  • Start out fall @ last known jump speed, slowly increase the fall speed as player falls.

It works lovely TBH, for jumping & falling.

  • The longer the jump continues, velocity is decreased until peak is reached.
  • Start out the jump fast, slowly decreasing the speed the higher the player reaches.

Here’s my falling method, if you notice anything out of line / things that should be done in a different manner please let me know :slight_smile:


/** Process physics method */
private void processPhysics() {
	if(jumping) {
		handleJumping();
	} else if(falling) {
		handleFalling();
	}
}



/** Falling method */
private void handleFalling() {
	jumping = false;
	jumpTimeSoFar = - 1;
	jumpTimeStart = - 1;
	jumpVelocity = 0;

	// The more the player weighs, the faster he falls
	for(int i = 0; i < mass; i ++ ) {
		// For every point in mass:
		fallVelocity += 0.00001 * i;
	}

	// The more gravity, the faster the player is pulled to ground
	for(int i = 0; i < gravity; i ++ ) {
		// For every point in gravity:
		fallVelocity += 0.001 * i;
	}

	// The longer the fall continues, the faster the player falls
	for(int i = 0; i < (fallTimeSoFar / 10); i ++ ) {
		// for every 10ms in 'fallTimeSoFar':
		fallVelocity += 0.0001d * i;
	}
	if(y < GROUND_LEVEL) {
		y += fallVelocity;
		fallTimeSoFar = System.currentTimeMillis() - fallTimeStart;
	} else if(y >= GROUND_LEVEL) {
		jumpTimeStart = - 1;
		jumpTimeSoFar = - 1;
		fallTimeStart = - 1;
		fallVelocity = 0;
		System.out.println("Fall completed in " + fallTimeSoFar + " ms");
		fallTimeSoFar = - 1;
		falling = false;
	}
}

Yeah, put that method into a component and give that component to entities that are influenced by gravity. Like what I have done above.

EDIT:

I don’t think you need time to do what you are doing, is it purely to decrease the rate of acceleration of the object as it nears terminal velocity? In that case yes, you need it but being honest, not worth the effort. No one is going to notice that as you get faster your rate of acceleration gets slower, most games don’t have objects that can reach those speeds and still been seen. If the camera is moving with it (which it pretty much would have) then the effect will be practically unnoticeable.

I am going to call you out on this, don’t confuse Velocity/Speed/Acceleration.

All are different, Acceleration is the “rate at which the velocity changes”, velocity and speed are similar. However, velocity has a magnitude and a direction, speed only has the magnitude. So you can think of speed as the velocities magnitude or “length”.

Separating these can help you clean up some code, such as this:



float maxSpeed = 10; // m/s
float acceleration 5; // ms/s
Vector velocity = new Vector2();

// So we can instantly give our velocity some sort of direction, going at max speed by doing the following
velocity.x = maxSpeed * cos(angle);
velocity.y = maxSpeed * sin(angle);

//Or we could do it gradually
velocity.x += acceleration * cos(angle);
velocity.y += acceleration * sin(angle);



Basically the point I am slabbering on about is that knowing the difference instantly gives you a bunch of readable variables that everyone will understand.

EDIT: Ignore me if I sound grumpy, 1am -_- :D, nn lol.

Try something based on this:


public void jump()
{
    if(onGround() || onWall())
    {
        dy = JUMP_SPEED;
    }
}

public void update()
{
    dy -= GRAVITY;
    y += dy;

    if(onGround())
    {
        dy = 0;
    }
}

Try making a “Jumping test case”, I don’t want my player zipping up than zipping down at a set speed, just looks and feels cheesey.

The whole point of this “test platformer” I’m making is to simulate gravity/mass and have it effect velocity. (up/down)

What I had first which is cheap and looks horrible, no mass/gravity involved:
(Wish I knew how to take a .gif to show you how much of a impact this has on the standard jumping VS. gravity/mass involved in the jump)


if (jumping) {
	if (jumpTicks < jumpHeight) {
		jumpTicks++;
		y--;
	} else if (jumpTicks >= jumpHeight) {
		jumping = false;
		jumpTicks = 0;
		falling = true;
	}
} else if (falling) {
	if (!onGround) {
		y++;
	} else if (onGround) {
		falling = false;
	}
}

Once I added the simulation of gravity/mass the jumping/falling started looking way smoother.
Once again the whole point of my “platformer test” is to simulate mass/gravity and have it effect the players jump/fall velocity accordingly.

  • Thanks for the feedback guys, I’ll work on re-writing it without System.currentTimeMillis().
  • Thanks HeroesGraveDev.

Actually using:


velocity.y -= gravity;

Should give you a gradually increase drop rate, granted there will be no slow down as it approaches terminal velocity. Which would suck for say, a car lol. If it just accelerated at rate of say, 100ms/s and when it got to it’s max speed it suddenly just stopped accelerating, that would look shite :D.

EDIT: Could you not use a logarithm with the data you have? To control the rate of acceleration depending on the current velocity?

Please don’t compare my jumping simulator to a car simulator LOL, of course they’d be made different yo…

I’m making a mass/gravity simulator:
More mass, faster the fall.
Longer the fall, fall rate increases.
etc…

Thanks for the feedback though, I’m happy with what I have at the moment.
As problems arise I’ll fix them :stuck_out_tongue:

I will look into this though :point:


velocity.y -= gravity;

Would it be wise to use a java.util.Timer for this?

NOTE: Not using seconds (As the delta suggestion would) I’m using milliseconds.

  • Thanks for all the feedback so far guys. ;D

A car falling is subject to the same physics as a person jumping.

Incorrect. Gravity is ~10N per kg, or 10m/s

Until the air resistance reaches 10N, then the fall rate decreases until it hits 0 at terminal velocity. Although most platformers don’t actually implement this and instead just stop accelerating at a certain speed.

No.

Have a look at the code I posted above. It’s extremely simple and it solves your problem.

Yes 2 objects, human or not will have the same characteristic “Weight”, I thought he meant a car accelerating like on a drag strip lol >___<

So you’re saying a 400 pound man and a 100 pound man will fall at the same speed??
Erm ok…