1
\$\begingroup\$

Problem:
I'm trying to implement basic jumping to my 2D game engine, but have failed several times.
Basically what I've done so far is disabling gravity and using a separate function moving the player upwards. The problem with this is that it looks really bad.

I've checked a lot of threads about this, and found one way that should work.
This is by simply adding another force going upwards against gravity. This force should be greater than gravity, but should decrease until the force of gravity is greater again.

The problem is that I am unable to implement it.

My code is written in Javascript and uses html5 canvas for rendering.
Note! This code is only a part of the whole engine.
As for variables:
c_objects - array with all objects the player can collide with
player - object literal with position, width, movement speed, velocity, and the velocity multiplier.

Pseudo-code is good for me, but i'd love an answer in JS.

Code:

// physics module collision
function collision(obj_1, obj_2) {
    var collision = Boolean(
        obj_1.x <= (obj_2.x + obj_2.width)
        && obj_2.x <= (obj_1.x + obj_1.width)
        && obj_1.y <= (obj_2.y + obj_2.height)
        && obj_2.y <= (obj_1.y + obj_1.height)
    );

    // return position booleans
    return {
        collision: collision,
    };
};    

function movement(x, y) {
    new_pos.x = player.x + x;
    new_pos.y = player.y + y;
    // check collision for all objects in collision array
    var index;
    var collisions = new Array();
    for (index = 0; index < c_objects.length; ++index) {
        var new_collision = engine.collision(new_pos, c_objects[index]);
        collisions[index] = new_collision.collision;
    }
    var it_collides = collisions.indexOf(true) >= 0;
    if (it_collides == false) {
            player.x += x;
            player.y += y;
    }
}


// velocity & gravity module for adding gravity to an object
function gravity(modifier) {
    if (player.gravity == true) {
        var x = 0;
        var y = 0;
        x = 0;
        y = +(player.velocity * modifier);
        engine.movement(x, y);

        if (player.velocity <= 450) {
            player.velocity = (player.velocity * player.velocity_m);
        }
        else {
            velocity = 450;
        }
    }
};
\$\endgroup\$
3
  • \$\begingroup\$ With a jump, I'd go with altering velocity directly. Then that velocity is changed by gravity until you collide with the floor. Changing the acceleration at the start seems a bit over the top. \$\endgroup\$
    – Polar
    Commented Dec 7, 2013 at 17:09
  • \$\begingroup\$ Correct, the solution was to add another function with higher velocity than the gravity, this velocity decreases over time which results in the player landing again. Only problem now is detecting when the player can jump or not. \$\endgroup\$
    – crazymage
    Commented Dec 7, 2013 at 18:20
  • \$\begingroup\$ Check if the player already has a vertical velocity. If they do, no jumping. Horizontal velocity is fine, as they could be running. \$\endgroup\$
    – Polar
    Commented Dec 8, 2013 at 21:52

1 Answer 1

1
\$\begingroup\$

The solution was to add another function with higher velocity than the gravity, this velocity decreases over time which results in the player landing again.

Example of this function:

var player = {
    speed: 180, // movement speed in pixels per second
    velocity: 400, // sets the falling speed / gravitational pull
    velocity_m: 1.02, // sets the velocity multiplier
    anti_veloctiy: -850,
    anti_veloctiy_m: 0.98,
};
    // jump
    function jump(modifier) {
        if (player.jump == true) {
            // multiply the anti_velocity
            player.anti_veloctiy = player.anti_veloctiy * player.anti_veloctiy_m;
            var x = 0;
            var y = 0;
            x = 0;
            y = (player.anti_veloctiy * modifier);
            engine.movement(x, y);
        }
    },

Call this function from your main loop. Then when your user presses space change
the value of player.jump to true.

Only thing left now is to detect if the player has landed and set player jump to false again. This can be done simply by adding some code to the collision, and movement function. We simply add another argument called height_margin which offsets the collision detection by a few pixels to check if the player is on ground.
The changes are marked with change.

// physics module collision. height_margin is a extra option usually used for checking if the player is on the ground or not.
collision: function collision(obj_1, obj_2, *height_margin*) {
    var collision = Boolean(
        obj_1.x <= (obj_2.x + obj_2.width)
        && obj_2.x <= (obj_1.x + obj_1.width)
        && obj_1.y <= (obj_2.y + obj_2.height)
        && obj_2.y <= (obj_1.y + obj_1.height + *height_margin*)
    );

    // return position booleans
    return {
        collision: collision,
    };
},

// the movement function takes the change in movement as arguments, and moves the player unless its colliding with something
movement: function movement(x, y, *height_margin*) {
    *// if height_margin is undefined set it to 0.
    height_margin = height_margin || 0;*
    new_pos.x = player.x + x;
    new_pos.y = player.y + y;
    // check collision for all objects in collision array
    var index;
    var collisions = new Array();
    for (index = 0; index < c_objects.length; ++index) {
        var new_collision = engine.collision(new_pos, c_objects[index], *height_margin*);
        collisions[index] = new_collision.collision;
    }
    var it_collides = collisions.indexOf(true) >= 0;
    if (it_collides == false) {
            player.x += x;
            player.y += y;
            // camera follow player
            offsetX -= x;
            offsetY -= y;
    }
    *// return it collides for use in external functions
    return it_collides;*
},

Now in the jump function we call the movement function like this: var on_ground = engine.movement(0, 0, 10);. We then check if the on_ground is true or false, and if its on_ground we set player.jump to false.

For actually adding support for jumping we now need to add a keypress handler which sets player.jump to true if var on_ground = engine.movement(0, 0, 10); is true.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .