[SOLVED] 2D game character sprite can't jump

Hi, I’ve read many forums already and I still can’t understand why my character couldn’t jump. Been trying for three days now. Here is my code:

I have my character on a ground plane with a ground tag (rigid body and collision is on) too. Character has rigid body and collisions too. the ASD keys work, but the W doesn’t. Thank you in advance!

CODE:

var AtticusScript = pc.createScript('atticusScript');
var onGround = false;
var jumpForce = 5;

// initialize code called once per entity
AtticusScript.prototype.initialize = function() {

};

// update code called every frame
AtticusScript.prototype.update = function(dt) {

if (this.app.keyboard.isPressed(pc.KEY_D)) {
        this.entity.sprite.play('atticusRight');
        this.entity.translateLocal(0.05, 0, 0);
    }

      if (this.app.keyboard.isPressed(pc.KEY_S)) {
        this.entity.sprite.play('atticusIdle');
        this.entity.translateLocal(0, 0, 0);
     }
     if (this.app.keyboard.isPressed(pc.KEY_A)) {
        this.entity.sprite.play('atticusLeft');
        this.entity.translate(-0.05, 0, 0);
    }

    else if (this.app.keyboard.isPressed(pc.KEY_W) && onGround === true) {
        this.entity.sprite.play('atticusJump');
        this.entity.rigidbody.applyImpulse(0, jumpForce, 0); // Apply Impulse
        onGround = false; // Set onGround variable to false
    }
    

};

Hi @Jamie_Robyn! I see your onGround boolean is false by default. Do you set it to true somewhere?

1 Like

Ohh, wait, I just changed it to true now which makes more sense since the character starts onground. though at the last line that starts with onground, I set it to false since he’s supposed to be jumping already by then. I tried to play it, but the character still didn’t jump, sadly. May I ask if that is the right way of doing it? Thank you, @Albertos


var AtticusScript = pc.createScript('atticusScript');
var onGround = true;
var jumpForce = 5;

// initialize code called once per entity
AtticusScript.prototype.initialize = function() {
};

// update code called every frame

AtticusScript.prototype.update = function(dt) {
if (this.app.keyboard.isPressed(pc.KEY_D)) {
        this.entity.sprite.play('atticusRight');
        this.entity.translateLocal(0.05, 0, 0);

    }

      if (this.app.keyboard.isPressed(pc.KEY_S)) {
        this.entity.sprite.play('atticusIdle');
        this.entity.translateLocal(0, 0, 0);

     }
     if (this.app.keyboard.isPressed(pc.KEY_A)) {
        this.entity.sprite.play('atticusLeft');
        this.entity.translate(-0.05, 0, 0);

    }

    else if (this.app.keyboard.isPressed(pc.KEY_W) && onGround === true) {
        this.entity.sprite.play('atticusJump');
        this.entity.rigidbody.applyImpulse(0, jumpForce, 0); // Apply Impulse
        onGround = false; // Set onGround variable to false
    }

   

};

Is the jump animation working? Does your entity have a dynamic rigidbody?

1 Like

I see, I was using kinematic then tried changing it to dynamic just now (the jump still did not work and it didn’t collide with the enemies anymore, unfortunately, so I reverted it to kinematic for now).

And hmm…I did use a png sprite sheet and generated frames into 4 columns x 1 row to have the character jump. :open_mouth:

I see you use two different ways of moving your entity. You should use translateLocal if you use a kinematic rigidbody and you should apply a force on the rigidbody if you use a dynamic rigidbody. (I also see you use translate instead of translateLocal somewhere).

https://developer.playcanvas.com/ru/user-manual/packs/components/rigidbody/

2 Likes

The dynamic rigidbody will not move when you use translateLocal. So the entity is moving while the rigidbody stay on the same place. Note that when you use a kinematic rigidbody and move it with translateLocal the entity doesn’t stop if it collide with something.

1 Like

Ohhh, got it, so I now just made it all kinematic. I will look more into rigid bodies in the future. May I ask how this character would be able to jump now as well as land back to a few steps away from its original X position? Apologies for the questions, and thank you @Albertos

var AtticusScript = pc.createScript('atticusScript');
var onGround = true;

// initialize code called once per entity
AtticusScript.prototype.initialize = function() {

};

// update code called every frame
AtticusScript.prototype.update = function(dt) {

if (this.app.keyboard.isPressed(pc.KEY_D)) {
        this.entity.sprite.play('atticusRight');
        this.entity.translateLocal(0.05, 0, 0);
    }

      if (this.app.keyboard.isPressed(pc.KEY_S)) {
        this.entity.sprite.play('atticusIdle');
        this.entity.translateLocal(0, 0, 0);
     }
     if (this.app.keyboard.isPressed(pc.KEY_A)) {
        this.entity.sprite.play('atticusLeft');
        this.entity.translateLocal(-0.05, 0, 0);
    }

    else if (this.app.keyboard.isPressed(pc.KEY_W) && onGround === true) {
        this.entity.sprite.play('atticusJump');
        this.entity.translateLocal(0, 4, 0);
        onGround = false
    }
    

};

Good question. You could use a timer or maybe you can use wasPressed instead of isPressed, but I’m not sure if that gives the right result.

1 Like

Ok, I changed it to wasPressed now and added .5 to the x value. It’s strange why the character still isn’t able to jump until now. :thinking:

var AtticusScript = pc.createScript('atticusScript');
var onGround = true;

// initialize code called once per entity
AtticusScript.prototype.initialize = function() {

};

// update code called every frame
AtticusScript.prototype.update = function(dt) {

if (this.app.keyboard.isPressed(pc.KEY_D)) {
        this.entity.sprite.play('atticusRight');
        this.entity.translateLocal(0.05, 0, 0);
    }

      if (this.app.keyboard.isPressed(pc.KEY_S)) {
        this.entity.sprite.play('atticusIdle');
        this.entity.translateLocal(0, 0, 0);
     }
     if (this.app.keyboard.isPressed(pc.KEY_A)) {
        this.entity.sprite.play('atticusLeft');
        this.entity.translateLocal(-0.05, 0, 0);
    }

    if (this.app.keyboard.wasPressed(pc.KEY_W) && onGround === true) {
        this.entity.sprite.play('atticusJump');
        this.entity.translateLocal(0.5, 4, 0);
        onGround = false
    }

};

If you share a link of your project I can take a look.

1 Like

Sure, here’s the link: PlayCanvas 3D HTML5 Game Engine I’m currently editing Level 1 scene. Thank you, @Albertos :smile:

The jump is applied, but the jump animation you use is not suitable, because it doens’t stay in place and plays a jump animation by itself. It should be a stationary sprite with a jump stance, just like your other sprites. Apart from that you also have to move your character down manually. This is because the kinematic rigidbody. You can add something like below.

    if (onGround === false) {
        this.entity.translateLocal(0, -0.1, 0);
    }
1 Like

I was able to apply those now (changed the sprite and added the code), so I guess last problem with my code, when I press W → screen turns black and character doesn’t go up anymore. Thank you for the help again!

var AtticusScript = pc.createScript('atticusScript');
var onGround = true;

// initialize code called once per entity
AtticusScript.prototype.initialize = function() {

};

// update code called every frame
AtticusScript.prototype.update = function(dt) {

if (this.app.keyboard.isPressed(pc.KEY_D)) {
        this.entity.sprite.play('atticusRight');
        this.entity.translateLocal(0.05, 0, 0);
    }

      if (this.app.keyboard.isPressed(pc.KEY_S)) {
        this.entity.sprite.play('atticusIdle');
        this.entity.translateLocal(0, 0, 0);
     }
     if (this.app.keyboard.isPressed(pc.KEY_A)) {
        this.entity.sprite.play('atticusLeft');
        this.entity.translateLocal(-0.05, 0, 0);
    }

    if (this.app.keyboard.wasPressed(pc.KEY_W) && onGround === true) {
        this.entity.sprite.play('atticusJump');
        this.entity.translateLocal(0.5, 3, 0);
        onGround = false;
    }

    else if (onGround === false) {
        this.entity.translateLocal(0, -3, 0);
    }
};

This is because you moved the entity to fast down and never set onGround to true again.

Below I have created a simple jump logic for you, based on a timer.

image

var AtticusScript = pc.createScript('atticusScript');
var onGround = true;
var timer = 0;

// initialize code called once per entity
AtticusScript.prototype.initialize = function() {

};

// update code called every frame
AtticusScript.prototype.update = function(dt) {

    if (this.app.keyboard.isPressed(pc.KEY_D)) {
        this.entity.sprite.play('atticusRight');
        this.entity.translateLocal(0.05, 0, 0);
    }

    if (this.app.keyboard.isPressed(pc.KEY_S)) {
        this.entity.sprite.play('atticusIdle');
        this.entity.translateLocal(0, 0, 0);
    }
    
    if (this.app.keyboard.isPressed(pc.KEY_A)) {
        this.entity.sprite.play('atticusLeft');
        this.entity.translateLocal(-0.05, 0, 0);
    }

    if (this.app.keyboard.wasPressed(pc.KEY_W) && onGround === true) {
        this.entity.sprite.play('atticusJump');
        onGround = false;
    }

    if (onGround === false) {
        timer += dt;

        if (timer < 0.3) {
            this.entity.translateLocal(0, 0.15, 0);
        }
        else if (timer < 0.6) {
            this.entity.translateLocal(0, -0.15, 0);
        }
        else {
            onGround = true;
            timer = 0;
        }
    }
};
1 Like

Thank you so much for your help, @Albertos it works well now. I’ll really study these more once I’ve the free time. Thanks again :smiley:

1 Like