Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

How can I have the player jump higher if the jump key is held down longer? I am currently just reducing gravity as long as the key is held and the player is jumping, but this looks odd.

share|improve this question
    
maybe just by some modification in how much you reduce gravity you get a better jump action. –  Ali.S Jun 7 '11 at 4:02
    
@Gajet That is rather clunky and seems an odd way of doing it. –  The Communist Duck Jun 7 '11 at 12:54
    
Hmm you saying reducing gravity doesn't imply that you are using a physics engine. Is this the case? Are you using Impulses to jump? –  Jonathan Connell Jun 7 '11 at 13:58
    
There is no physics engine, and I'm not using Impulses –  Jcubed Jun 7 '11 at 16:04
    
In which case, how does you player fall? Do you just translate his position according to a movement * jump * gravity vector? –  Jonathan Connell Jun 9 '11 at 15:24

4 Answers 4

up vote 8 down vote accepted

First you need to decide what you want the jump to look like.

In real life, the jump height is decided at the moment that you leave the ground. You can't keep jumping higher while you're already in mid-air.

So if you can control your jump height while you're already in the air, you're going to get some sort of "jet-pack"-like effect.

I seem to remember a sidescroller that had two different jump heights, I think it was one of the super mario games. The higher jump occured when you held the jump button, and the jump was then actually a two part jump, starting with the initial regular jump, followed by a second impulse that took you higher.

So, what do you want your jump to look like? What sort of control do you want the player to have over the jump?

What I would start with is this:

Leave gravity alone (i.e. never change it). When a player presses the jump button, apply the jump force as long as the player is pressing the jump button (up to some time limit). Then when the player releases the jump button, he cannot apply any jump force again (i.e. he can't initiate a jump again) until he touches the ground first, at which point jumps are re-enabled.

share|improve this answer
7  
+1 Leave gravity alone. –  Leftium Jun 7 '11 at 5:30
    
I tried that, and I get the jetpack effect. I was wondering if there was any way to avoid that. –  Jcubed Jun 7 '11 at 6:03
1  
Maybe not the game you have in mind, but in Super Mario 2 you jumped higher by ducking a bit before jumping. (Which makes a certain amount of intuitive sense, since you don't jump very far if you try to do it direct from a standing position.) –  Darien Jun 7 '11 at 7:51
3  
Jcubed: Instead of adding force to velocity, try adding the force directly to position. Then the player will move linearly up, instead of accellerating up. –  Olhovsky Jun 7 '11 at 8:59
1  
I do this all the time, just keep the time during which you set the jumping upwards velocity by holding down the button short enough so it's not a noticeable jet pack effect - then it'll be like Super Mario pretty easily, with a few magic number tweaks. Don't make the "force" smaller, just keep resetting the velocity to maximum jumpspeed until the jumpHigherTime expires or the player releases the button... also, I feel super meat boys jumping to be imprecise and annoying, as is any platform jumping that only relies on a physics engine ;p –  Oskar Duveborn Dec 1 '12 at 18:42

I have seen some people do this:

  1. Create a variable (I'll call it jumpTime) (number/double/float). When the jump key is pressed, set jumpTime to some number (i.e. 0.5. This will be the number of seconds that holding the jump key will have affect).

  2. Then, for every step, set the velocity to jumpTime multiplied by some other number, and decrease jumpTime by delta (the time difference between each step).

  3. Repeat that until jumpTime reaches zero or below, or when the player releases the jump key. After that happens, use normal physics (apply a constant negative acceleration until the player reaches the ground).

You may need to use trial and error (or "logical guessing") to find suitable values for those "some number"s, unless you know how to do it.


UPDATE: I found the trick that makes the jump a bit more realistic (since it is originally slow going up but then fast going down). Infinite Mario also uses the following line (293 of Character.js of JavaScript version)... this.Ya *= 0.85; This is simply like "air drag", and limits/slows down the velocity of the character when in mid-air. So every frame, multiply the y-velocity (vertical speed) by a number less than one so that it slows down when falling back down (and therefore both going upwards and going downwards during a jump will be similar and more realistic). I know, I'm bad at explaining...

When the character jumps using the method I originally described above, it "rises up" faster then "falling back downwards". The drag, however, slows down the vertical speed. Since we set the vertical speed to be proportional to the jumpTime every frame, this drag doesn't have much affect on the first half of the jumping. However in the next half (falling back downwards), the vertical speed is not set every frame, but simply added by another number (in this case it is the gravitational constant). Therefore, the drag takes effect in the falling, and since it decreases the speed (in any direction), it slows down the fall, making it similar to the first half.

There are other ways to solve this problem though, like decreasing the affect of gravity on the character as it falls. However, we need to find how much we should reduce the gravity.


Case Study: Infinite Mario

This is what I found (from line 206 of Mario.java by Markus Persson (Notch)):

    if (keys[KEY_JUMP] || (jumpTime < 0 && !onGround && !sliding))
    {
        if (jumpTime < 0)
        {
            xa = xJumpSpeed;
            ya = -jumpTime * yJumpSpeed;
            jumpTime++;
        }
        else if (onGround && mayJump)
        {
            world.sound.play(Art.samples[Art.SAMPLE_MARIO_JUMP], this, 1, 1, 1);
            xJumpSpeed = 0;
            yJumpSpeed = -1.9f;
            jumpTime = 7;
            ya = jumpTime * yJumpSpeed;
            onGround = false;
            sliding = false;
        }
        else if (sliding && mayJump)
        {
            world.sound.play(Art.samples[Art.SAMPLE_MARIO_JUMP], this, 1, 1, 1);
            xJumpSpeed = -facing * 6.0f;
            yJumpSpeed = -2.0f;
            jumpTime = -6;
            xa = xJumpSpeed;
            ya = -jumpTime * yJumpSpeed;
            onGround = false;
            sliding = false;

            facing = -facing;
        }
        else if (jumpTime > 0)
        {
            xa += xJumpSpeed;
            ya = jumpTime * yJumpSpeed;
            jumpTime--;
        }
    }
    else
    {
        jumpTime = 0;
    }

The javascript version is basically the same https://github.com/robertkleffner/mariohtml5/blob/master/code/character.js

This is similar to the suggestion from Olhovsky, but in this case the force will be proportional to the amount of time passed after the player pressed the jump key.

My javascript version:

    if ( onGround && jump && !jumped ) {
        jumpTime = maxJumpTime;
        onGround = false;
        jumped = true;
        this.vel.y = jumpTime * jumpConstant;
        A = true;
    } else if ( !onGround && jump && jumpTime > 0 && !released ) {
        jumpTime -= evt.delta;
        this.vel.y = jumpTime * jumpConstant;
        B = true;
    } else if ( !onGround && ( !jump || jumpTime <= 0 ) ) {
        this.vel.y -= gravityConstant * evt.delta;
        jumpTime = 0
        released = true;
    } if ( this.pos.y < 0 && !A && !B ) {
        onGround = true;
        released = false;
        this.pos.y = 0;
        this.vel.y = 0;
    }
    if ( !jump && onGround ) jumped = false;

However, some values for the constants (e.g. "gravityConstant" and "jumpConstant") will give an unrealistic jump though. But sometimes games don't have to be realistic! (update see the update section above)

This question is more than a year old already, but I hope this helps!

share|improve this answer

As Olhovsky has said, the jump height is decided the moment you leave the ground, not after that.

If you really want to avoid the jetpack effect, I only see two ways: a key combination to jump higher, or fundamentally changing the way the jump key works:

Instead of making the player jump as soon as the key is pressed, delay the jump until the key is released. So basically the duration of the key press controls how much spring tension in the player’s legs is built up, and subsequently released.

Of course, this fundamentally alters the game mechanics and may be unfamiliar for the player. But the effect could be quite interesting and may well be worth the unfamiliarity.

share|improve this answer
2  
I think I remember playing some platformer with exactly that mechanic - don't leave the ground until you've "charged" the jump. With some pretty animations (like dust cloud growing at the character's feet) this can be done to feel intuitive. –  Jari Komppa Jun 7 '11 at 13:31

I've found another solution in David Gouveia's answer to the question " How to make a character jump?"

Summary:

His idea was to set a velocity when the player pushes down the jump button. In every frame it only computes the gravity. However, when the player releases the button, it sets the velocity to a smaller value if the velocity is greater than it. The velocity is only decremented each frame by the gravity.

I shouldn't steal his answer, so go ahead and read his post. His solution is under the "Variable Height Jump" section.

So really people came up with many different ways to solve this problem...

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.