JavaScript寫個貪吃蛇小游戲(超詳細(xì))
貪吃蛇大家都玩過,但你會制作嘛?聽起來好像很難的樣子,其實非常的簡單,話不多說直接上代碼
我們先把dom結(jié)構(gòu)寫出來
<div id="content"> <div id="snake"> <div class="box head"></div> <div class="box"></div> </div> </div>
其中,content為整個布局的大盒子,snake就是蛇,里面的box就是他的身體,為了區(qū)分頭部我們給第一個box加了個head名字用于區(qū)分,下面我們再把css加上
<style> .box{ width: 60px; height: 60px; background-color: red; position:absolute; left: 0; top: 0; line-height: 60px; } .head{ background-color: yellowgreen; } </style>
我們給蛇的每一節(jié)的寬高設(shè)置為60像素,并給了一個定位,因為如果不加定位的話無法讓他脫離文檔流(在頁面中飄起來),而且后續(xù)也無法通過left和top來判斷他的坐標(biāo).
好的這樣我們就得到了一條可愛的小蛇(然鵝并沒有看出來哪里可愛- -)。什么?你問我他的頭哪去了,很簡單,在給元素加了定位以后后面的元素會覆蓋掉前面的元素,所以只是頭部和身體重疊了你看不到而已。
隨后咱們得讓這條蛇動起來是吧,那么我們怎么讓他動起來呢?原理很簡單,我們可以設(shè)置一個定時器,每過一個時間就讓他動一下,而怎么讓他動呢,只需要設(shè)置一個數(shù)值,讓這個值每動一下就+=60,然后通過判斷是上下動還是左右動,來給元素的left與top賦值。我們把邏輯寫成代碼,就出來了如下的代碼
<script> var boxs = document.querySelectorAll(".box"); var snake_x = 0; var snake_y = 0; var turn = "right"; setInterval(function(){ snakeMove(); },100) function snakeMove(){ switch( turn ){ case "right": snake_x += 60;break; case "left" : snake_x -= 60;break; case "top" : snake_y -= 60;break; case "bottom": snake_y += 60;break; } for(var i = boxs.length - 1; i > 0 ; i --){ boxs[i].style.left = boxs[i - 1].style.left; boxs[i].style.top = boxs[i - 1].style.top; } boxs[i].style.left = snake_x + "px"; boxs[i].style.top = snake_y + "px"; } document.onkeydown = function(evt){ var e = evt || event; var keyCode = e.keyCode || e.which; switch( keyCode ){ case 37 : turn = "left";break; case 38 : turn = "top";break; case 39 : turn = "right";break; case 40 : turn = "bottom";break; } } </script>
上述代碼中,我們給小蛇的初始位置的x和y的坐標(biāo)都設(shè)置為0,并且默認(rèn)初始向右走,通過鍵盤上方向鍵的輸入,來改變他的方向。其中,難點在于
for(var i = boxs.length - 1; i > 0 ; i --){ boxs[i].style.left = boxs[i - 1].style.left; boxs[i].style.top = boxs[i - 1].style.top; } boxs[i].style.left = snake_x + "px"; boxs[i].style.top = snake_y + "px";
這一塊代碼,這塊代碼的目的是讓后面的元素跟著前面的走,也就是讓蛇的每一塊身體都跟著上一塊去運動,然后最后再給頭部設(shè)置為snake_x和snake_y當(dāng)前的值即可,這樣就形成了第一塊(頭部)坐標(biāo)為
snake_x,snake_y
實時變化的值,第二塊為第一塊之前的值,第三塊為第二塊之前的值。。。以此類推就得到了一個身體跟著頭部走的效果
但是當(dāng)你把代碼輸進(jìn)去以后一運行會發(fā)現(xiàn),這條小蛇過于頑皮,以至于走到邊界以后還會無限的向前走,那這不行啊,總不能讓蛇跑了不是,所以得給小蛇加上一個邊界
var snake_x_max = document.documentElement.clientWidth ; var snake_y_max = document.documentElement.clientHeight; if(snake_x > snake_x_max){ snake_x = 0; } if(snake_x < 0){ snake_x = snake_x_max; } if(snake_y > snake_y_max){ snake_y = 0; } if(snake_y < 0){ snake_y = snake_y_max; }
這里我們設(shè)置x和y的最大值為當(dāng)前窗口的寬高,然后通過if語句進(jìn)行判斷,如果當(dāng)前坐標(biāo)大于了最大值,就講當(dāng)前坐標(biāo)歸0,如果小于0的話(也就是跑到了左邊的邊界),就將當(dāng)前坐標(biāo)設(shè)置為最大值,這樣就可以得到一個邊界啦
你以為這樣就完事啦?nonono,沒有食物吃的蛇怎么能叫做貪吃蛇呢,那是沒有靈魂噠。下面我們開始制作食物(不能讓蛇餓著是吧)。
<div id="food"> </div>
然后給他加個css
#food{ width: 60px; height: 60px; position: absolute; background: greenyellow; }
然后再綁定一下元素并將他的left和top值設(shè)為范圍內(nèi)隨機(jī)數(shù),這樣可以做到隨機(jī)位置生成
var fd=document.getElementById("food"); fd.style.left=Math.random()*snake_x_max+"px"; fd.style.top=Math.random()*snake_y_max+"px";
好的這樣我們就得到了一個隨機(jī)生成的食物
不過我們的小蛇好像對食物并沒有什么興趣呢,路過以后并不會吃掉,所以我們得給他加一個碰撞檢測吧,碰撞檢測的邏輯很簡單,只需要讓食物的left值與頭部的left值相減的絕對值<=食物的大小,并且食物的top值與頭部的top值相減的絕對值<=食物的大小,設(shè)置小于等于是因為如果直接用相等來判斷的話,必須兩個元素完全重合才行,我們需要的是碰到邊緣就算遲到,所以用兩個數(shù)值相減小于等于來做。然后判斷當(dāng)頭部與食物發(fā)生碰撞時,將蛇的身體部分克隆一塊出來放到蛇的身體里面,并讓食物的位置重新刷新(適用克隆為偷懶方法,此偷懶方法僅適用于當(dāng)小蛇開局自帶一個身體的時候,如果小蛇開局不自帶身體的話,我們無法克隆已有身體,只能通過createElement
去新創(chuàng)建一個身體塊出來并添加className
后再添加到父元素中去才行)。下面我們把邏輯轉(zhuǎn)換為代碼
var dl=snake_x; var dt=snake_y; var fl=fd.style.left; var ft=fd.style.top; var dv=document.querySelectorAll("#snake div"); var sk=document.getElementById("snake"); var a2=Number(fl.substring(0,fl.indexOf("px"))); var b2=Number(ft.substring(0,ft.indexOf("px"))); if(Math.abs(dl-a2)<=60&&Math.abs(dt-b2)<=60){ fd.style.left=Math.random()*1000+"px"; fd.style.top=Math.random()*800+"px"; sk.appendChild(dv[1].cloneNode()); boxs = document.querySelectorAll(".box"); }
其中那一大長串的substring的方法是因為獲取到的left與top的值的格式是例如”200px”這樣的數(shù)組,無法進(jìn)行數(shù)學(xué)運算,所以要把px給截掉,并將剩下的字符串”200”轉(zhuǎn)換成number類型才可以進(jìn)行數(shù)學(xué)運算。
這樣一個簡單的貪吃蛇就做好啦~
啥?你問我什么什么類似碰到自己會死這樣更多的規(guī)則機(jī)制咋沒寫,肯定是因為我懶啊!我連createElement都懶得用直接克隆一個出來了,咋會勤快到把剩下這么多的機(jī)制補(bǔ)全呢哈哈?;A(chǔ)機(jī)制我已經(jīng)寫出來了,各種奇奇怪怪的機(jī)制還是留給小伙伴們自由發(fā)揮吧~
PS:大家完全可以把頭部的背景圖片改成你小伙伴的照片,再把食物改成一些你想讓ta吃的東西,可以拿來惡搞啊哈哈哈
到此這篇關(guān)于JavaScript寫個貪吃蛇小游戲(超詳細(xì))的文章就介紹到這了,更多相關(guān)js 貪吃蛇內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript+CSS實現(xiàn)仿Mootools豎排彈性動畫菜單效果
這篇文章主要介紹了JavaScript+CSS實現(xiàn)仿Mootools豎排彈性動畫菜單效果,可實現(xiàn)鼠標(biāo)滑過菜單項呈現(xiàn)彈性移動顯示的效果,具有一定參考借鑒價值,需要的朋友可以參考下2015-10-10微信小程序?qū)崿F(xiàn)視頻播放器發(fā)送彈幕
這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)視頻播放器發(fā)送彈幕,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-04-04JavaScript實現(xiàn)網(wǎng)頁頭部進(jìn)度條刷新
這篇文章主要介紹了JavaScript實現(xiàn)網(wǎng)頁頭部進(jìn)度條刷新實例代碼,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-04-04asp.net HttpHandler實現(xiàn)圖片防盜鏈
這個例子來自于《Maximizing ASP.NET Real World, Object-Oriented Development》一書, 需要的朋友可以參考下。2009-11-11JavaScript實現(xiàn)模態(tài)框拖拽效果
這篇文章主要介紹了通過JavaScript實現(xiàn)模態(tài)框拖拽的效果,以及鼠標(biāo)松開,可以停止拖動模態(tài)框移動等功能,感興趣的小伙伴可以了解一下2021-12-12webpack項目使用eslint建立代碼規(guī)范實現(xiàn)
這篇文章主要介紹了webpack項目使用eslint建立代碼規(guī)范實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05學(xué)習(xí)JavaScript設(shè)計模式(單例模式)
這篇文章主要帶領(lǐng)大家學(xué)習(xí)JavaScript設(shè)計模式,其中重點介紹單例模式,舉例說明單例模式的技術(shù)、弊端等,對單例模式進(jìn)行詳細(xì)剖析,感興趣的小伙伴們可以參考一下2015-11-11