《HTML5 Canvas开发详解》——1.9 第二个示例:猜字母

    xiaoxiao2024-07-16  100

    本节书摘来自异步社区《HTML5 Canvas开发详解》一书中的第1章,第1.9节,作者: 【美】Steve Fulton , Jeff Fulton 更多章节内容可以访问云栖社区“异步社区”公众号查看。

    1.9 第二个示例:猜字母

    现在来快速看一下另一个广泛提及的 “Hello World!”类型的应用程序示例——“猜字母”游戏。本章通过这个示例来说明用JavaScript编写Canvas程序比用Canvas API多了哪些工作量。

    如图1-4所示的游戏当中,玩家要做的是猜出计算机从字母表中随即抽取的字母。游戏会记录玩家已经猜了多少次,列出已经猜过的字母,并且告诉玩家是需要往哪个方向猜(往Z方向猜还是往A方向猜)。

    1.9.1 游戏如何工作 这个游戏的基本结构与“Hello World!”的设置相同,canvasApp()是主函数,所有其他函数都定义为局部函数。这里使用drawScreen()函数在画布上显示文本。不过,本示例中也包括了其他一些函数,后面的章节会继续描述。

    1.9.2 “猜字母”游戏的变量这里是游戏中将要用到的所有变量的列表,它们都在canvasApp()中定义并初始化,因此它们的作用域都被限定在本地定义的封装函数内。

    guesses:这个变量保存玩家按键的次数,次数越少说明他玩得越好。message:这个变量用来向玩家提示游戏的玩法。letters:这个数组保存字母表中的每一个字母,一方面用来随机挑选一个游戏的秘密字母,另一方面也用来计算字母在字母表中的相对位置。today:这个变量保存当前日期,仅用于在屏幕上显示,并无其他目的。letterToGuess:这个变量保存当前被猜的游戏秘密字母。higherOrLower:这个变量存储文本 “Higher”或“Lower”,具体取决于最后一次猜的字母与秘密字母的位置关系。如果秘密字母离“a”更近,程序给出“L- ower”提示,如果离“z”更近,则给出“Higher”提示。lettersGuessed:这个数组保存玩家已经猜过的字母集合。程序将把这些字母显示在屏幕上,提示玩家他已经猜过什么字母。gameOver:这个变量在玩家获胜前都设为false,程序能通过它知道何时在屏幕上显示“You Win”信息,玩家赢了之后就不用再猜了。代码如下所示。 var guesses = 0; var message = "Guess The Letter From a (lower)to z (higher)"; var letters = [       "a","b","c","d","e","f","g","h","i","j","k","l","m","n","o",       "p","q","r","s","t","u","v","w","x","y","z"       ]; var today = new Date(); var letterToGuess = ""; var higherOrLower = ""; var lettersGuessed; var gameOver = false;

    1.9.3 initGame()函数initGame()函数为玩家初始化游戏。以下是两段重要的代码。第一段代码从字母数组中找出一个随机字母,然后将其储存在letterToGuess变量中。

    var letterIndex = Math.floor(Math.random()* letters.length); letterToGuess = letters[letterIndex];

    第二段代码为DOM的window对象添加了一个事件监听器,以“监听”键盘的keyup事件。当某个键被按下时,将调用eventKeyPressed事件处理函数检测按下的字母。

    window.addEventListener("keyup",eventKeyPressed,true);

    以下是函数的全部代码。

    function initGame(){   var letterIndex = Math.floor(Math.random()* letters.length);   letterToGuess = letters[letterIndex];   guesses = 0;   lettersGuessed = [];   gameOver = false;   window.addEventListener("keyup",eventKeyPressed,true);   drawScreen(); }

    1.9.4 eventKeyPressed()函数当玩家按下一个键时将调用此函数,这个函数包含了游戏中的大部分操作。JavaScript中的每个事件处理函数都会传递event对象。该对象中包含发生事件的相关信息,这里使用e参数表示该对象。

    首先检测gameOver变量是否为false,如果是false,则继续检测玩家按下的是哪个键。以下代码实现了该功能。第一行代码从事件中获得按键值,并将其转换为一个字母表中的字母,用于与letterToGuess中存储的字母进行比较。

    var letterPressed = String.fromCharCode(e.keyCode);

    下一行代码将这个字母转换为小写字母,如果玩家不小心打开大写锁定键也可以检测大写字母。

    letterPressed = letterPressed.toLowerCase();

    接下来增加guesses变量的计数,用于显示猜测次数。然后使用Array.push()方法将字母添加到lettersGuessed数组。

    guesses++; lettersGuessed.push(letterPressed);

    现在检测游戏的当前状态并给玩家反馈。首先,测试letterPressed与letterToGuess是否相同,如果相同玩家就赢了。

    if (letterPressed == letterToGuess){   gameOver = true;

    如果玩家没赢,程序需要分别获得letterToGuess以及letterPressed在数组letters中的索引。下面将用这些数值计算是应该显示“Higher”还是应该显示“Lower”,或者显示“That is not a letter.”(这不是一个字母)。为此,这里使用数组的indexOf()方法获得每个字母的对应索引。由于数组是按字母顺序排列的,所以判断显示哪条信息就非常容易。

    } else {   letterIndex = letters.indexOf(letterToGuess);   guessIndex = letters.indexOf(letterPressed);

    现在来进行检测。首先,如果guessIndex小于0,意味着indexOf()返回了-1,也就是说按键不是一个字母,那么就显示一条错误信息。

    if (guessIndex < 0){   higherOrLower = "That is not a letter";

    剩下的测试就简单了。如果guessIndex大于letterIndex就把higherOrLower文本设为 “Lower”。反之,若guessIndex小于letterIndex就把higherOrLower文本设为 “Higher”。

    } else if (guessIndex > letterIndex){    higherOrLower = "Lower";   } else {    higherOrLower = "Higher";   } }

    最后,调用drawScreen()在屏幕上进行绘制。

    drawScreen();

    以下是函数的全部代码。

    function eventKeyPressed(e){    if (!gameOver){    var letterPressed = String.fromCharCode(e.keyCode);    letterPressed = letterPressed.toLowerCase();    guesses++;    lettersGuessed.push(letterPressed);    if (letterPressed == letterToGuess){       gameOver = true;     } else {      letterIndex = letters.indexOf(letterToGuess);      guessIndex = letters.indexOf(letterPressed);      Debugger.log(guessIndex);      if (guessIndex < 0){       higherOrLower = "That is not a letter";      } else if (guessIndex > letterIndex){         higherOrLower = "Lower";      } else {       higherOrLower = "Higher";      }    }    drawScreen();    } }

    1.9.5 drawScreen()函数下面开始编写drawScreen()函数。之前已经学习过其中的大部分代码了——代码几乎与“Hello World!”中的代码相同。例如,这里使用Canvas文本API在屏幕上绘制多个变量。仅需要设置一次context.textBaseline = 'top'就可以对所有显示的文本生效,还可以使用context.fillStyle改变颜色,并且可以使用ontext.font改变字体。

    这里最有趣的事就是显示lettersGuessed数组的内容。在画布上,数组将显示为一组用逗号分隔的字符串,例如:

    Letters Guessed: p,h,a,d

    为了输出这个字符串,只需使用lettersGuessed数组的toString()方法,即可以使用逗号间隔的方式打印出玩家猜到的数组。

    context.fillText ("Letters Guessed: " + lettersGuessed.toString(), 10, 260);

    接下来还需检测gameOver变量。如果结果为真,程序在屏幕上使用大字号(40px)显示文本“You Got It!”(你胜利了),这样用户就知道自己获胜了。

    以下是函数的完整代码。

    function drawScreen(){     //背景     context.fillStyle = "#ffffaa";     context.fillRect(0, 0, 500, 300);     //边框     context.strokeStyle = "#000000";     context.strokeRect(5, 5, 490, 290);     context.textBaseline = "top";     //日期     context.fillStyle = "#000000";     context.font = "10px _sans";     context.fillText (today, 150 ,10);    //消息     context.fillStyle = "#FF0000";     context.font = "14px _sans";     context.fillText (message,125,30);     //猜测的次数     context.fillStyle = "#109910";     context.font = "16px _sans";     context.fillText ('Guesses: ' + guesses, 215, 50);     //显示Higher或Lower     context.fillStyle = "#000000";     context.font = "16px _sans";     context.fillText ("Higher Or Lower: " + higherOrLower, 150,125);     //猜过的字母     context.fillStyle = "#FF0000";     context.font = "16px _sans";     context.fillText ("Letters Guessed: " + lettersGuessed.toString(), 10, 260);     if (gameOver){       context.fillStyle = "#FF0000";       context.font = "40px _sans";       context.fillText ("You Got It!", 150, 180);     }   }

    1.9.6 导出Canvas到图像之前,本章简要讨论了Canvas对象的toDataUrL()属性。这里将使用这个属性让用户能够随时创建一个游戏画面的图像。这就像基于Canvas制作的游戏中的屏幕捕捉功能。

    此处需要在HTML页面上创建一个按钮,用户单击就可以获得屏幕捕捉的图像。下面将这个按钮添加到< form > 中,然后赋予其编号createImageData。

    <form> <input type="button" id="createImageData" value="Export Canvas Image"> </form>

    在init()函数中,通过document对象的getElementById()方法获得了这个表单元素的参考。然后使用createImageDataPressed()方法为按钮的“单击”事件设置一个事件处理器。

    var formElement = document.getElementById("createImageData"); formElement.addEventListener('click', createImageDataPressed, false);

    在canvasApp()函数中,定义createImageDataPressed()函数作为事件处理器,这个函数调用window.open(),并将Canvas.toDataUrl()方法的返回数值传送给窗口,由于这个数据表单是一个有效的PNG,图像会在一个新窗口中显示。

    function createImageDataPressed(e){   window.open(theCanvas.toDataURL(),"canvasImage","left=0,top=0,width=" +   theCanvas.width + ",height=" + theCanvas.height +",toolbar=0,resizable=0");   }

    1.9.7 最终的游戏代码例1-4显示了猜字母游戏的完整代码

    例1-4 猜字母游戏 <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>CH1EX4: Guesss The Letter Game</title> <script src="modernizr-1.6.min.js"></script> <script type="text/javascript"> window.addEventListener('load', eventWindowLoaded, false); var Debugger = function (){ }; Debugger.log = function (message){   try {     console.log(message);   } catch (exception){     return;   } } function eventWindowLoaded(){   canvasApp(); } function canvasSupport (){    return Modernizr.canvas; } function eventWindowLoaded(){   canvasApp(); } function canvasApp(){   var guesses = 0;   var message = "Guess The Letter From a (lower)to z (higher)";   var letters = [          "a","b","c","d","e","f","g","h","i","j","k","l","m","n","o",          "p","q","r","s","t","u","v","w","x","y","z"          ];   var today = new Date();   var letterToGuess = "";   var higherOrLower = "";   var lettersGuessed;   var gameOver = false;   if (!canvasSupport()){       return;      }   var theCanvas = document.getElementById("canvasOne");   var context = theCanvas.getContext("2d"); initGame();   function initGame(){    var letterIndex = Math.floor(Math.random()* letters.length);    letterToGuess = letters[letterIndex];    guesses = 0;    lettersGuessed = [];    gameOver = false;    window.addEventListener("keyup",eventKeyPressed,true);    var formElement = document.getElementById("createImageData");    formElement.addEventListener('click', createImageDataPressed, false);    drawScreen();   }   function eventKeyPressed(e){    if (!gameOver){      var letterPressed = String.fromCharCode(e.keyCode);      letterPressed = letterPressed.toLowerCase();      guesses++;      lettersGuessed.push(letterPressed);      if (letterPressed == letterToGuess){       gameOver = true;      } else {       letterIndex = letters.indexOf(letterToGuess);       guessIndex = letters.indexOf(letterPressed);       Debugger.log(guessIndex);       if (guessIndex < 0){         higherOrLower = "That is not a letter";       } else if (guessIndex > letterIndex){         higherOrLower = "Lower";       } else {         higherOrLower = "Higher";       }      }      drawScreen();     }   }   function drawScreen(){    //背景    context.fillStyle = "#ffffaa";    context.fillRect(0, 0, 500, 300);    //边框    context.strokeStyle = "#000000";    context.strokeRect(5, 5, 490, 290);    context.textBaseline = "top";    //日期    context.fillStyle = "#000000";    context.font = "10px _sans";    context.fillText (today, 150 ,10);    //消息    context.fillStyle = "#FF0000";    context.font = "14px _sans";    context.fillText (message, 125, 30);    //猜测的次数    context.fillStyle = "#109910";    context.font = "16px _sans";    context.fillText ('Guesses: ' + guesses, 215, 50);    //显示Higher或Lower    context.fillStyle = "#000000";    context.font = "16px _sans";    context.fillText ("Higher Or Lower: " + higherOrLower, 150,125);    //猜过的字母    context.fillStyle = "#FF0000";    context.font = "16px _sans";    context.fillText ("Letters Guessed: " + lettersGuessed.toString(), 10, 260);    if (gameOver){      context.fillStyle = "#FF0000";      context.font = "40px _sans";      context.fillText ("You Got It!", 150, 180);    }   }   function createImageDataPressed(e){    window.open(theCanvas.toDataURL(),"canvasImage","left=0,top=0,width=" +    theCanvas.width + ",height=" + theCanvas.height +",toolbar=0,resizable=0");   } } </script> </head> <body> <div style="position: absolute; top: 50px; left: 50px;"> <canvas id="canvasOne" width="500" height="300"> Your browser does not support HTML5 Canvas. </canvas> <form> <input type="button" id="createImageData" value="Export Canvas Image"> </form> </div> </body> </html> 相关资源:敏捷开发V1.0.pptx
    最新回复(0)