title: How do I properly introduce a delay after a drawImage function in an html5 canvas game?
body: <p>I'm making a simple memory game and I have put a short delay after 2 cards have been flipped face up and before they are checked for a match. If they are unmatched they will then flip back face down. The problem I'm having is that the delay comes before the second card is flipped face up even though it comes afterwards in the code, resulting in the second card not showing face up. I'm using the drawImage function with pre-loaded images so the call shouldn't have to wait for an image to load. I've added my code below and commented after the draw face up and delay functions.</p>
  
  <p>An online version: <a href="http://dtc-wsuv.org/mscoggins/hiragana/seindex.html" rel="nofollow noreferrer">http://dtc-wsuv.org/mscoggins/hiragana/seindex.html</a></p>
  
  <pre><code>var ROWS = 2;
  var COLS = 3;
  var canvas = document.getElementById('myCanvas');
  var ctx = canvas.getContext('2d');
  canvas.width = COLS * 80 + (COLS - 1) * 10 + 40;
  canvas.height = ROWS * 100 + (ROWS - 1) * 10 + 40;
  
  var Card = function(x, y, img) {
      this.x = x;
      this.y = y;
      this.w = 80;
      this.h = 100;
      this.r = 10;
      this.img = img;
      this.match = false;
  };
  
  Card.prototype.drawFaceDown = function() {
      this.drawCardBG();
  
      ctx.beginPath();
      ctx.fillStyle = "red";
      ctx.arc(this.w / 2 + this.x, this.h / 2 + this.y, 15, 0, 2 * Math.PI);
      ctx.fill();
      ctx.closePath();
  
      this.isFaceUp = false;
  };
  
  Card.prototype.drawFaceUp = function() {
      this.drawCardBG();
  
      var imgW = 57;
      var imgH = 70;
      var imgX = this.x + (this.w - imgW) / 2;
      var imgY = this.y + (this.h - imgH) / 2;
      ctx.drawImage(this.img, imgX, imgY, imgW, imgH);
      this.isFaceUp = true;
  };
  
  Card.prototype.drawCardBG = function() {
      ctx.beginPath();
      ctx.fillStyle = "white";
      ctx.fillRect(this.x, this.y, this.w, this.h);
      ctx.closePath();
  
      ctx.beginPath();
      ctx.strokeStyle = "black";
      ctx.lineWidth = 1;
      ctx.moveTo(this.x + this.r, this.y);
      ctx.lineTo(this.w + this.x - this.r * 2, this.y);
      ctx.arcTo(this.w + this.x, this.y, this.w + this.x, this.y + this.r, this.r);
      ctx.lineTo(this.w + this.x, this.h + this.y - this.r * 2);
      ctx.arcTo(this.w + this.x, this.h + this.y, this.w + this.x - this.r, this.h + this.y, this.r);
      ctx.lineTo(this.x + this.r, this.h + this.y);
      ctx.arcTo(this.x, this.h + this.y, this.x, this.h + this.y - this.r, this.r);
      ctx.lineTo(this.x, this.y + this.r);
      ctx.arcTo(this.x, this.y, this.x + this.r, this.y, this.r);
      ctx.stroke();
      ctx.closePath();
  };
  
  Card.prototype.mouseOverCard = function(x, y) {
      return x &gt;= this.x &amp;&amp; x &lt;= this.x + this.w &amp;&amp; y &gt;= this.y &amp;&amp; y &lt;= this.y + this.h;
  };
  
  var imgLib = [
      'img/a.png', 'img/ka.png', 'img/sa.png', 'img/ta.png', 'img/na.png', 'img/ha.png',
      'img/ma.png', 'img/ya.png', 'img/ra.png', 'img/wa.png', 'img/i.png', 'img/ki.png',
      'img/shi.png', 'img/chi.png', 'img/ni.png', 'img/hi.png', 'img/mi.png', 'img/ri.png',
      'img/u.png', 'img/ku.png', 'img/su.png', 'img/tsu.png', 'img/nu.png', 'img/hu.png',
      'img/mu.png', 'img/yu.png', 'img/ru.png', 'img/n.png', 'img/e.png', 'img/ke.png',
      'img/se.png', 'img/te.png', 'img/ne.png', 'img/he.png', 'img/me.png', 'img/re.png',
      'img/o.png', 'img/ko.png', 'img/so.png', 'img/to.png', 'img/no.png', 'img/ho.png',
      'img/mo.png', 'img/yo.png', 'img/ro.png', 'img/wo.png'
  ];
  
  var imgArray = [];
  imgArray = imgLib.slice();
  
  var flippedCards = [];
  var numTries = 0;
  
  var doneLoading = function() {};
      canvas.addEventListener("click", function(e) {
          for(var i = 0;i &lt; cards.length;i++) {
              var mouseX = e.clientX - e.currentTarget.offsetLeft;
              var mouseY = e.clientY - e.currentTarget.offsetTop;
              if(cards[i].mouseOverCard(mouseX, mouseY)) {
                  if(flippedCards.length &lt; 2 &amp;&amp; !this.isFaceUp) {
                      cards[i].drawFaceUp(); //draw card face up
                      flippedCards.push(cards[i]);
                      if(flippedCards.length === 2) {
                          numTries++;
                          if(flippedCards[0].img.src === flippedCards[1].img.src) {
                              flippedCards[0].match = true;
                              flippedCards[1].match = true;
                          }
                          delay(600); //delay after image has been drawn
                          checkMatches();
                      }
                  }
              }
          }
          var foundAllMatches = true;
          for(var i = 0;i &lt; cards.length;i++) {
              foundAllMatches = foundAllMatches &amp;&amp; cards[i].match;
          }
      if(foundAllMatches) {
          var winText = "You Win!";
          var textWidth = ctx.measureText(winText).width;
          ctx.fillStyle = "rgba(255, 255, 255, 0.5)";
          ctx.fillRect(0, 0, canvas.width, canvas.height);
          ctx.fillStyle = "red";
          ctx.font = "40px Arial";
          ctx.fillText(winText, canvas.width / 2 - textWidth, canvas.height / 2);
      }
      }, false);
  
  var gameImages = [];
  
  for(var i = 0;i &lt; ROWS * COLS / 2;i++) {
      var imgId = Math.floor(Math.random() * imgArray.length);
      var match = imgArray[imgId];
      gameImages.push(match);
      gameImages.push(match);
      imgArray.splice(imgId, 1);
  }
  
  gameImages.sort(function() {
      return 0.5 - Math.random();
  });
  
  var cards = [];
  var loadedImages = [];
  var index = 0;
  
  var imgLoader = function(imgsToLoad, callback) {
      for(var i = 0;i &lt; imgsToLoad.length;i++) {
          var img = new Image();
          img.src = imgsToLoad[i];
          loadedImages.push(img);
          cards.push(new Card(0, 0, img));
          img.onload = function() {
              if(loadedImages.length &gt;= imgsToLoad.length) {
                  callback();
              }
          };
      }
      for(var i = 0;i &lt; COLS;i++) {
          for(var j = 0;j &lt; ROWS;j++) {
              cards[index].x = i * 80 + i * 10 + 20;
              cards[index].y = j * 100 + j * 10 + 20;
              index++;
          }
      }
      for(var i = 0;i &lt; cards.length;i++) {
          cards[i].drawFaceDown();
      }
  };
  
  imgLoader(gameImages, doneLoading);
  
  var checkMatches = function() {
      for(var i = 0;i &lt; cards.length;i++) {
          if(!cards[i].match) {
              cards[i].drawFaceDown();
          }
      }
      flippedCards = [];
  };
  
  var delay = function(ms) {
      var start = new Date().getTime();
      var timer = false;
      while(!timer) {
          var now = new Date().getTime();
          if(now - start &gt; ms) {
              timer = true;
          }
      }
  
  };
  </code></pre>