ScottC
ScottC

Reputation: 462

setTimeout and setInterval not working as expected

I can't seem to get this working, what should happen is when the user presses the spacebar ie. event.which=32 it does move but it moves 20 up and 20 over all at once it doesn't go 1 by 1 every second or 1000 milliseconds

$(function() {

    var canvas = document.getElementById('canvas');
    var ctx = canvas.getContext('2d');
    var x =0;
    var y =100;
    var w =50;
    var h =50;
    var prekey = '';
    ctx.fillStyle = "rgb(200,0,0)";  
    ctx.fillRect (x, y, w, h);
    var i=0; var hi = '';

    $("*").keydown(function(event)  {
        ctx.clearRect (0, 0, 500, 300);

        if (event.which == 37){
            if (x!=0){x=x-1;} prekey=event.which;
        }
        if (event.which == 39){if (x!=450){x=x+1;} prekey=event.which;}
        if (event.which == 32)  {
            if (prekey==39) {
                for(i=0;i<=20;i++) {
                    function jumpBox() {
                        x=x+1;
                        y=y-1;
                        ctx.clearRect (0, 0, 500, 300);
                        ctx.fillRect (x, y, w, h);
                        return 1;
                    }

                    var t = setTimeout(jumpBox, 1000);
                }

            if (prekey==37){}
            }           
        ctx.fillRect (x, y, w, h);
    });

});

Upvotes: 0

Views: 462

Answers (2)

Ruan Mendes
Ruan Mendes

Reputation: 92294

Andrew's answer is the direction you want to go, I just put it in a working js fiddle and tried to make sense of it, since I couldn't figure out what the script was supposed to do exactly.

http://jsfiddle.net/mendesjuan/xYUNn/2

Here's what the new script does.

  • Moves the box when you hit left and right arrows
  • Starts the animation when you hit space
  • Does nothing for other keys

Changes to your script

  • For animation to work, you need to chain your setTimeouts, you can't just call them all in a loop. When you do that, all the steps are going to happen after a second, almost instantly, and you won't see any animation
  • No need to run $('*'), it's wasteful, just uses $(document) since the event bubbles
  • i++ is more readable than than i = i+1 specially if you're not assigning it to a variable
  • ifs in one line are very hard to read
  • Added a way to clear the timeout when you hit another key

You can now change the script for your needs

$(function() {
    var canvas = document.getElementById('canvas');
    var ctx = canvas.getContext('2d');
    var x = 0;
    var y = 100;
    var w = 50;
    var h = 50;
    var prekey = '';
    ctx.fillStyle = "rgb(200,0,0)";
    ctx.fillRect (x, y, w, h);

    var timeout;
    $(document).keydown(function(event)  {
        var counter = 0;
        clearTimeout(timeout);
        function animateCanvasBox() {
            x++;
            y--;
            ctx.clearRect (0, 0, 500, 300);
            ctx.fillRect (x, y, w, h);
            if (counter < 20) {
                timeout = setTimeout(animateCanvasBox, 100);
            }
            counter++;
        }

        if (event.which == 37){ //left arrow
            if (x != 0){
                x--;
            }
            prekey=event.which;
            ctx.clearRect (0, 0, 500, 300);
            ctx.fillRect (x, y, w, h);

        }
        else if (event.which == 39){ // right-arrow
            if (x != 450){
                x++;
            }
            prekey=event.which;
            ctx.clearRect (0, 0, 500, 300);
            ctx.fillRect (x, y, w, h);
        }
        else if (event.which == 32)  { //space
            animateCanvasBox();
        }
    });
});​

Here's a version that supports all arrows http://jsfiddle.net/mendesjuan/xYUNn/5/

Upvotes: 0

Andrew
Andrew

Reputation: 13853

You are setting all your setTimeouts at the same time through the for loop. You need to wait before calling the next one.

if (prekey==39) { 
    var count = 0,
    jumpBox;
    jumpBox = function()  {
        x=x+1;
        y=y-1;
        ctx.clearRect (0, 0, 500, 300);
        ctx.fillRect (x, y, w, h);

        if(++count < 20) {
           setTimeout(jumpBox, 1000);
        }    
    }
    var t = setTimeout(jumpBox, 1000);
}

Upvotes: 2

Related Questions