0

我想知道当用户更新变量的实际值时,是否有一种简单的方法可以在 HTML5 画布上“重写”由 JavaScript 变量显示的值?

例如,我正在使用 HTML5 画布和 JavaScript 编写一个非常简单的游戏来教用户一些基本的威尔士语。

目前,我有两个数组:一个包含数字 1-10 的 10 个 .png 图像,另一个包含数字 1-10 的 10 个威尔士单词字符串。

当用户查看页面时,画布会显示一个“开始游戏”按钮,单击该按钮时,会从 images 数组中随机抽取一个元素,从 words 数组中随机抽取一个元素,以及勾号和十字的图像.

如果图像和单词代表相同的数字,用户应该点击勾号,如果不是,用户应该点击叉号。如果用户做出了正确的选择——我有一个 currentScore 变量,其值增加了 5(从 0 开始),如果他们做出错误的选择,currentScore 的值保持不变。

当我在浏览器中查看页面,玩游戏时,如果我在图片和文字代表数字时点击勾号,我可以看到在控制台中 currentScore 的值增加了 5,但是 currentScore 的值画布上显示的内容保持不变。同样,如果我在它们不匹配时单击十字,则控制台中的分数会增加,但画布上的分数不会增加。

所以代码背后的逻辑是正确的,并且它有效,我只是不确定如何在每次更新其实际值时在画布上更新显示的 currentScore 值。

我用来执行此操作的功能如下:

function drawLevelOneElements(){
            /*First, clear the canvas */ 
            context.clearRect(0, 0, myGameCanvas.width, myGameCanvas.height);
            /*This line clears all of the elements that were previously drawn on the canvas. */
            /*Then redraw the game elements */
            drawGameElements(); 

            /*Create an array of words for numbers 1-10 */
            var wordsArray = new Array();
            wordsArray[0] = "Un";
            wordsArray[1] = "Dau";
            wordsArray[2] = "Tri";
            wordsArray[3] = "Pedwar";
            wordsArray[4] = "Pump";
            wordsArray[5] = "Chwech";
            wordsArray[6] = "Saith";
            wordsArray[7] = "Wyth";
            wordsArray[8] = "Naw";
            wordsArray[9] = "Deg";

            /*Use Math.random() to generate a random number between 1 & 10 to draw the word and image to the canvas */
            var drawnImage = Math.floor(Math.random()*10);
            var drawnWord = Math.floor(Math.random()*10);

            /*Draw an image and a word to the canvas just to test that they're being drawn */
            context.drawImage(imageArray[drawnImage], 100, 30, 30, 30);
            context.strokeText(wordsArray[drawnWord], 500, 60);

            /*Now draw the tick and cross to the canvas */
            context.font = "30pt Calibri"; /*Set text font and size */
            context.drawImage(tick, 250, 200, 50, 50);
            context.drawImage(cross, 350, 200, 50, 50);

            /*Add an event listener to the page to listen for a click on the tick or the cross, if the user clicks
                the right one to indicate whether the image and word relate to the same number or not, increase the
                user's score*/
            myGameCanvas.addEventListener('click', function(e){
                console.log('click: ' + e.pageX + '/' + e.pageY);
                var mouseX = e.pageX - this.offsetLeft;
                var mouseY = e.pageY - this.offsetTop;
                /*If the tick is clicked, check whether or not the image and word represent the same number, if they do,
                    increase the score, if not, leave the score as it is*/
                if((mouseX > 250 && mouseX < 300) && (mouseY > 200 && mouseY < 250) && (drawnImage == drawnWord)){ 
                    currentScore = currentScore + 5;
                    console.log('Current Score = ' + currentScore);
                } else if((mouseX > 250 && mouseX < 300) && (mouseY > 200 && mouseY < 250) && (drawnImage != drawnWord)){
                    currentScore = currentScore; 
                    console.log('Current Score = ' + currentScore);

                /*If the cross is clicked, check whether or not the image and word represent the same number, if they 
                    don't, increase the score, otherwise, leave the score as it is*/
                } else if((mouseX > 350 && mouseX < 400) && (mouseY > 200 && mouseY < 250) && (drawnImage != drawnWord)){
                    currentScore = currentScore + 5;
                    console.log('Current Score = ' + currentScore);
                } else if ((mouseX > 350 && mouseX < 400) && (mouseY > 200 && mouseY < 250) && (drawnImage == drawnWord)){
                    currentScore = currentScore; 
                    console.log('Current Score = '+ currentScore); 
                } else {
                    console.log('The click was not on either the tick or the cross.');
                }
            }, false);

我不会认为这样做需要太多代码,但我就是不知道该怎么做。任何帮助将非常感激。谢谢!

*编辑*

我已按照您的建议添加了代码,但由于某种原因,画布上显示的分数仍未更新...

if((mouseX > 250 && mouseX < 300) && (mouseY > 200 && mouseY < 250) && (drawnImage == drawnWord)){ 
                    currentScore = currentScore + 5;
                    context.clearRect(currentScorePositionX, currentScorePositionY, 20, 20); /*Clear the old score from the canvas */
                    context.strokeText(currentScore, 650, 15); /*Now write the new score to the canvas */
                    console.log('Current Score = ' + currentScore);
                } else if((mouseX > 250 && mouseX < 300) && (mouseY > 200 && mouseY < 250) && (drawnImage != drawnWord)){
                    currentScore = currentScore; 
                    console.log('Current Score = ' + currentScore);

有什么建议么?

4

4 回答 4

1

您可能没有想到的是,画布元素可以是透明的,并且可以相互堆叠。这样,您可以拥有一个仅 GUI 的画布和一个动作画布,并将它们分开。如果您对 css 没有信心,并且想要一个示例,那么绝对定位将使这项工作发挥作用。

于 2012-05-10T23:13:38.490 回答
0

我对我的函数进行了一些更改,现在有以下代码:

/*Add an event listener to the page to listen for a click on the tick or the cross, if the user clicks
                the right one to indicate whether the image and word relate to the same number or not, increase the
                user's score*/
            myGameCanvas.addEventListener('click', function(e){
                console.log('click: ' + e.pageX + '/' + e.pageY);
                var mouseX = e.pageX - this.offsetLeft;
                var mouseY = e.pageY - this.offsetTop;
                /*If the tick is clicked, check whether or not the image and word represent the same number, if they do,
                    increase the score, if not, leave the score as it is*/
                if((mouseX > 250 && mouseX < 300) && (mouseY > 200 && mouseY < 250) && (drawnImage == drawnWord)){ 
                    currentScore = currentScore + 5;
                    var scorePositionX = currentScorePositionX;
                    var scorePositionY = currentScorePositionY;
                    context.clearRect(scorePositionX, scorePositionY, 30, 30); /*Clear the old score from the canvas */
                    context.strokeText(currentScore, 650, 50); /*Now write the new score to the canvas */
                    console.log('Current Score = ' + currentScore);
                } else if((mouseX > 250 && mouseX < 300) && (mouseY > 200 && mouseY < 250) && (drawnImage != drawnWord)){
                    currentScore = currentScore; 
                    console.log('Current Score = ' + currentScore);

                /*If the cross is clicked, check whether or not the image and word represent the same number, if they 
                    don't, increase the score, otherwise, leave the score as it is*/
                } else if((mouseX > 350 && mouseX < 400) && (mouseY > 200 && mouseY < 250) && (drawnImage != drawnWord)){
                    currentScore = currentScore + 5;
                    context.clearRect(currentScorePositionX, currentScorePositionY, 20, 20); /*Clear the old score from the canvas */
                    context.strokeText(currentScore, 500, 50); /*Now write the new score to the canvas */
                    console.log('Current Score = ' + currentScore);
                } else if ((mouseX > 350 && mouseX < 400) && (mouseY > 200 && mouseY < 250) && (drawnImage == drawnWord)){
                    currentScore = currentScore; 
                    console.log('Current Score = '+ currentScore); 
                } else {
                    console.log('The click was not on either the tick or the cross.');
                }
            }, false);

现在显示当前分数,并在每次用户正确选择刻度线或叉号时更新它,但是,每次将新分数绘制到画布时,而不是删除先前绘制的分数并写入新分数取而代之的是,它只是将其写在顶部,因此旧乐谱和新乐谱都显示在同一位置——这有点混乱,而且难以阅读。

此外,乐谱的位置、字体和大小也不是我想要的——我原本打算将它显示在我的“乐谱”中,但是,它现在显示在乐谱下方的主“乐谱”上画布的显示部分。字体也不同——数字不显示为通常的字符,即 5、10 等,但字体更大,就像“泡泡书写”,数字中间有空格。字体也大得多——至少是我在“得分栏”中显示的文本大小的两倍。

有人可以向我指出我在这里做错了什么吗?非常感谢!

于 2012-05-10T23:09:53.577 回答
0

您需要清除部分或全部画布并重新绘制它以更新画布显示。您已经在 drawLevelOneElements() 的第一行执行此操作 - 您清除了整个屏幕。要清除一个部分,您可以执行以下操作:

context.clearRect(x, y, scoreDigitWidth, scoreDigitHeight);

x 和 y 是您的分数数字的坐标, scoreDigitWidth 和 scoreDigitHeight 是宽度和高度。然后你可以使用 context.drawImage() 填充这个被清除的区域。您可以使用不断循环更新框架来启动该过程,或者如果它不需要经常更新,只需在行后运行它:

currentScore = currentScore;

即当你知道新的分数时。

您通常最好清除和重绘画布上发生的变化,而不是全部。这是一篇关于性能的好文章。http://www.html5rocks.com/en/tutorials/canvas/performance/

它看起来像一个非常简单的动画,你最好只使用 html 元素(divs、imgs 等)而不是画布,这将允许使用不支持画布元素的浏览器的用户仍然使用它,即 IE8 <.

于 2012-05-10T13:24:53.697 回答
0

基于Ed Kirk所说的,您可以通过每隔一段时间将其与自身进行比较来检测分数变量何时发生变化(例如,对于初学者来说,50 毫秒)。

例子:

var myScore = 0;
var myOldScore = myScore;

setInterval(function() { 
    if(myScore != myOldScore) {
        myOldScore = myScore;
        // the variable has changed, write it to the canvas
    }
}, 50); // will execute every 50 milliseconds
于 2012-05-10T13:28:34.973 回答