Why does the Jump not stop when the spacebar stays down?

EDITED: I think the title explains itself, but while I have a really smooth (double jump) that responds to how long the player presses the jump button, there is a problem if the space-bar stays down because the double jump will automatically happen. What I would like to see is that even if the space-bar stays down, the single jump is executed. Only when the player presses the space-bar twice, should the double jump occur.

I think this has to do more with JavaScript’s/TypeScript’s auto-repeat functionality on Events rather than the jump itself, but can anyone tell me why the jump continues when the space-bar stays down?

Here is a link to the project, since it is larger than the forum will for uploading: Dropbox - jumptests.zip - Simplify your life

The code, for reference:

@ccclass('JumpTests')
export class JumpTests extends Component {

    @property({type:Vec2, tooltip: "The up velocity of the jump"})
    public jumpVelocity:Vec2 = new Vec2();

    @property({type:CCFloat, tooltip: "Adds latency to button push to add forgiveness if player presses jump again but has not yet hit the floor"})
    public jumpDelay:number = 0.25;

    @property({type:CCInteger, tooltip: "Maximum number of jumps"})
    public maxJumps:number = 2;

    @property({type:CCFloat, tooltip: "Added to RigidBody2D linear damping when player is stopping or changing directions"})
    public linearDrag:number = 4;

    @property({type:CCFloat, tooltip: "Scales gravity. Used bring the player down faster when falling"})
    public gravity: number = 1;

    @property({type:CCFloat, tooltip: "This is used to adjust the rate that the player falls back to the ground"})
    public fallMultiplier: number = 5;

    @property({type: EventHandler})
    public eventHandler:EventHandler|null = null;


    private _keys:Map<number, boolean> = new Map();
    private _isGrounded:boolean = false;
    private _jumpTimer:number = 0;
    private _numOfJumps:number = 0;


    private _rb:RigidBody2D| null = null;
    private _bodyCollider:Collider2D|null = null;
    private _footCollider:Collider2D|null = null;

    private _initColliders() {
        let colliders = this.getComponents(BoxCollider2D);
        colliders.forEach(collider=> {
          if (collider.tag === 0) {
              this._bodyCollider = collider;
          }

          if (collider.tag === 1) {
              this._footCollider = collider;
          }
      });
    }

    private _registerListeners() {
        systemEvent.on(SystemEvent.EventType.KEY_DOWN, this.onKeyDown, this);
        systemEvent.on(SystemEvent.EventType.KEY_UP, this.onKeyUp, this);
    }

    private _unregisterListeners() {
        systemEvent.off(SystemEvent.EventType.KEY_DOWN, this.onKeyDown, this);
        systemEvent.off(SystemEvent.EventType.KEY_UP, this.onKeyUp, this);
    }

    isKeyPressed(key:number) {
        return this._keys.get(key);
    }

    isGrounded() {
        let result = false;

        if (this._footCollider) {
            const colliderList = PhysicsSystem2D.instance.testAABB(this._footCollider.worldAABB);
            colliderList.forEach(collider => {
                if (collider.group === (2 << 1)) {
                    result = true;
                }
            });
        }
        return result;
    }

    // EVENT FUNCTIONS

    start () {
      this._rb = this.getComponent(RigidBody2D);
      this._keys.set(macro.KEY.space, false);
      this._initColliders();
      this._registerListeners();
    }

    onKeyDown(event:EventKeyboard) {
        this._keys.set(event.keyCode, event.isPressed);
    }

    onKeyUp(event:EventKeyboard) {
        this._keys.set(event.keyCode, event.isPressed);
    }

    update(deltaTime:number) {
        this._isGrounded = this.isGrounded();
        if (this.isKeyPressed(macro.KEY.space)) {
            this._jumpTimer = Date.now() + this.jumpDelay;
        }
    }

    lateUpdate(deltaTime:number) {
        /* What I would like to happen is that even if the space bar is down, the jump is only executed once.
         * Currently, when the spacebar stays down, is the double jump is performed once, then it just bounces up and down.
         * This might currently be because of JavaScript's/TS auto-repeat functionality on Events more than the jump itself.
         * How do i make sure that even if the space bar is stays down, this is only executed once? 
         */

        if ( this.isKeyPressed(macro.KEY.space) && (this._jumpTimer > Date.now()) ) {
                this.doJump(deltaTime);
        }
        this.modifyPhysics();
    }

    doJump(dt:number) {
        if (this._rb) {
            if (this._isGrounded) {
                this._numOfJumps = 0;
            }

            if ( this._isGrounded || this._numOfJumps < this.maxJumps ) {
                this._rb.linearVelocity = new Vec2(this._rb.linearVelocity.x, 0);
                this._rb.applyForceToCenter(this.jumpVelocity, true);
                this._jumpTimer = 0;
                ++this._numOfJumps;
                this._isGrounded = false;
            }
            this._keys.set(macro.KEY.space, false);
        }
    }

    modifyPhysics() {
        if (this._rb) {
            if (this._isGrounded) {
                this._rb.linearDamping = 0
                this._rb.gravityScale = 0;
            } else {
                // Is up in air
                this._rb.gravityScale = this.gravity;
                this._rb.linearDamping = 0;

                if (this._rb.linearVelocity.y < 0) {
                    // if falling
                    this._rb.gravityScale = this.gravity * this.fallMultiplier;
                } 
                else if(this._rb.linearVelocity.y > 0 && !this.isKeyPressed(macro.KEY.space)) {
                    // if moving upwards, but released the jump key, change jump height
                    this._rb.gravityScale = this.gravity * (this.fallMultiplier / 2);
                }
            }
        }
    }
}

hi,what version of Cocos Creator are you using?
is the space bar pressed?
only this code is not very convenient to determine the problem, it is convenient to provide a demo?

1 Like

Hi thank you for your reply. What is the best way to provide a demo?
I am currently using v. 3.0 and the space bar is definitely being pressed.

you can cocos project into a zip package, and then uploaded to the forum.
you can click this button, as shown below:
image

1 Like

Edited the post so you can download a project.

JumpTests.zip (1.9 KB)
Sorry, you can refer to this for modification for the time being. The current design of keydown is implemented like keyevent on the web. Keydown will always be triggered when the key is pressed, and keypress will only be triggered once. Not yet compatible with keypress. So the performance on the game is like this.

1 Like

Yes, that worked perfectly. Thank you.
Although keypress is depreciated according to MDN, are there plans to implement a way to check if a key is down? I’d love to contribute to that if yes.

Thanks again.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.