Keyboard input lag and delay

Hi.

I would like to constantly rotate a sprite in my project while certain key down. This is the code I am using:

export default class NewClass extends cc.Component {

    delta:number;
    speed:number = 1000;

    // onLoad () {}

    // start () {}

    update (dt) {
        this.delta = dt;
        cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, this.onKeyDown,this);
    }

    onKeyDown (_event) {
        switch(_event.keyCode){
            case cc.macro.KEY.a:
                this.node.angle += this.speed * this.delta;
                break;
            case cc.macro.KEY.d:
                this.node.angle -= this.speed * this.delta;
                break;
        }
    }

}

What is happening is that when I press the button, it is rotate the sprite only once and then stop for a moment and only after a second or two begin rotating constantly when I’m holding the button down.
Also the rotation is pretty slow, in other engines I usually need to apply 100 * delta to get a smooth rotation but here not even 1000 * delta is satisfying, it is not smooth, I can notice a little lag when the object rotate maybe because it is stopping and not constantly rotating? Input lag could explain it.

Is there any other ways I can listen to key down input in Cocos, or is there any problem with my code?
Did anyone else experienced anything like this before?

I would appreciate any help.

Thanks.

Managed to improve rotation using actions instead of changing the angle value directly:

onKeyDown (_event) {
        switch(_event.keyCode){
            case cc.macro.KEY.a:
                this.node.runAction(cc.rotateBy(0.1, -10));
                break;
            case cc.macro.KEY.d:
                this.node.runAction(cc.rotateBy(0.1, 10));
                break;
        }
    }

Here I run the action to rotate the sprite 10 degrees over 0.1 seconds left and right.
The result is a very smooth rotation exactly what I want, however for some reason the delay is still present. When I press the button for the first time, it is rotate it once and then stop for a moment and continue the rotation after a second if the key is down. I would like the rotation to be more snapy, I prefer not to have this delay when the rotation begin. I would appreciate any suggestions.

Thanks.

Remove the systemEvent assign from update, you only need to register it once.

1 Like

Thank you, glad to know it was not necessary to call the systemEvent every frame.
However, it did not fix the problem, even if I moved the systemEvent to the start function, did get the same result for both the lag and delay.

For now I managed to solve the problem by using a boolean to check if the key is down or not like so:

export default class NewClass extends cc.Component {

    speed:number = 100;
    turnLeft:boolean = false;
    turnRight:boolean = false;

    // onLoad () {}

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

    update (dt) {

        if(this.turnLeft)
            this.node.angle += this.speed * dt;

        if(this.turnRight)
            this.node.angle -= this.speed * dt;
    }

    onKeyDown (_event) {
        switch(_event.keyCode){
            case cc.macro.KEY.a:
                this.turnLeft =  true;
                break;
            case cc.macro.KEY.d:
                this.turnRight = true;
                break;
        }
    }

    onKeyUp (_event) {
        switch(_event.keyCode){
            case cc.macro.KEY.a:
                this.turnLeft =  false;
                break;
            case cc.macro.KEY.d:
                this.turnRight =  false;
                break;
        }
    }

}

This way I get instant and smooth rotation even if I update the angle directly by 100 * delta like I usually do.

Thanks again.

That seems like the typematic-rate function of keyboard handling in the OS. To be clear, you have an event on key down that does one rotation. That means when the keyboard is pressed, the rotation is only performed once. Holding down the key has a delay before it repeats the keydown event which is called.

The proper way is to set a bool true on down and clear it on up, like you did. Or some other method of similar redesign where key down begins rotation and key up ends it. Keep in mind that if your app loses focus the key state might change without the app getting notified. So checking key states when you gain focus again is good practice.

1 Like

Thanks a lot for the tip, I haven’t thought of this. Indeed it can be a problem.