记录--Canvas实现打飞字游戏
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助
打开游戏界面,看到一个画面简洁、却又富有挑战性的游戏。屏幕上,有一个白色的矩形框,里面不断下落着各种单词,而我需要迅速地输入这些单词。如果我输入的单词与屏幕上的单词匹配,那么我就可以获得得分;如果我输入的单词错误或者时间过长,那么我就会输掉游戏。游戏的节奏非常快,每当我输入一个单词,屏幕上就会有新的单词出现,让我不能有丝毫的懈怠。
在游戏中,我不断地挑战自己,不断地提高自己的打字速度和准确性。经过一段时间的练习,我发现我的打字速度和准确性都有了显著的提高,这让我非常开心。
一、游戏介绍
打字游戏使用Canvas和JavaScript实现。游戏的核心玩法是,玩家需要在字母下落到底部之前输入相应的单词。如果玩家输入正确,就会得到相应的分数。游戏中包含了许多有趣的功能,如随机生成单词、单词下落、单词匹配、得分计算等等。此外,游戏设计还考虑到了玩家的游戏体验,如游戏难度的调整、游戏音效的设置等等。如果你喜欢挑战和打字游戏,那么这款游戏一定不容错过!
二、效果预览
三、实现思路
在实现游戏时,主要包括以下几个部分:
- 随机生成单词
- 添加新的单词
- 更新画面
- 画出单词
- 处理已输入单词
- 处理未输入单词
- 重置游戏
具体实现可以参考代码中的注释。
1. 搭建页面结构
使用Canvas和JavaScript实现的打字游戏的HTML模板。在这个HTML模板中,我们使用了canvas
元素来显示游戏画面。此外,我们还添加了一个得分标签、一个文本输入框和一个重置游戏按钮。在游戏开始时,用户需要点击文本输入框并输入单词。如果输入的单词与下落的单词匹配,则会得到相应的分数。如果下落的单词没有被输入,则游戏结束。用户可以通过点击重置游戏按钮重新开始游戏。
1 2 3 4 5 6 7 8 9 10 11 12 13 | <! DOCTYPE html> < html > < head > < title >Canvas打字游戏</ title > < meta charset="UTF-8"> </ head > < body > < canvas id="gameCanvas" width="500" height="400"></ canvas > < p >得分: < span id="score">0</ span ></ p > < input type="text" id="userInput" autofocus> < button id="resetButton">重新开始</ button > </ body > </ html > |
2. 美化界面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | canvas { border: 1px solid black; } body { display: flex; flex-direction: column; align-items: center; } #gameCanvas { margin: 20px; } input[type=text] { margin: 20px; font-size: 20px; padding: 10px; border: none; border-bottom: 2px solid gray; } #score { font-size: 20px; margin: 20px; } #resetButton { margin: 20px; font-size: 20px; padding: 10px; border: none; background-color: #4CAF50; color: white; border-radius: 5px; } #resetButton:hover { background-color: #3E8E41; } |
3. 编写JavaScript代码
对于js代码的编写,我用ES6的class语法来进行编写。使用ES6中的class语法来定义一个游戏类,能够利用class语法的面向对象特性来进行游戏逻辑的封装和组织。使用class语法可以更加清晰地表达游戏的结构和关系,将游戏的各个部分封装在一个类中,可以更加方便地管理和维护代码。
同时,使用class语法还可以更加方便地进行继承和多态的操作,方便扩展和重用代码。在实现游戏时,可能会有不同的游戏模式,或者需要对游戏进行一些特殊的调整。使用class语法可以更加便捷地扩展和修改游戏的逻辑,提高代码的可维护性和可扩展性。
还可以更加方便地进行代码的组织和管理。游戏逻辑封装在一个类中,可以更加清晰地表达游戏的结构和关系,方便代码的组织和管理。同时还可以更加方便地进行代码的测试和调试,提高代码的质量和可靠性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 | class TypingGame { constructor() { this.canvas = document.getElementById("gameCanvas"); this.context = this.canvas.getContext("2d"); this.gameStatus = 'looping' // 游戏状态,初始值为 'looping' this.blinkInterval = null; this.score = 0 // 得分,初始值为 0 this.wordList = []; this.SPEED = 1; // 字符下落速度 this.ANGLE = Math.PI / 2; this.words = ['apple', 'orange', 'banana', 'pear', 'grape']; this.userInput = document.getElementById("userInput"); this.resetButton = document.getElementById("resetButton"); this.addNewWord = this.addNewWord.bind(this); this.handleKeyPress = this.handleKeyPress.bind(this); this.resetGame = this.resetGame.bind(this); this.update = this.update.bind(this); this.drawWord = this.drawWord.bind(this); this.handleWordMatch = this.handleWordMatch.bind(this); this.handleWordMiss = this.handleWordMiss.bind(this); this.init(); } /** * 初始化游戏 */ init() { // 随机生成一些单词 this.generateRandomWords(); // 绑定键盘输入事件 this.userInput.addEventListener("keypress", this.handleKeyPress); // 绑定重置游戏按钮点击事件 this.resetButton.addEventListener("click", this.resetGame); // 添加第一个单词 this.addNewWord(); // 开始游戏循环 this.update(); } /** * 随机生成一些单词 */ generateRandomWords() { for (let i = 0; i < 100 ; i++) { // 随机生成一个指定长度的单词 const word = this.getRandomString(Math.floor(Math.random() * 7) + 3); this.words.push(word); } } /** * 随机生成一个字母 */ getRandomLetter() { const letters = "abcdefghijklmnopqrstuvwxyz"; const index = Math.floor(Math.random() * letters.length); return letters[index]; } /** * 随机生成一个指定长度的单词 */ getRandomString(length) { let result = ""; for (let i = 0; i < length; i++) { result += this.getRandomLetter(); } return result; } /** * 添加新的单词 */ addNewWord() { // 获取单词的宽度 const wordWidth = this.context.measureText(this.getRandomWord()).width; const word = { word: this.getRandomWord(), x: Math.max(wordWidth, Math.random() * (this.canvas.width - wordWidth)), y: 0, angle: this.ANGLE, }; this.wordList.push(word); } /** * 随机获取一个单词 */ getRandomWord() { const index = Math.floor(Math.random() * this.words.length); return this.words[index]; } /** * 更新画面 */ update() { if (this.gameStatus !== 'looping') return; // 清空画布 this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); this.wordList.forEach((word, i) => { word.y += this.SPEED; word.x += Math.sin(word.angle); word.angle += Math.random() * 0.1 - 0.05; const x = word.x - this.context.measureText(word.word).width / 2; // 画出单词 this.drawWord(word.word, x, word.y); if (word.x < 0 || word.x > this.canvas.width) { word.angle = -word.angle; } if (word.y > this.canvas.height) { // 处理未输入单词 this.handleWordMiss(word); this.wordList.splice(i, 1); // 添加新的单词 this.addNewWord(); } }); // 请求下一帧动画 requestAnimationFrame(this.update); } /** * 画出单词 */ drawWord(word, x, y) { this.context.font = "30px Arial"; this.context.fillText(word, x, y); } /** * 处理已输入单词 */ handleKeyPress(event) { if (event.keyCode === 13) { const userWord = this.userInput.value; this.userInput.value = ""; this.wordList.forEach((word, idx) => { if (word.word === userWord) { // 处理已输入单词 this.handleWordMatch(word, idx); } }); } } /** * 处理已输入单词 */ handleWordMatch(word, idx) { // 增加得分 this.score++; // 更新得分显示 document.getElementById("score").innerText = this.score; const x = word.x - this.context.measureText(word.word).width / 2; const y = word.y; let isWhite = true; let blinkCount = 0; // 单词闪烁 this.blinkInterval = setInterval(() => { if (isWhite) { this.context.fillStyle = "white"; } else { this.context.fillStyle = "black"; } this.context.fillText(word.word, x, y); isWhite = !isWhite; blinkCount++; if (blinkCount >= 10) { this.context.fillStyle = "black"; this.context.fillText(word.word, x, y); this.wordList.splice(idx, 1) // 添加新的单词 this.addNewWord() clearInterval(this.blinkInterval); } }, 100); } /** * 处理未输入单词 */ handleWordMiss(word) { if (word.y > this.canvas.height) { clearInterval(this.blinkInterval); this.gameStatus = 'pause'; this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); this.context.font = "30px Arial"; let text =['你输了,你这个菜鸡,','恭喜你,虽败犹荣,','真棒,我的宝子厉害,'] let textSay=this.score>15?this.score>50?text[2]:text[1]:text[0]; this.context.fillText(`${textSay}分数${this.score}分`, this.canvas.width / 2 - 180, this.canvas.height / 2); } } /** * 重置游戏 */ resetGame() { this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); // 开始游戏循环 requestAnimationFrame(this.update); clearInterval(this.blinkInterval); this.gameStatus='looping'; this.score = 0; // 更新得分显示 document.getElementById("score").innerText = this.score; this.wordList = []; // 添加新的单词 this.addNewWord(); } } const typingGame = new TypingGame(); |
TypingGame
类是整个游戏的核心。在constructor
方法中,首先初始化了一些游戏状态和相关的变量,然后调用了init
方法,对游戏进行初始化。在init
方法中,定义了一些事件处理方法,如键盘输入事件处理方法、重置游戏按钮点击事件处理方法等等。在init
方法中,还调用了addNewWord
方法,添加了第一个单词,并且开始游戏循环。在update
方法中,主要是更新画面的逻辑,如清空画布、画出单词、处理已输入单词、处理未输入单词等等。在resetGame
方法中,主要是重置游戏的状态,如清空画布、得分归零、添加新的单词等等。
整个游戏的实现比较简单,主要是依赖于Canvas和JavaScript。游戏中使用了一些Canvas的API,如context.fillText()
方法、context.clearRect()
方法等等,同时还使用了一些JavaScript的语言特性,如类、箭头函数等等。如果你对游戏的实现过程感兴趣,可以参考代码中的注释,了解游戏中每个方法的具体实现细节。
四、写在最后
Canvas和JavaScript看似平凡无奇,却能够创造出令人惊叹的数字世界。在这个数字化时代,掌握这些工具已经成为了一种竞争优势。本篇文章将带领读者一起探索Canvas和JavaScript的世界,通过实现一个打字游戏,领略这些工具的神奇之处。
游戏的实现并不复杂,但却需要运用许多Canvas的API和JavaScript的语言特性。通过随机生成单词、让单词下落、根据用户输入判断单词是否匹配等等,我们成功实现了一个简单而有趣的游戏。在实现游戏的过程中,我们也学习了一些Canvas的API和JavaScript的语言特性,例如类、箭头函数等等。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了