0

I've been trying to figure out how to run an infinite loop while pausing for user click, then allow for a break out.

When the loop starts, the user is presented with an image, and must choose the identical image from one of 4 displayed. If they successfully click the match within 5 seconds, they are presented another image, and the game goes on. If they either choose an incorrect image, or 5 seconds elapses, the game ends.

I've got all of the functionality worked out, except this pause while waiting for a click or the time to expire.

Ideally, I'd also like the time to be adjustable on each iteration. Say start at 5 seconds, then shorten the time slightly (10ms) on each loop.

I believe it must be solvable using setTimeout() or setInterval(), but just can't wrap my head around it.

Here is a minimal concept of what I'm trying to accomplish.

$('#playnow').on('click',function(){
    var speed = 5000;
    var speed_reduce = 10;
    var game_running = true;

    /* create array of images */
    var imgs = ['puppy.png','kitten.png','bunny.png','goldfish.png'];

    var runnow = setInterval(
        function(){

            //get random image from loaded theme
            rand_img = imgs[Math.floor(Math.random() * imgs.length) ];

            //display chosen image
            $('#goal_image').html('<img src="'+theme_dir+rand_img+'" />');

            // wait up to 5 seconds for user to click or time to expire
            if(*clicked and matched*){
                //get new random image and reset timer (less 10ms)
            }
            if(*time expired*){
                //bail out and game ends
            }   

            /* reduce time */
            speed -= speed_reduce;
        },
    speed);

});
bluedenham
  • 29
  • 1
  • 7

4 Answers4

0

Well, firstly, you need to clearInterval() when they either click or fail in order to stop the current interval. Then, you can restart an interval with the new speed. The interval seems to be working for.

Every 5 seconds a new picture is displayed. So, you want an onclick event for the picture that clears the interval and starts a new one. So, you may want to use setTimeout instead of setInterval since it is only a single iteration at a time.

You could use setInterval, I suppose, but there's no real benefit to it. This way also makes it relatively easy to reduce the speed each time.

Remi Guan
  • 21,506
  • 17
  • 64
  • 87
Araymer
  • 1,315
  • 1
  • 10
  • 16
0

You'll want something like this I think:

var speed = 5000, // the initial time
    currentimage,
    timer,
    gamerunning;
function newimage(){
    var imgs = ['puppy.png','kitten.png','bunny.png','goldfish.png'];
    currentimage=Math.floor(Math.random() * imgs.length);
    $('#goal_image').html('<img src="'+theme_dir+imgs[currentimage]+'" />');
    timer = setTimeout(speed, lost)
}
function answer(id){
    if(!gamerunning){return}
    clearTimeout(timer)
    if(id==currentimage){
        speed -= 10; // time decrease every time.
        newimage();
    }else{
        lost()
    }
}
function lost(){
    gamerunning=0;
    speed=5000;
    // what to do when lost.
}
$("#puppy").on("click",function(){answer(0)}); // here #puppy is the id of the answer image, and 0 the index in the imgs array.
$("#kitten").on("click",function(){answer(1)});
$("#bunny").on("click",function(){answer(2)});
$("#fish").on("click",function(){answer(3)});
$("#gamestartbutton").on("click",function(){gamerunning=1})
Ewoud
  • 741
  • 4
  • 6
  • Thanks to everybody who put in their two cents. I was able to accomplish my goal using a combination of all answers, but as I can only award an official 'thanks' to one, I chose Ewoud as their answer was the most helpful, and eventually got my own mental juices flowing the most. @Ewoud: created `nweimage` and `lost` functions @Michael Saunders: created `runNow` @fken: created `gameover` @Araymer: made me see the need for `clearInterval` (ended up using set/clearTimeout) – bluedenham Jan 09 '16 at 16:46
0

One way to solve this problem is to use setTimeout() and clearTimeout() rather than setInterval. Also, you need some event for the successful button click (I've pretended you have a special "#successfulmatch" button):

var speed = 5000;
var speed_reduce = 10;
var game_running = true;
var imgs = ['puppy.png','kitten.png','bunny.png','goldfish.png'];
var myTimeout;

function runNow(speed){
  rand_img = imgs[Math.floor(Math.random() * imgs.length) ];
  $('#goal_image').html('<img src="'+theme_dir+rand_img+'" />');
  
  // Keep track of the timeout so we can cancel it later if the user clicks fast enough.
  myTimeout = window.setTimeout(function(){
    game_running = false;
    gameEnds();
  },speed);
}

$('#successfulmatch').on('click',function(){
  if(game_running){
    
    // Cancel the timeout because the user was fast enough
    window.clearTimeout(myTimeout);
  
    // Give the user less time than before
    runNow(speed - speed_reduce);
  }
  else{
    // Throw an error: you forgot to hide the clickable buttons when the game ended.  
  }
}

$('#playnow').on('click',function(){
    runNow(speed);
}
                 
           
Michael Saunders
  • 2,662
  • 1
  • 12
  • 21
0

Looks like you are mixing the logic for checking "has the user clicked the image? was it correct?" with the one for checking "has time expired?"

You can listen for onclick events on the images and set a timeout event for the game over so the user has to cancel that timer, to cancel imminent game over, by clicking on the images if the right image is clicked the timer is reset if not, it's game over you can cancel a timeout event before it runs with cancelTimeout() see W3C here for a reference.

here is a quick prototype:

$('#playnow').on('click', function() {
  var speed = 5000;
  var speed_reduce = 10;
  var game_running = true;

  /* create array of images */
  var imgs = ['puppy.png', 'kitten.png', 'bunny.png', 'goldfish.png'];

  // function that ends the game if it's called
  function gameover() {
    alert("GAME OVER");
    game_running = false;
  }

  // in order to use clearTimeout() you must store the timer in a global variable
  // setting a timeout that will end the game if it's not cleared before
  window.timer = setTimeout(gameover, speed);

  // function that is called whenever the user clicks on a image
  function onclickimage(event) {

    if (!game_running) return;

    if ( /*clicked right img*/ ) {

      // get random image from loaded theme
      var rand_img = imgs[Math.floor(Math.random() * imgs.length)];

      // display chosen image
      $('#goal_image').html('<img src="' + theme_dir + rand_img + '" />');

      // delete timer, user now has one more opportunity
      clearTimeout(timer);

      // speed is less 10ms
      speed -= speed_reduce;

      // launch timer again
      window.gametimer = setTimeout(loop, speed);
    } else { // if click did not match correct image
      gameover();
    }
  }

});
fken
  • 11
  • 3