Question

When i press spacebar, the function shoot executes.

window.onkeydown=function(e){
    var which = e.keyCode;
    if(which == 32){
        shoot();
    }
}

If you hold space down, shoot calls many times in a row. I only want the function to execute once every 500ms.

Was it helpful?

Solution

(function($){

    var lazerCharging = false,
        lazerChargeTime = 500;  // Charge time in ms

    function handleKeyPress(e){
        if(e.keyCode == 32){
            shoot(lazerChargeTime);   
        }
    }

    function shoot(chargeTime){

        if(!lazerCharging){        

            lazerCharging = true;       
            $("body").append("pew<br/>");

            setTimeout(function(){
                lazerCharging = false;
            }, chargeTime)            
        }        
    }

    $(window).on("keydown", handleKeyPress);

})($);

Here's a jsfiddle

OTHER TIPS

You'll want to "debounce"

Using jQuery throttle / debounce, you can pass a delay and function to $.debounce to get a new function, that when called repetitively, executes the original function just once per "bunch" of calls.

This can be especially useful for rate limiting execution of handlers on events that will trigger AJAX requests. Just take a look at this example to see for yourself!

Ben Alman did the hard work for you here: http://benalman.com/code/projects/jquery-throttle-debounce/examples/debounce/

Essentially a debounce as MattC suggested. Store the time the function was called last and make sure 500 ms has passed. Also you probably should be using .addEventListener instead of window.onkeydown

(function() {
    var lastCallTime = 0;
    window.onkeydown = function(e){
        var now = Date.now();
        if(e.keyCode == 32 && now - lastCallTime > 500) {
            shoot();
            lastCallTime = now;
        }
    }
});

I doubt it's guaranteed that keydown/keypress events are always fired continuously. It may depend on the browser, operating system settings, etc. Even if they are, "fire rate" may fluctate. You probably don't want this.

I think a better idea would be to create a timer that's started when the first keydown event is fired, and stopped on keyup event.

http://jsfiddle.net/kPbLH/

var fireTimer = null;

function fire() {
    // do whatever you need
}

document.addEventListener("keydown", function(e) {
    if (e.keyCode == 32 && fireTimer === null) {
         fire(); // fire immediately...
         fireTimer = setInterval(fire, 500);  // ...and 500ms, 1000ms and so on after
    }
});

document.addEventListener("keyup", function(e) {
    if (e.keyCode == 32 && fireTimer !== null) {
        clearInterval(fireTimer);
        fireTimer = null;
    }
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top