Html5寫(xiě)一個(gè)簡(jiǎn)單的俄羅斯方塊小游戲

導(dǎo)言
在一個(gè)風(fēng)和日麗的一天,看完了瘋狂HTML 5+CSS 3+JavaScript講義,跟著做了書(shū)里最后一章的俄羅斯方塊小游戲,并做了一些改進(jìn),作為自己前端學(xué)習(xí)的第一站。
游戲效果:
制作思路
因?yàn)闀?shū)里的俄羅斯方塊比較普通,太常規(guī)了,不是很好看,所以我在網(wǎng)上找了上面那張圖片,打算照著它來(lái)做。(請(qǐng)無(wú)視成品和原圖的差距)
然后便是游戲界面和常規(guī)的俄羅斯方塊游戲邏輯。
接著便是游戲結(jié)束界面了。
原本想做個(gè)彈出層,但覺(jué)得找圖片有點(diǎn)麻煩,所以就在網(wǎng)上找了文字特效,套用了一下。
代碼實(shí)現(xiàn):
首先是html文件和css文件,主要涉及了布局方面。作為新手,在上面真的是翻來(lái)覆去的踩坑。o(╥﹏╥)o
index.html
<!DOCTYPE html> <html> <head> <title>俄羅斯方塊</title> <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/> <link rel=stylesheet type="text/css" href="teris.css"> <style type="text/css"> /*導(dǎo)入外部的字體文件*/ @font-face{ font-family:tmb;/*為字體命名為tmb*/ src:url("DS-DIGIB.TTF") format("TrueType");/*format為字體文件格式,TrueType為ttf*/ } div>span{ font-family:tmb; font-size:18pt; color:green; } </style> </head> <body> <div id="container" class="bg"> <!--ui--> <div class="ui_bg"> <div style="float:left;margin-right:4px;"> 速度:<span id="cur_speed">1</span> </div> <div style="float:left;"> 當(dāng)前分?jǐn)?shù):<span id="cur_points">0</span> </div> <div style="float:right;"> 最高分?jǐn)?shù):<span id="max_points">0</span> </div> </div> <canvas id="text" width="500" height="100" style="position:absolute;"></canvas> <canvas id="stage" width="500" height="100" style="position:absolute;"></canvas> </div> <script src='EasePack.min.js'></script> <script src='TweenLite.min.js'></script> <script src='easeljs-0.7.1.min.js'></script> <script src='requestAnimationFrame.js'></script> <script type="text/javascript" src="jquery-3.4.1.min.js"></script> <script type="text/javascript" src="teris.js"></script> </body> </html>
teris.css
*{ margin:0; padding:0; } html, body{ width:100%; height:100%; } .bg{ font-size:13pt; background-color:rgb(239, 239, 227); /*好看的漸變色*/ background-image:radial-gradient(rgb(239, 239, 227), rgb(230, 220, 212)); /*陰影*/ box-shadow:#cdc8c1 -1px -1px 7px 0px; padding-bottom:4px; } .ui_bg{ border-bottom:1px #a69e9ea3 solid; padding-bottom:2px; overflow:hidden;/*沒(méi)有這句的話(huà)因?yàn)樽觗iv都設(shè)置了float,所以是浮在網(wǎng)頁(yè)上的,所以父div就沒(méi)有高度,這句清除了浮動(dòng),讓父div有了子div的高度*/ }
然后是重頭戲,teris.js
游戲變量
//游戲設(shè)定 var TETRIS_ROWS = 20; var TETRIS_COLS = 14; var CELL_SIZE = 24; var NO_BLOCK=0; var HAVE_BLOCK=1; // 定義幾種可能出現(xiàn)的方塊組合 var blockArr = [ // Z [ {x: TETRIS_COLS / 2 - 1 , y:0}, {x: TETRIS_COLS / 2 , y:0}, {x: TETRIS_COLS / 2 , y:1}, {x: TETRIS_COLS / 2 + 1 , y:1} ], // 反Z [ {x: TETRIS_COLS / 2 + 1 , y:0}, {x: TETRIS_COLS / 2 , y:0}, {x: TETRIS_COLS / 2 , y:1}, {x: TETRIS_COLS / 2 - 1 , y:1} ], // 田 [ {x: TETRIS_COLS / 2 - 1 , y:0}, {x: TETRIS_COLS / 2 , y:0}, {x: TETRIS_COLS / 2 - 1 , y:1}, {x: TETRIS_COLS / 2 , y:1} ], // L [ {x: TETRIS_COLS / 2 - 1 , y:0}, {x: TETRIS_COLS / 2 - 1, y:1}, {x: TETRIS_COLS / 2 - 1 , y:2}, {x: TETRIS_COLS / 2 , y:2} ], // J [ {x: TETRIS_COLS / 2 , y:0}, {x: TETRIS_COLS / 2 , y:1}, {x: TETRIS_COLS / 2 , y:2}, {x: TETRIS_COLS / 2 - 1, y:2} ], // □□□□ [ {x: TETRIS_COLS / 2 , y:0}, {x: TETRIS_COLS / 2 , y:1}, {x: TETRIS_COLS / 2 , y:2}, {x: TETRIS_COLS / 2 , y:3} ], // ┴ [ {x: TETRIS_COLS / 2 , y:0}, {x: TETRIS_COLS / 2 - 1 , y:1}, {x: TETRIS_COLS / 2 , y:1}, {x: TETRIS_COLS / 2 + 1, y:1} ] ]; // 記錄當(dāng)前積分 var curScore=0; // 記錄曾經(jīng)的最高積分 var maxScore=1; var curSpeed=1; //ui元素 var curSpeedEle=document.getElementById("cur_speed"); var curScoreEle=document.getElementById("cur_points"); var maxScoreEle=document.getElementById("max_points"); var timer;//方塊下落控制 var myCanvas; var canvasCtx; var tetris_status;//地圖數(shù)據(jù) var currentFall;//當(dāng)前下落的block
游戲界面的完善
//create canvas function createCanvas(){ myCanvas=document.createElement("canvas"); myCanvas.width=TETRIS_COLS*CELL_SIZE; myCanvas.height=TETRIS_ROWS*CELL_SIZE; //繪制背景 canvasCtx=myCanvas.getContext("2d"); canvasCtx.beginPath(); //TETRIS_COS for(let i=1; i<TETRIS_COLS; i++){ canvasCtx.moveTo(i*CELL_SIZE, 0); canvasCtx.lineTo(i*CELL_SIZE, myCanvas.height); } for(let i=1; i<TETRIS_ROWS; i++){ canvasCtx.moveTo(0, i*CELL_SIZE); canvasCtx.lineTo(myCanvas.width, i*CELL_SIZE); } canvasCtx.closePath(); canvasCtx.strokeStyle="#b4a79d"; canvasCtx.lineWidth=0.6; canvasCtx.stroke(); //第一行,最后一行,第一列,最后一列粗一點(diǎn)。 canvasCtx.beginPath(); canvasCtx.moveTo(0, 0); canvasCtx.lineTo(myCanvas.width, 0); canvasCtx.moveTo(0, myCanvas.height); canvasCtx.lineTo(myCanvas.width, myCanvas.height); canvasCtx.moveTo(0, 0); canvasCtx.lineTo(0, myCanvas.height); canvasCtx.moveTo(myCanvas.width, 0); canvasCtx.lineTo(myCanvas.width, myCanvas.height); canvasCtx.closePath(); canvasCtx.strokeStyle="#b4a79d"; canvasCtx.lineWidth=4; canvasCtx.stroke(); //設(shè)置繪制block時(shí)的style canvasCtx.fillStyle="#201a14"; } draw canvas
function changeWidthAndHeight(w, h){ //通過(guò)jquery設(shè)置css h+=$("ui_bg").css("height")+$("ui_bg").css("margin-rop")+$("ui_bg").css("margin-bottom")+$("ui_bg").css("padding-top")+$("ui_bg").css("padding-bottom"); $(".bg").css({ "width":w, "height":h, "top":0, "bottom":0, "right":0, "left":0, "margin":"auto" }); } change width and height
//draw blocks function drawBlocks(){ //清空地圖 for(let i=0; i<TETRIS_ROWS;i++){ for(let j=0;j<TETRIS_COLS;j++) canvasCtx.clearRect(j*CELL_SIZE+1, i*CELL_SIZE+1, CELL_SIZE-2, CELL_SIZE-2); } //繪制地圖 for(let i=0; i<TETRIS_ROWS;i++){ for(let j=0;j<TETRIS_COLS;j++){ if(tetris_status[i][j]!=NO_BLOCK) canvasCtx.fillRect(j*CELL_SIZE+1, i*CELL_SIZE+1, CELL_SIZE-2, CELL_SIZE-2);//中間留點(diǎn)縫隙 } } //繪制currentFall for(let i=0;i<currentFall.length;i++) canvasCtx.fillRect(currentFall[i].x*CELL_SIZE+1, currentFall[i].y*CELL_SIZE+1, CELL_SIZE-2,CELL_SIZE-2); } draw block
游戲邏輯
function rotate(){ // 定義記錄能否旋轉(zhuǎn)的旗標(biāo) var canRotate = true; for (var i = 0 ; i < currentFall.length ; i++) { var preX = currentFall[i].x; var preY = currentFall[i].y; // 始終以第三個(gè)方塊作為旋轉(zhuǎn)的中心, // i == 2時(shí),說(shuō)明是旋轉(zhuǎn)的中心 if(i != 2) { // 計(jì)算方塊旋轉(zhuǎn)后的x、y坐標(biāo) var afterRotateX = currentFall[2].x + preY - currentFall[2].y; var afterRotateY = currentFall[2].y + currentFall[2].x - preX; // 如果旋轉(zhuǎn)后所在位置已有方塊,表明不能旋轉(zhuǎn) if(tetris_status[afterRotateY][afterRotateX + 1] != NO_BLOCK) { canRotate = false; break; } // 如果旋轉(zhuǎn)后的坐標(biāo)已經(jīng)超出了最左邊邊界 if(afterRotateX < 0 || tetris_status[afterRotateY - 1][afterRotateX] != NO_BLOCK) { moveRight(); afterRotateX = currentFall[2].x + preY - currentFall[2].y; afterRotateY = currentFall[2].y + currentFall[2].x - preX; break; } if(afterRotateX < 0 || tetris_status[afterRotateY-1][afterRotateX] != NO_BLOCK) { moveRight(); break; } // 如果旋轉(zhuǎn)后的坐標(biāo)已經(jīng)超出了最右邊邊界 if(afterRotateX >= TETRIS_COLS - 1 || tetris_status[afterRotateY][afterRotateX+1] != NO_BLOCK) { moveLeft(); afterRotateX = currentFall[2].x + preY - currentFall[2].y; afterRotateY = currentFall[2].y + currentFall[2].x - preX; break; } if(afterRotateX >= TETRIS_COLS - 1 || tetris_status[afterRotateY][afterRotateX+1] != NO_BLOCK) { moveLeft(); break; } } } if(canRotate){ for (var i = 0 ; i < currentFall.length ; i++){ var preX = currentFall[i].x; var preY = currentFall[i].y; if(i != 2){ currentFall[i].x = currentFall[2].x + preY - currentFall[2].y; currentFall[i].y = currentFall[2].y + currentFall[2].x - preX; } } localStorage.setItem("currentFall", JSON.stringify(currentFall)); } } 旋轉(zhuǎn)
//按下 下 或 interval到了 function next(){ if(moveDown()){ //記錄block for(let i=0;i<currentFall.length;i++) tetris_status[currentFall[i].y][currentFall[i].x]=HAVE_BLOCK; //判斷有沒(méi)有滿(mǎn)行的 for(let j=0;j<currentFall.length;j++){ for(let i=0;i<TETRIS_COLS; i++){ if(tetris_status[currentFall[j].y][i]==NO_BLOCK) break; //最后一行滿(mǎn)了 if(i==TETRIS_COLS-1){ //消除最后一行 for(let i=currentFall[j].y; i>0;i--){ for(let j=0;j<TETRIS_COLS;j++) tetris_status[i][j]=tetris_status[i-1][j]; } //分?jǐn)?shù)增加 curScore+=5; localStorage.setItem("curScore", curScore); if(curScore>maxScore){ //超越最高分 maxScore=curScore; localStorage.setItem("maxScore", maxScore); } //加速 curSpeed+=0.1; localStorage.setItem("curSpeed", curSpeed); //ui輸出 curScoreEle.innerHTML=""+curScore; maxScoreEle.innerHTML=""+maxScore; curSpeedEle.innerHTML=curSpeed.toFixed(1);//保留兩位小數(shù) clearInterval(timer); timer=setInterval(function(){ next(); }, 500/curSpeed); } } } //判斷是否觸頂 for(let i=0;i<currentFall.length;i++){ if(currentFall[i].y==0){ gameEnd(); return; } } localStorage.setItem("tetris_status", JSON.stringify(tetris_status)); //新的block createBlock(); localStorage.setItem("currentFall", JSON.stringify(currentFall)); } drawBlocks(); } //右移 function moveRight(){ for(let i=0;i<currentFall.length;i++){ if(currentFall[i].x+1>=TETRIS_ROWS || tetris_status[currentFall[i].y][currentFall[i].x+1]!=NO_BLOCK) return; } for(let i=0;i<currentFall.length;i++) currentFall[i].x++; localStorage.setItem("currentFall", JSON.stringify(currentFall)); return; } //左移 function moveLeft(){ for(let i=0;i<currentFall.length;i++){ if(currentFall[i].x-1<0 || tetris_status[currentFall[i].y][currentFall[i].x-1]!=NO_BLOCK) return; } for(let i=0;i<currentFall.length;i++) currentFall[i].x--; localStorage.setItem("currentFall", JSON.stringify(currentFall)); return; } //judge can move down and if arrive at end return 1, if touch other blocks return 2, else, return 0 function moveDown(){ for(let i=0;i<currentFall.length;i++){ if(currentFall[i].y>=TETRIS_ROWS-1 || tetris_status[currentFall[i].y+1][currentFall[i].x]!=NO_BLOCK) return true; } for(let i=0;i<currentFall.length;i++) currentFall[i].y+=1; return false; } 上下左右移動(dòng)
function gameKeyEvent(evt){ switch(evt.keyCode){ //向下 case 40://↓ case 83://S next(); drawBlocks(); break; //向左 case 37://← case 65://A moveLeft(); drawBlocks(); break; //向右 case 39://→ case 68://D moveRight(); drawBlocks(); break; //旋轉(zhuǎn) case 38://↑ case 87://W rotate(); drawBlocks(); break; } } keydown事件監(jiān)聽(tīng)
keydown事件監(jiān)聽(tīng)
其他的詳細(xì)情況可以看源代碼,我就不整理了。
接下來(lái)我們看游戲結(jié)束時(shí)的特效。因?yàn)槲乙膊皇呛芏?,所以在這里整理的會(huì)比較詳細(xì)。當(dāng)做學(xué)習(xí)。
//game end function gameEnd(){ clearInterval(timer); //鍵盤(pán)輸入監(jiān)聽(tīng)結(jié)束 window.onkeydown=function(){ //按任意鍵重新開(kāi)始游戲 window.onkeydown=gameKeyEvent; //初始化游戲數(shù)據(jù) initData(); createBlock(); localStorage.setItem("currentFall", JSON.stringify(currentFall)); localStorage.setItem("tetris_status", JSON.stringify(tetris_status)); localStorage.setItem("curScore", curScore); localStorage.setItem("curSpeed", curSpeed); //繪制 curScoreEle.innerHTML=""+curScore; curSpeedEle.innerHTML=curSpeed.toFixed(1);//保留兩位小數(shù) drawBlocks(); timer=setInterval(function(){ next(); }, 500/curSpeed); //清除特效 this.stage.removeAllChildren(); this.textStage.removeAllChildren(); }; //特效,游戲結(jié)束 setTimeout(function(){ initAnim(); //擦除黑色方塊 for(let i=0; i<TETRIS_ROWS;i++){ for(let j=0;j<TETRIS_COLS;j++) canvasCtx.clearRect(j*CELL_SIZE+1, i*CELL_SIZE+1, CELL_SIZE-2, CELL_SIZE-2); } }, 200); //推遲顯示Failed setTimeout(function(){ if(textFormed) { explode(); setTimeout(function() { createText("FAILED"); }, 810); } else { createText("FAILED"); } }, 800); }
上面代碼里的localstorage是html5的本地?cái)?shù)據(jù)存儲(chǔ)。因?yàn)椴皇沁\(yùn)用很難,所以具體看代碼。
整個(gè)特效是運(yùn)用了createjs插件。要引入幾個(gè)文件。
easeljs-0.7.1.min.js,EasePacj.min.js,requestAnimationFrame.js和TweenLite.min.js 游戲重新開(kāi)始就要清除特效。我看api里我第一眼望過(guò)去最明顯的就是removeAllChildren(),所以就選了這個(gè)。其他的改進(jìn)日后再說(shuō)。
//清除特效 this.stage.removeAllChildren(); this.textStage.removeAllChildren();
function initAnim() { initStages(); initText(); initCircles(); //在stage下方添加文字——按任意鍵重新開(kāi)始游戲. tmp = new createjs.Text("t", "12px 'Source Sans Pro'", "#54555C"); tmp.textAlign = 'center'; tmp.x = 180; tmp.y=350; tmp.text = "按任意鍵重新開(kāi)始游戲"; stage.addChild(tmp); animate(); } initAnim
上面初始化了一個(gè)stage,用于存放特效,一個(gè)textstage,用于形成“FAILED”的像素圖片。還有一個(gè)按任意鍵重新游戲的提示。同時(shí)開(kāi)始每隔一段時(shí)間就刷新stage。
根據(jù)block的位置來(lái)初始化小圓點(diǎn)。
function initCircles() { circles = []; var p=[]; var count=0; for(let i=0; i<TETRIS_ROWS;i++) for(let j=0;j<TETRIS_COLS;j++) if(tetris_status[i][j]!=NO_BLOCK) p.push({'x':j*CELL_SIZE+2, 'y':i*CELL_SIZE+2, 'w':CELL_SIZE-3, 'h':CELL_SIZE-4}); for(var i=0; i<250; i++) { var circle = new createjs.Shape(); var r = 7; //x和y范圍限定在黑色block內(nèi) var x = p[count]['x']+p[count]['w']*Math.random(); var y = p[count]['y']+p[count]['h']*Math.random(); count++; if(count>=p.length) count=0; var color = colors[Math.floor(i%colors.length)]; var alpha = 0.2 + Math.random()*0.5; circle.alpha = alpha; circle.radius = r; circle.graphics.beginFill(color).drawCircle(0, 0, r); circle.x = x; circle.y = y; circles.push(circle); stage.addChild(circle); circle.movement = 'float'; tweenCircle(circle); } } initCircles
然后再講顯示特效Failed的createText()。先將FAILED的text顯示在textstage里,然后ctx.getImageData.data獲取像素?cái)?shù)據(jù),并以此來(lái)為每個(gè)小圓點(diǎn)定義位置。
function createText(t) { curText=t; var fontSize = 500/(t.length); if (fontSize > 80) fontSize = 80; text.text = t; text.font = "900 "+fontSize+"px 'Source Sans Pro'"; text.textAlign = 'center'; text.x = TETRIS_COLS*CELL_SIZE/2; text.y = 0; textStage.addChild(text); textStage.update(); var ctx = document.getElementById('text').getContext('2d'); var pix = ctx.getImageData(0,0,600,200).data; textPixels = []; for (var i = pix.length; i >= 0; i -= 4) { if (pix[i] != 0) { var x = (i / 4) % 600; var y = Math.floor(Math.floor(i/600)/4); if((x && x%8 == 0) && (y && y%8 == 0)) textPixels.push({x: x, y: y}); } } formText(); textStage.clear();//清楚text的顯示 } CreateText
跟著代碼的節(jié)奏走,我們現(xiàn)在來(lái)到了formtext.
function formText() { for(var i= 0, l=textPixels.length; i<l; i++) { circles[i].originX = offsetX + textPixels[i].x; circles[i].originY = offsetY + textPixels[i].y; tweenCircle(circles[i], 'in'); } textFormed = true; if(textPixels.length < circles.length) { for(var j = textPixels.length; j<circles.length; j++) { circles[j].tween = TweenLite.to(circles[j], 0.4, {alpha: 0.1}); } } } formtext
explode()就是講已組成字的小圓點(diǎn)給重新遣散。
動(dòng)畫(huà)實(shí)現(xiàn)是使用了tweenlite.
function tweenCircle(c, dir) { if(c.tween) c.tween.kill(); if(dir == 'in') { /*TweenLite.to 改變c實(shí)例的x坐標(biāo),y坐標(biāo),使用easeInOut彈性函數(shù),透明度提到1,改變大小,radius,總用時(shí)0.4s*/ c.tween = TweenLite.to(c, 0.4, {x: c.originX, y: c.originY, ease:Quad.easeInOut, alpha: 1, radius: 5, scaleX: 0.4, scaleY: 0.4, onComplete: function() { c.movement = 'jiggle';/*輕搖*/ tweenCircle(c); }}); } else if(dir == 'out') { c.tween = TweenLite.to(c, 0.8, {x: window.innerWidth*Math.random(), y: window.innerHeight*Math.random(), ease:Quad.easeInOut, alpha: 0.2 + Math.random()*0.5, scaleX: 1, scaleY: 1, onComplete: function() { c.movement = 'float'; tweenCircle(c); }}); } else { if(c.movement == 'float') { c.tween = TweenLite.to(c, 5 + Math.random()*3.5, {x: c.x + -100+Math.random()*200, y: c.y + -100+Math.random()*200, ease:Quad.easeInOut, alpha: 0.2 + Math.random()*0.5, onComplete: function() { tweenCircle(c); }}); } else { c.tween = TweenLite.to(c, 0.05, {x: c.originX + Math.random()*3, y: c.originY + Math.random()*3, ease:Quad.easeInOut, onComplete: function() { tweenCircle(c); }}); } } }
TweenLite.to函數(shù)第一個(gè)參數(shù),要做動(dòng)畫(huà)的實(shí)例,第二個(gè)參數(shù),事件,第三個(gè)參數(shù),動(dòng)畫(huà)改變參數(shù)。
Quad.easeInOut()意思是在動(dòng)畫(huà)開(kāi)始和結(jié)束時(shí)緩動(dòng)。onComplete動(dòng)畫(huà)完成時(shí)調(diào)用的函數(shù)。易得,在我們的應(yīng)用中,我們將開(kāi)始下一次動(dòng)畫(huà)。
個(gè)人感言
其實(shí)剛開(kāi)始沒(méi)想做這么復(fù)雜,所以文件排的比較隨意,然后就導(dǎo)致了后期項(xiàng)目完成時(shí)那副雜亂無(wú)章的樣子。^_^,以后改。等我等看懂動(dòng)畫(huà)效果時(shí)在說(shuō),現(xiàn)在用的有點(diǎn)半懵半懂。
這篇博客寫(xiě)得有點(diǎn)亂。新手之作,就先這樣吧。同上,以后改。因?yàn)椴恢肋@個(gè)項(xiàng)目會(huì)不會(huì)拿來(lái)直接當(dāng)我們計(jì)算機(jī)職業(yè)實(shí)踐的作業(yè)。要是的話(huà),我就徹改,連同博客。
以下是源代碼地址。
還在審核。明天再說(shuō)。相信我,我在小番茄里做了記錄。
總結(jié)
以上所述是小編給大家介紹的Html5寫(xiě)一個(gè)簡(jiǎn)單的俄羅斯方塊小游戲,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!如果你覺(jué)得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!
相關(guān)文章
使用數(shù)據(jù)結(jié)構(gòu)給女朋友寫(xiě)個(gè)Html5走迷宮游戲
本文給大家分享使用數(shù)據(jù)結(jié)構(gòu)給女朋友寫(xiě)個(gè)Html5走迷宮游戲功能,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2019-11-26- 本篇文章主要介紹了H5 canvas實(shí)現(xiàn)貪吃蛇小游戲,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-07-28
html5 canvas-2.用canvas制作一個(gè)猜字母的小游戲
今天我們要用canvas制作一個(gè)猜字母的小游戲,游戲設(shè)計(jì)很簡(jiǎn)單,系統(tǒng)會(huì)隨機(jī)從a-z的26個(gè)字母中選擇一個(gè)保存起來(lái),你鍵盤(pán)輸入一個(gè)字母,系統(tǒng)會(huì)提示你正確字符比你當(dāng)前輸入字母小2013-01-07HTML5+CSS+JavaScript實(shí)現(xiàn)捉蟲(chóng)小游戲設(shè)計(jì)和實(shí)現(xiàn)
這篇文章主要介紹了HTML5+CSS+JavaScript實(shí)現(xiàn)捉蟲(chóng)小游戲設(shè)計(jì)和實(shí)現(xiàn),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參2021-10-12