繁体   English   中英

如何在html5 canvas游戏中的drawImage函数之后适当引入延迟?

[英]How do I properly introduce a delay after a drawImage function in an html5 canvas game?

我正在制作一个简单的记忆游戏,在将两张牌面朝上翻转之后以及检查配对之前,我稍加延迟。 如果它们不匹配,它们将面朝下翻转。 我遇到的问题是,即使代码中之后出现第二张卡片,也要延迟第二张卡片的正面朝上,导致第二张卡片的正面朝上显示。 我正在将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;
        }
    }

};

在功能退出之前,屏幕不会刷新。 解决此问题的通常方法是使用setTimeout 将要在延迟后运行的代码放在单独的函数中,并使用setTimeout在所需的延迟后调用该函数。 请注意,setTimeout将立即返回; 回调将在以后执行。

我已经在下面实现了这一点,只需将您的click事件监听器代码替换为以下代码:

    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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM