如何在html5画布游戏中的drawImage函数之后正确引入延迟?

时间:2016-11-24 01:07:17

标签: javascript canvas delay drawimage

我正在制作一个简单的记忆游戏,并且在将两张牌面朝上翻转并且在检查匹配之前我已经进行了短暂的延迟。如果它们无与伦比,那么它们将面朝下翻转。我遇到的问题是延迟是在第二张卡面朝上翻转之前,即使它后来出现在代码中,导致第二张卡面朝上显示。我正在使用带有预加载图像的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 个答案:

答案 0 :(得分: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);