2016-11-24 23 views
0

我正在制作一个简单的记忆游戏,并且在将两张牌面朝上并在他们检查比赛之前,我已经放了一个短暂的延迟。如果他们无法匹敌,他们会将脸朝下翻转。我遇到的问题是延迟发生在第二张牌面朝上之前,即使它后来在代码中出现,导致第二张牌不能正面显示。我使用带有预加载图像的drawImage函数,因此调用不需要等待图像加载。我已经在下面添加了我的代码,并在绘制平面和延迟函数之后发表评论。如何在HTML5 canvas游戏中的drawImage函数后正确引入延迟?

的在线版本:http://dtc-wsuv.org/mscoggins/hiragana/seindex.html

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 >= this.x && x <= this.x + this.w && y >= this.y && y <= 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 < 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 < 2 && !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 < cards.length;i++) { 
      foundAllMatches = foundAllMatches && 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 < 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 < 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 >= imgsToLoad.length) { 
       callback(); 
      } 
     }; 
    } 
    for(var i = 0;i < COLS;i++) { 
     for(var j = 0;j < ROWS;j++) { 
      cards[index].x = i * 80 + i * 10 + 20; 
      cards[index].y = j * 100 + j * 10 + 20; 
      index++; 
     } 
    } 
    for(var i = 0;i < cards.length;i++) { 
     cards[i].drawFaceDown(); 
    } 
}; 

imgLoader(gameImages, doneLoading); 

var checkMatches = function() { 
    for(var i = 0;i < 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 > ms) { 
      timer = true; 
     } 
    } 

}; 
+1

屏幕不会被刷新,直到你的函数退出。 通常的处理方法是使用[setTimeout](https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout)。 将延迟后要运行的代码放入单独的函数中,并在所需的延迟后使用setTimeout调用该函数。请注意,setTimeout将立即返回;回调将在稍后执行。 – Jon

+0

@Jon你可以在此扩展吗?我尝试将checkMatches函数移动到'window.setTimeout(checkMatches,600)'中,并且延迟消失,但卡片没有翻转过来 – mscoggins

回答

0

屏幕不会被刷新,直到你的函数退出。通常的处理方法是使用setTimeout。将延迟后要运行的代码放入单独的函数中,并使用setTimeout在所需的延迟后调用该函数。请注意,setTimeout将立即返回;回调将在稍后执行。

我在下面实现了这个,刚刚替换为以下点击事件监听器代码:

canvas.addEventListener("click", function(e) { 
     for(var i = 0;i < 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 < 2 && !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(); 
         window.setTimeout(checkMatchesAndCompletion, 600); 
        } 
       } 
      } 
     } 

     function checkMatchesAndCompletion() { 
      checkMatches(); 

      var foundAllMatches = true; 
      for(var i = 0;i < cards.length;i++) { 
       foundAllMatches = foundAllMatches && 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); 
+0

这个答案解决了这个问题。当我尝试使用setTimeout时,我将它设置为稍微不同,所以我可能会搞砸了一些东西。无论如何,感谢您的帮助和快速回复。非常感激。 – mscoggins