How to make user wait 100ms before pressing button again?

Hi, I’m struggling slightly on this. Here is my current code:

Button.prototype.press = function (x, y) {
    if (this.checkForClick(x, y)) {
        this.pressed = true;
        this.entity.translate(0, -this.diplacement, 0);
    }
};


Button.prototype.release = function () {
    var app = this.app;

    if (this.pressed) {
        this.pressed = false;

        this.entity.translate(0, this.diplacement, 0);
        app.fire(this.event);
        app.fire('game:audio', 'Swoosh');
    }
    
};

When using this however, in my project, if you spam fast enough, the button will move downwards, and go out of place.

Is there any way to make it so the user has to wait 100ms before you can press again? Thanks :slight_smile:

Well, definitely you can add timers using the default Javascript setTimeout function.

But before doing that, from your code I see that on the press method you send the entity move in the negative Y. That means that if I click and hold the button pressed for a long time that entity will travel out of place as you say.

Normally you will execute code that runs only once in your release method.

Also, maybe you don’t want to translate the position, but instead might want to set the position. In this case, you might have an event that moves the button down on “press” and then restores it on “release” using “setPosition()”. So you’d have two events, this.pressed and this.release. The user would be unable to press again until he releases and that wouldn’t matter anyway because multiple setPosition()s would just put the object in the same position over and over again.

https://developer.playcanvas.com/en/api/pc.Entity.html

You might also want to have a third event, this.hover to change the cursor when it is over the button but not clicked.

1 Like

Hi @wturber
I have tried this, using “setPosition()”

Button.prototype.press = function (x, y) {
    if (this.checkForClick(x, y)) {
        this.pressed = true;

        var position = this.entity.getPosition();
        this.entity.setPosition(position.x, position.y - this.diplacement, position.z);

    }
};


Button.prototype.release = function () {
    var app = this.app;

    if (this.pressed) {
        this.pressed = false;

 var position = this.entity.getPosition();
        this.entity.setPosition(position.x, position.y + this.diplacement, position.z);
        app.fire(this.event);
        app.fire('game:audio', 'Swoosh');
    }
};

This also does the same thing, spamming makes it go down and out of place.

So, the way I see it, you have two alternatives:

  1. Instruct users to stop spamming the button :slight_smile:
  2. Refrain from using the press function, because that event will fire per frame if someone is click and holding the button.

Do everything in your release method, that guarantees that it will happen only once per click.

@Leonidas
I have tried this now (putting it into all one method, as you suggested)

Button.prototype.press = function (x, y) {
                var app = this.app;
    if (this.checkForClick(x, y)) {
        this.pressed = true;

        var position = this.entity.getPosition();

        this.entity.setPosition(position.x, position.y - this.diplacement, position.z);
    
            setTimeout(function () {
        this.entity.setPosition(position.x, position.y + this.diplacement, position.z);
        app.fire(this.event);
        app.fire('game:audio', 'Swoosh');

            }.bind(this), 25);
    }
};

However, now it just goes upwards, instead of down first. Why is this happening?

So, what I’ve said is avoid using the press function, instead use the release event callback. Because that is executed only once.

Now, after you do that, your code to be debugged requires some context on where it is running (what is the entity, how much is the displacement). Try creating a simple sample project that runs that code so we can debug it there.

@leonidas
I have fixed it now :slight_smile:

Button.prototype.press = function (x, y) {
                var app = this.app;
    if (this.checkForClick(x, y)) {
        this.pressed = true;

        var position = this.entity.getPosition();

        this.entity.setPosition(position.x, position.y - this.diplacement, position.z);
    
        setTimeout(function () {
        var position2 = this.entity.getPosition();
        this.entity.setPosition(position2.x, position2.y + this.diplacement, position.z);
        }.bind(this), 100);
        app.fire(this.event);
        app.fire('game:audio', 'Swoosh');


    }
};

For some reason, setting another variable “position2” and using that worked. :slight_smile:
Thank you for your help that you gave to help me get the answer :slight_smile:

2 Likes

Great! Keep up learning :wink:

1 Like

Well yes, since your are setting your position using a formula that changes position.y by this.diplacement every time the function is called. So, if you have a continual stream of that function call happening (user spamming the button) where you subtract a value with each call, then, yes, the button will push away.

What I had in mind was that you would set a fixed value or a value that was pre-calculated outside your .press function. If I wanted to use this.diplacement as a universal offset that is used for a large number of buttons, then I’d probably parent the buttons to an empty entity (nullobject in animator speak) with no scaling or offset. I would use this empty entity for overall positioning of the button and then directly change the button position like this:

this.entity.setPosition(0, this.diplacement, 0);

You would reset it back to its normal position on release like this:

this.entity.setPosition(0, 0, 0);

To be clear, I’m not saying that this is the right, good, elegant or better way to do it. It is just “a” way to do it. It’s probably more animator brain at work than coder brain.

Leonidas’ suggestion to use the release method seems simpler. But then you have to add some other code to restore the button height.