Best way to handle wall jumping?

I’m creating a game where the player ascends a tower by wall jumping his way to the top. When the player has collided with the right wall they can only jump left and vice versa. Here is part of my current implementation:


    if(wallCollision() == "left"){
        player.setPosX(0);
        player.setVelX(0);
        ignoreCollisions = true;
        player.setCanJump(true);
        player.setFacingLeft(false);
    } else if (wallCollision() == "right"){
        player.setPosX(screenWidth-playerWidth*2);
        player.setVelX(0);
        ignoreCollisions = true;
        player.setCanJump(true);
        player.setFacingLeft(true);
    } else{
        player.setVelY(player.getVelY() + gravity);
    } 

and


private String wallCollision(){
    if(player.getPosX() < playerWidth && !ignoreCollisions)
        return "left";
    else if(player.getPosX() > screenWidth - playerWidth*2 && !ignoreCollisions)
        return "right";
    else{       
        timeToJump += Gdx.graphics.getDeltaTime();
        if(timeToJump > 0.50f){
            timeToJump = 0;
            ignoreCollisions = false;
        }
        return "jumping";
    }
}

If the player is colliding with the left wall it will switch between the states left and jumping repeatedly due to the variable ignoreCollisions being switched repeatedly in collision checks. This will give a chance to either jump as intended or simply ascend vertically instead of diagonally.

I can’t figure out an implementation that will reliably make sure the player jumps as intended. Does anyone have any pointers?

If no-one can help me with this particular example of code can they provide me an example of a wall jump that works?

i dont really understand what your trying to do. So lets asume the player hits the left wall.
What do you want to happen ?

[quote]they can only jump left and vice versa
[/quote]
does that mean automaticly ? or will you wait for a player input to start the jump ? and what is supposed to happen while you wait for the player input ?
Or do you want the player to fall down until the player gives the input to jump ?

I’ve taken a video to show how my game currently works here. It works sort of how I want except if you notice at 8 seconds on the left wall when I click he moves up the wall. I know the issue is because of the logic in my code.

Referring to the snippet I provided imagine you’re currently flying towards the left wall. The boolean ignoreCollisions will bet set to false because you want to collide with the wall. When you collide with the wall the wallCollision() method returns “left” which stops movement and sets ignoreCollisions to true because you want to ignore the fact you’re now in collision boundaries with the wall. By ignoring the collision you can jump to the opposite wall. The problem then arises that whenever wallCollision() is called it will switch between returning “left” and “jumping” because ignoreCollision will keep getting switched between true and false. This is what causes the vertical jump at 8 seconds.

I know this is very hard to understand and my code is inherently flawed so I need another way to go about it.

now i hope i understand you correctly.
i would do it like this in your loop:

first - Check for collisions - if the player collides with a wall you set a boolean to true that states this fact.
for example “collisionLeft = true” , or “collisionRight = true”, also stop the xVel if you collide.
second - apply the gravity and playermovement:

and simply perform checks there, so for example if theres a “collisionLeft”, only allow the player to jump right and vice versa.
Also only allow the player to jump (basicly setting a xVel), if he is colliding with a wall, but in the opposite direction.

ive tryed to do some code here for your case:


public void movePlayer(){
yVel = xyz;
if (collisionLeft && !collisionRight && Gdx.input.isKeyPressed(Keys.D)) { xVel= 15; }  // for example ^^
 if (!collisionLeft && collisionRight && Gdx.input.isKeyPressed(Keys.A)) { xVel= -15; }// for example ^^
}

ofc in order for that to work, you will need to set the collision booleans like ive wrote before and set the xVel to 0 as soon as you collide with a wall.
btw ive wrote that on my phone, so im sure there are some bugs in there, but i think you will understand what i mean. :wink:

I believe I have something similar to what you have wrote. Whenever the user clicks then this piece of code is executed:


if(player.canJump(screenWidth, playerWidth)){
				if(player.isFacingLeft())
					player.setVelX(-36.0f);
				else
					player.setVelX(36.0f);
				player.setVelY(25.0f);
			}

the canJump() method looks like this


	public boolean canJump(float screenWidth, int playerWidth) {
		if(posX <= playerWidth || posX >= screenWidth - playerWidth*2 || posY < 0)
			return true;
		else
			return false;
	}

I believe it does something similar to what you said?

yeah looks that way. does it work ? :smiley:

EDIT
ofc it would make sense to check for collision before doing this stuff.
and only setting xVel to 0 if you hit a wall.

No, that’s how I had it originally. The problem is to do with the ignoreCollisions variable that keeps getting switched when wallCollision() is called. Here is my full code. Maybe this will help better than my explanations!

What is the significance of ignoreCollisions? Remove it.

try the following :
create 2 Instance Variables:


boolean collisionLeft = false;
boolean collisionRight = false;

change your code here like this :

		if(wallCollision() == "left" && !collisionLeft){
			player.setPosX(0);
			player.setVelX(0);
			player.setFacingLeft(false);
			collisionLeft = true;
			collisionRight = false;
		} else if (wallCollision() == "right" && !collisionRight){
			player.setPosX(screenWidth-playerWidth*2);
			player.setVelX(0);
			player.setFacingLeft(true);
			collisionRight = true;
			collisionLeft = false;
		} else{
			player.setVelY(player.getVelY() + gravity);
		} 

now in my opinion the biggest problem is that you do more than you would have to do. And since your “updateRunning()” gets called really often, you set your xVel back to 0 before youve even moved out of the wall. If you would remove all the unused Stuff you could solve this really easily. But for your case, these changes i did here COULD fix that. But im not sure since i havent looked at your whole code. But you can try it. :smiley:

EDIT
and also

do that ;D

Thank you so much! It now works as desired!

Remember to compare strings using [icode].equals()[/icode] and not [icode]==[/icode] :slight_smile: