javascript實(shí)現(xiàn)打磚塊小游戲(附完整源碼)
小時(shí)候玩一天的打磚塊小游戲,附完整源碼
在?給個(gè)贊?
實(shí)現(xiàn)如圖
需求分析
1、小球在觸碰到大盒子上、左、右邊框,以及滑塊后沿另一方向反彈,在碰到底邊框后游戲結(jié)束;
2、小球在觸碰到方塊之后,方塊消失;
3、消除所有方塊獲得游戲勝利;
4、可通過鼠標(biāo)與鍵盤兩種方式移動(dòng)滑塊;
5、游戲難度可調(diào)整,實(shí)時(shí)顯示得分。
代碼分析
1、html結(jié)構(gòu):左右兩個(gè)提示框盒子分別用一個(gè)div,在其中添加需要的內(nèi)容;中間主體部分用一個(gè)div,里面包含一個(gè)滑塊(slider),一個(gè)小球(ball),以及一個(gè)裝有所有方塊的brick盒子,我們通過使用js在brick中動(dòng)態(tài)添加方塊,這樣大大減少了div的數(shù)量。簡(jiǎn)化了html結(jié)構(gòu)。
2、css樣式:通過使用position:relative/absolute/fixed,完成對(duì)整個(gè)頁(yè)面的布局;
3、js行為:首先對(duì)于小球的運(yùn)動(dòng),我們通過使用setInterval定時(shí)器進(jìn)行實(shí)現(xiàn);小球與滑塊以及方塊之間的碰撞,我們通過碰撞檢測(cè)函數(shù)進(jìn)行實(shí)現(xiàn);滑塊的移動(dòng)我們需要設(shè)置兩種方法,通過鼠標(biāo)實(shí)現(xiàn)可以使用拖拽;通過鍵盤實(shí)現(xiàn)使用鍵盤事件。
一些封裝的函數(shù)
動(dòng)態(tài)創(chuàng)建方塊
函數(shù)分析
1、首先,我們?cè)趇d=“brick”的div盒子中動(dòng)態(tài)插入n個(gè)方塊,在css中預(yù)先為這些盒子設(shè)置了固定的寬高,并設(shè)置了左浮動(dòng)布局。這樣,所有的方塊就會(huì)按照自左到右自上而下排列在盒子中;但是通過浮動(dòng)布局在中間某一個(gè)方塊碰撞消失后,后面的方塊會(huì)補(bǔ)充上來(lái),這并不是我們想要的;
2、為了防止后面的方塊向前移動(dòng),顯然我們不能使用浮動(dòng),在這里我們對(duì)每一個(gè)方塊使用絕對(duì)定位;
3、在給每一個(gè)方塊進(jìn)行絕對(duì)定位之前,我們先要獲取它們當(dāng)前所在位置的left與top值,并賦給它們,否則方塊將全部擠在一個(gè)格子里;
4、最后再給每個(gè)方塊進(jìn)行絕對(duì)定位。
function createBrick(n){ var oBrick = document.getElementById("brick") //在大盒子brick中插入n個(gè)div方塊,并給予隨機(jī)顏色 for(var i = 0; i<n; i++){ var node = document.createElement("div"); node.style.backgroundColor= color(); oBrick.appendChild(node); } //獲取所有的方塊 var brickArr = obrick.getElementsByTagName("div") //根據(jù)每個(gè)方塊當(dāng)前所在位置,將left與top值賦給方塊 for(var i=0;i<brickArr.length;i++){ brickArr[i].style.left = brickArr[i].offsetLeft+"px"; brickArr[i].style.top = brickArr[i].offsetTop+"px"; } //將所有方塊設(shè)置成絕對(duì)定位,注意這一步與上一步順序不能調(diào)換 for(var i =0;i<brickArr.length;i++){ brickArr[i].style.position="absolute"; } }
碰撞檢測(cè)函數(shù)
代碼分析見上一篇
function knock(node1,node2){ var l1 = node1.offsetLeft; var r1 = node1.offsetLeft + node1.offsetWidth; var t1 = node1.offsetTop; var b1 = node1.offsetTop+node1.offsetHeight; var l2 = node2.offsetLeft; var r2 = node2.offsetLeft + node2.offsetWidth; var t2 = node2.offsetTop; var b2 = node2.offsetTop+node2.offsetHeight; if(l2>r1||r2<l1||t2>b1||b2<t1){ return false; }else{ return true; } }
完整代碼(復(fù)制可用)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>打磚塊小游戲</title> <style> #box{ width: 600px;height: 650px;border: 5px solid rgb(168, 139, 8); position: relative;left: 500px; background:linear-gradient(rgb(19, 192, 120),rgb(47, 32, 114)); } #ball{ width: 20px;height: 20px;border-radius: 10px; background-color: white;position: absolute; top: 560px;box-shadow: 0px 0px 3px 3px aqua; } #btn{ width: 150px;height: 90px;position: fixed;left: 730px;top: 350px; border-radius: 10px;font-size: 24px;cursor: pointer; } #slider{ width: 120px;height: 20px;background-color: rgb(168, 139, 8);position: absolute; top: 585px;border-radius: 10px;box-shadow: 0px 0px 2px 2px red;cursor: pointer; } #brick div{ width: 98px;height: 20px;float: left;border: 1px solid black; } #tip{ width: 280px;position:fixed;top: 100px;left: 150px; border: 1px solid black;text-indent: 2em;padding: 10px;border-radius: 20px; } #grade{ width: 180px;position:fixed;top: 100px;left: 1150px; border: 1px solid black;text-indent: 2em;padding: 10px;border-radius: 20px; } #grade h3{ font-weight: 500; } </style> </head> <body> <div id="box"> <div id="ball"></div> <div id="slider"></div> <div id="brick"></div> </div> <div id="tip"> <h1>提示</h1> <p>點(diǎn)擊按鈕開始游戲</p> <p>方法1:使用鼠標(biāo)按住滑塊,左右拖動(dòng),反彈小球</p> <p>方法2:使用鍵盤“左”“右”方向鍵控制滑塊移動(dòng),按住快速移動(dòng)</p> <p>小球觸碰到底部為失敗</p> <p>清空所有方塊游戲勝利</p> </div> <div id="grade"> <h3>游戲強(qiáng)度:</h3> <h2>XXX</h2> <h3>得分:</h3> <h1>00</h1> </div> <button id="btn">開始游戲</button> <script> var box = document.getElementById("box"); var ball = document.getElementById("ball"); var btn = document.getElementById("btn"); var slider = document.getElementById("slider") var obrick = document.getElementById("brick") var brickArr = obrick.getElementsByTagName("div") var grade = document.getElementById("grade") var rank = grade.children[1] var score = grade.children[3] var sco = 0; var timer; var isRunning = false; var speedX = rand(3,12); var speedY = -rand(3,12); var num =speedX-speedY; console.log(num) switch(num){ case 6:case 7:case 8: rank.innerHTML="簡(jiǎn)單"; break; case 9:case 10:case 11: rank.innerHTML="一般"; break; case 12:case 13:case 14: rank.innerHTML="中等"; break; case 15:case 16:case 17: rank.innerHTML="難" break; case 18:case 19:case 20: rank.innerHTML="很難" slider.style.width = 100+"px"; break; case 21:case 22: rank.innerHTML="特別難" slider.style.width = 80+"px"; break; case 23:case 24: rank.innerHTML="哭了" slider.style.width = 60+"px"; break; } //隨機(jī)生成小球與滑塊位置 var beginGo = rand(100,500) ball.style.left = beginGo +40 +"px" slider.style.left = beginGo +"px" //開始按鈕點(diǎn)擊事件 btn.onclick = function(){ btn.style.display="none"; isRunning = true; clearInterval(timer); timer = setInterval(function(){ //獲取小球初始位置 var ballLeft = ball.offsetLeft; var ballTop = ball.offsetTop; //獲取小球運(yùn)動(dòng)之后位置 var nextleft = ballLeft + speedX; var nexttop = ballTop + speedY; //水平邊界判斷,當(dāng)小球的left值小于容器左邊界或者大于容器右邊界時(shí),將水平方向速度取反 if(nextleft<=0||nextleft>=box.offsetWidth-ball.offsetWidth-10){ speedX=-speedX; } //垂直邊界判斷,當(dāng)小球的top值小于容器上邊界時(shí),將垂直方向速度取反 if(nexttop<=0){ speedY=-speedY; } //當(dāng)小球觸碰到下邊界時(shí),提示“游戲失敗”,重新刷新頁(yè)面 if(nexttop>box.offsetHeight-ball.offsetHeight){ location.reload(); alert("You were dead!") } //將運(yùn)動(dòng)后的位置重新賦值給小球 ball.style.left = nextleft+"px"; ball.style.top= nexttop+"px"; //小球與滑塊的碰撞檢測(cè) if(knock(ball,slider)){ speedY=-speedY; } //小球與方塊的碰撞檢測(cè) for(var j=0; j<brickArr.length;j++){ if(knock(brickArr[j],ball)){ speedY=-speedY obrick.removeChild(brickArr[j]); sco++; score.innerHTML=sco; break; } } //當(dāng)容器中方塊數(shù)量為0時(shí),宣布“游戲勝利”,刷新頁(yè)面 if(brickArr.length<=0){ location.reload(); alert("You win!") } },20) } //鼠標(biāo)控制滑塊 slider.onmousedown = function(e){ var e = e||window.event; //獲取滑塊初始位置 var offsetX = e.clientX - slider.offsetLeft; if(isRunning){ document.onmousemove = function(e){ var e = e||window.event; var l =e.clientX-offsetX; if(l<=0){ l=0; } if(l>=box.offsetWidth-slider.offsetWidth-10){ l=box.offsetWidth-slider.offsetWidth-10 ; } slider.style.left = l + "px"; } } } document.onmouseup = function(){ document.onmousemove = null; } //按鍵控制滑塊 document.onkeydown = function(e){ var e = e||window.event; var code = e.keyCode || e.which; var offsetX = slider.offsetLeft; if(isRunning){ switch(code){ case 37: if(offsetX<=0){ slider.style.left=0 break; } slider.style.left = offsetX*4/5 + "px"; break; case 39: if(offsetX>=box.offsetWidth-slider.offsetWidth-10){ slider.style.left=box.offsetWidth-slider.offsetWidth; break; } slider.style.left = (box.offsetWidth-slider.offsetWidth-offsetX)/5 +offsetX + "px"; break; } } } createBrick(72) //容器內(nèi)創(chuàng)建方塊 function createBrick(n){ var oBrick = document.getElementById("brick") //在大盒子brick中插入n個(gè)div方塊,并給予隨機(jī)顏色 for(var i = 0; i<n; i++){ var node = document.createElement("div"); node.style.backgroundColor= color(); oBrick.appendChild(node); } //獲取所有的方塊 var brickArr = obrick.getElementsByTagName("div") //根據(jù)每個(gè)方塊當(dāng)前所在位置,將left與top值賦給方塊 for(var i=0;i<brickArr.length;i++){ brickArr[i].style.left = brickArr[i].offsetLeft+"px"; brickArr[i].style.top = brickArr[i].offsetTop+"px"; } //將所有方塊設(shè)置成絕對(duì)定位,注意這一步與上一步順序不能調(diào)換 for(var i =0;i<brickArr.length;i++){ brickArr[i].style.position="absolute"; } } //隨機(jī)生成顏色 function color(){ var result= "#"; for(var i=0;i<6;i++){ result += rand(0,15).toString(16) // 把十進(jìn)制的數(shù)字變成十六進(jìn)制的字符串:0 1 ...9 a b c d f } return result; } //隨機(jī)數(shù)生成 function rand(n,m){ return n+parseInt(Math.random()*(m-n+1)); } //碰撞檢測(cè)函數(shù) function knock(node1,node2){ var l1 = node1.offsetLeft; var r1 = node1.offsetLeft + node1.offsetWidth; var t1 = node1.offsetTop; var b1 = node1.offsetTop+node1.offsetHeight; var l2 = node2.offsetLeft; var r2 = node2.offsetLeft + node2.offsetWidth; var t2 = node2.offsetTop; var b2 = node2.offsetTop+node2.offsetHeight; if(l2>r1||r2<l1||t2>b1||b2<t1){ return false; }else{ return true; } } </script> </body> </html>
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
JavaScript中Require調(diào)用js的實(shí)例分享
下面小編就為大家?guī)?lái)一篇JavaScript中Require調(diào)用js的實(shí)例分享。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧2017-10-10JavaScript canvas實(shí)現(xiàn)帶有陰影的圖形和文字
這篇文章主要為大家詳細(xì)介紹了JavaScript canvas實(shí)現(xiàn)帶有陰影的圖形和文字,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-03-03JS實(shí)現(xiàn)批量上傳文件并顯示進(jìn)度功能
這篇文章主要介紹了JS實(shí)現(xiàn)批量上傳文件并顯示進(jìn)度功能,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-06-06javascript中l(wèi)ocalStorage本地存儲(chǔ)(新增、刪除、修改)使用詳細(xì)教程
本地存儲(chǔ)localstorage是一種在瀏覽器中存儲(chǔ)數(shù)據(jù)的方式,可以將數(shù)據(jù)保存在用戶的本地計(jì)算機(jī)上,以便在下一次訪問網(wǎng)站時(shí)使用,下面這篇文章主要給大家介紹了關(guān)于javascript中l(wèi)ocalStorage本地存儲(chǔ)(新增、刪除、修改)使用詳細(xì)教程,需要的朋友可以參考下2023-05-05js+CSS簡(jiǎn)單實(shí)現(xiàn)瀑布流布局
瀑布流布局,是一種視覺表現(xiàn)為參差不齊的多欄布局,常用于內(nèi)容以圖片為主的頁(yè)面展示,本文將使用css和js兩種方式來(lái)實(shí)現(xiàn)瀑布流布局,需要的可以參考下2023-11-11