Flixel Forums

development => help => Topic started by: superbany on Mon, Oct 4, 2010

Title: Wall jumping
Post by: superbany on Mon, Oct 4, 2010
I'm working on a platformer, and I'm trying to include wall jumping as a skill. To keep the player from bouncing straight up a wall, I make the character move away from the wall after every jump. However, this only seems to work when the wall is to the right of the player. Here's the code:
Code: [Select]
//[player coding]
else if (canWallJump)
{
play("slideOnWall");
if (FlxG.keys.justPressed("A"))
{
acceleration.y = 450;   //Resets gravity (lowered while sliding)
velocity.y = - acceleration.y * 0.5;  //Player jumps up
if (onLeftWall)  //Defined in the PlayState's update if colliding with the tiles on the left
velocity.x = maxVelocity.x;
if (onRightWall)
velocity.x = -maxVelocity.x;
}
}

I tried switching the order, but this only works on the right wall, and on the left wall the player  just goes straight up. Anybody see what's happening?
Title: Re: Wall jumping
Post by: initials on Mon, Oct 4, 2010
A few things to try.

Use an else if. This will stop it from running both commands.

Try adding some logs. hit the tilda key to get the dev mode on.





Code: [Select]
//[player coding]
else if (canWallJump)
{
play("slideOnWall");
if (FlxG.keys.justPressed("A"))
{
acceleration.y = 450;   //Resets gravity (lowered while sliding)
velocity.y = - acceleration.y * 0.5;  //Player jumps up
if (onLeftWall) {  //Defined in the PlayState's update if colliding with the tiles on the left
velocity.x = maxVelocity.x;
FlxG.log("On left wall, jumped");
}

else if (onRightWall)
velocity.x = -maxVelocity.x;
FlxG.log("On right wall, jumped");
}
}
}
Title: Re: Wall jumping
Post by: superbany on Mon, Oct 4, 2010
I originally did have an else if statement, but I couldn't get it to work then either. I tried running the logs, and it is only recognizing the player as being on the right wall, no matter which one they're actually on.

I'm guessing it might be in the PlayState... maybe?
Code: [Select]
Player.onRightWall = false; //Resets being on walls
Player.onLeftWall = false;
//Checks that the player is touching the tilemap, in the air, and is going down(or up slowly)
if (player.collide(tiles) && !player.onFloor && player.velocity.y >= -50)
{
if (player.collideRight)
Player.onRightWall = true;
else if (player.collideLeft)
Player.onLeftWall = true;
}
It comes after super.update(), could that do anything?
*EDIT*: Nope, putting it before makes no wall jumping possible. Never mind that last line.
Title: Re: Wall jumping
Post by: ETG on Mon, Oct 4, 2010
Doesn't Flixel by default just call collide right in it's collide left function?
Title: Re: Wall jumping
Post by: superbany on Mon, Oct 4, 2010
I don't see anything about that in the documentation...
I think I've found the problem. In PlayState.as, I have:

Code: [Select]
Player.onRightWall = Player.onLeftWall = false;
if (player.collide(tiles) && !player.onFloor && player.velocity.y >= -50)
{
if (player.collideRight)
Player.onRightWall = true;
else if (player.collideLeft)
Player.onLeftWall = true;
}
However, if I remove the "else", the game only recognizes the player as being on the left wall. I think since I'm using a FlxTilemap, it is recognizing the tiles as being over the entire game level, and so "player" will always have collideRight be true. I'll try making a requirement of having a key against the wall and see if that works.
Title: Re: Wall jumping
Post by: superbany on Mon, Oct 4, 2010
Changed it to:
Code: [Select]
Player.onRightWall = Player.onLeftWall = false;
if (player.collide(tiles) && !player.onFloor && player.velocity.y >= -50)
{
if (player.collideRight && FlxG.keys.pressed("RIGHT"))
Player.onRightWall = true;
else if (player.collideLeft && FlxG.keys.pressed("LEFT"))
Player.onLeftWall = true;
}
in PlayState.as and to:
Code: [Select]
else if (canWallJump)
{
play("slideOnWall");
if (FlxG.keys.justPressed("A"))
{
acceleration.y = 450;
velocity.y = - acceleration.y * 0.5;
if (onLeftWall)
{
velocity.x = maxVelocity.x;
FlxG.log("On left wall, jumped");
}
else if (onRightWall)
{
velocity.x = -maxVelocity.x;
FlxG.log("On right wall, jumped");
}
}
}
in Player.as, and it now works fine, with the correct rebound off each wall. Thanks for all the help!
Title: Re: Wall jumping
Post by: carls on Mon, Oct 4, 2010
Nice!
At somedays ago I was wondering in a method to do this in a flixel game.
Nice to see that the forum helps you and you got your game works...makes me happy =)
congratulations and good luck!
Title: Re: Wall jumping
Post by: Nimja on Tue, Oct 5, 2010
Actually better method is this:

override hitLeft / hitRight function, check if you're in the air and set your walljump var to something. And a sliding var to true.

1 for left,
-1 for right
0 for not sliding.

Now, the cool thing is that it will work WHILE you press left/right to slide against the wall. And if you jump, you can just multiply the velocity.x with the walljump var. (instead of more if functions)

And the walljump var can also be used for using the right animation.
Title: Re: Wall jumping
Post by: superbany on Tue, Oct 5, 2010
I'm not really understanding your train of thought. What exactly are you suggesting? [could you list your proposed code?]
Title: Re: Wall jumping
Post by: Nimja on Wed, Oct 6, 2010
Example:
http://dev.nimja.com/shadow/4

Code (all in your player.as, based on FlxSprite:
Code: [Select]
//Enable wall-jumping.
private var _wall:int = 0;
override public function hitLeft(Contact:FlxObject, Velocity:Number):void {
super.hitLeft(Contact, Velocity);
if (!onFloor) _wall = 1;
}
override public function hitRight(Contact:FlxObject, Velocity:Number):void {
super.hitLeft(Contact, Velocity);
if (!onFloor) _wall = -1;
}

//Update function
override public function update():void {
//Jump button just pressed.
var jump:Boolean = FlxG.keys.justPressed("UP");

//Jumping against wall.
if (_wall != 0 && jump) {
velocity.y = -JUMP;
velocity.x = JUMP * _wall;
}

//Reset wall-jump var, by resetting it only activates when user 'pushes' against wall.
_wall = 0;

super.update();
}

You'll have to do the animation code yourself. As I have a somewhat weird setup. My jumping mechanic is based on non-linear movement, which makes it feel much nicer. I'll post my code when it's a bit cleaner ;)
Title: Re: Wall jumping
Post by: superbany on Wed, Oct 6, 2010
I see your point, with cleaning it up and having the wall jumping mechanics inside Player.as, but I want it to only work with the current state's tiles, and it looks like your version will let them wall jump off anything. However, I did use your idea with the 0,1, or -1:
PlayState.as:
Code: [Select]
Player.onWall = 0;
if (player.collide(tiles) && !player.onFloor && player.velocity.y >= -50)
{
if (player.collideRight && FlxG.keys.pressed("RIGHT"))
Player.onWall = -1;
else if (player.collideLeft && FlxG.keys.pressed("LEFT"))
Player.onWall = 1;
}
Player.as:
Code: [Select]
if (inWater) //Handles water physics
{
acceleration.y = 100;
if (onFloor)
maxVelocity.x = 25;
else
maxVelocity.x = 100;
}
else
{
maxVelocity.x = 100;
var canWallJump: Boolean;
if (onWall && powerup_walljump) //Wall jumping is an upgrade, and won't be default
{
acceleration.y = 75; //Slower sliding down wall
canWallJump = true;
}
else
{
acceleration.y = 450;
canWallJump = false;
}
}

//[other stuff]....

else if (canWallJump)
{
play("slideOnWall");
if (FlxG.keys.justPressed("A"))
{
acceleration.y = 450;
velocity.y = - acceleration.y * 0.35;
velocity.x = maxVelocity.x * onWall;
}
}

.. and it works perfectly fine. I might want to figure out a way to get the detection for colliding with the tiles within Player.as, so the object is self-sufficient.
Title: Re: Wall jumping
Post by: Nimja on Tue, Oct 12, 2010
A sidenote:
HitLeft and HitRight are automatically called when you hit something on the side (not just maptiles, but other things as well, like vertical platforms.

And they only work WHILE you press the movement key towards them, because you only hit them once, then you fall.

So it already does it, all in the Player.as hence my solution.