国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

如何用原生 JS,快速寫一個(gè)貪吃蛇小游戲

開發(fā) 前端
游戲元素的話一共有 3 個(gè),蛇頭,身體和蘋果。就用 3 個(gè)構(gòu)造函數(shù)來生成坐標(biāo),以及給對(duì)應(yīng)坐標(biāo)的那個(gè)對(duì)象里面添加不同的屬性。

前言

貪吃蛇算是小游戲里面比較好寫的,沒有什么難點(diǎn),基本上需要實(shí)現(xiàn)的功能,都能很順利的用代碼敲出來。

1、繪制游戲區(qū)域和游戲元素

仍然是用 16 * 16 的二維數(shù)組來繪制,對(duì)這個(gè)數(shù)組進(jìn)行遍歷。第一層遍歷的時(shí)候創(chuàng)建 tr,第二層遍歷的時(shí)候創(chuàng)建 td。然后添加一些 CSS 樣式,游戲區(qū)域就寫好了。

let arr = [  [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}],
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}],
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}],
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}],
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}],
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}],
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}],
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}],
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}],
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}],
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}],
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}],
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}],
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}],
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}],
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}],
]
//渲染游戲區(qū)域
const renderTable = () {
document.querySelector('table').innerHTML = ''
arr.forEach(item {
//第一層遍歷創(chuàng)建tr
let tr = document.createElement('tr')
item.forEach(item2 {
//第二層遍歷創(chuàng)建td
let td = document.createElement('td')
tr.appendChild(td)
})
document.querySelector('table').appendChild(tr)
})
}
renderTable()

CSS&HTML:

 <style>
table {
margin: 0px auto;
border-collapse: collapse;
border: 5px solid black;
}
td {
border-radius: 50%;
width: 40px;
height: 40px;
border: none
}
.bgc1 {
background-color: black;
}
.bgc2 {
background: url(./pngsucai_512252_f77802.png) no-repeat;
background-size: 100%;
z-index: 1;
}
.bgc3 {
background: url(./92034446ddc7a91edec038f2d69415fd.jpeg)no-repeat;
background-size: 100%;
z-index: 9;
}
.defen {
font-size: 30px;
position: absolute;
top: 40%;
right: 20px;
}
</style>
<body>
<table></table>
<div class="defen">
鍵盤上下左右控制,Enter鍵暫停
<br>
<br>
得分
<br>
<span>0</span>
</div>
<script src="./貪吃蛇2.0.js"></script>
</body>

游戲元素的話一共有 3 個(gè),蛇頭,身體和蘋果。就用 3 個(gè)構(gòu)造函數(shù)來生成坐標(biāo),以及給對(duì)應(yīng)坐標(biāo)的那個(gè)對(duì)象里面添加不同的屬性。用構(gòu)造函數(shù)寫既方便查找,也方便修改。然后寫個(gè)渲染函數(shù),格子里面對(duì)應(yīng)的不同的屬性,就渲染出不同的樣式。

//渲染樣式的函數(shù)
const renderColor = () {
arr.forEach((item, index) => {
const trArr = document.querySelectorAll('tr')
item.forEach((item2, index2) => {
//頭部渲染
if (item2.head === 1) {
trArr[index].querySelectorAll('td')[index2].classList.add('bgc3')
}
//身體渲染成黑色
else if (item2.body === 1) {
trArr[index].querySelectorAll('td')[index2].classList.remove('bgc3')
trArr[index].querySelectorAll('td')[index2].classList.remove('bgc2')
trArr[index].querySelectorAll('td')[index2].classList.add('bgc1')
}
//蘋果渲染
else if (item2.apple === 1) {
trArr[index].querySelectorAll('td')[index2].classList.add('bgc2')
}
//如果是其他的值,就把這個(gè)樣式清空
else {
trArr[index].querySelectorAll('td')[index2].className = ''
}
})
})
}
//蛇頭構(gòu)造函數(shù)
function Head(x, y) {
this.x = x
this.y = y
this.render = function (a) {
arr[this.y][this.x].head = a
}
}
//身體構(gòu)造函數(shù)
function Body(x, y) {
this.x = x
this.y = y
this.render = function (a) {
arr[this.y][this.x].body = a
}
}
//蘋果構(gòu)造函數(shù)
function Apple(x, y) {
this.x = x
this.y = y
this.render = function (a) {
arr[this.y][this.x].apple = a
}
}
//依次渲染默認(rèn)出現(xiàn)的頭部,身體和蘋果
let a = new Head(10, 10)
a.render(1)
//聲明一個(gè)存放身體元素的數(shù)組,移動(dòng)以及判斷獲勝都需要用到這個(gè)數(shù)組的功能
let bodyArr = []
let b = new Body(10, 11)
bodyArr.push(b)
b.render(1)
let c = new Apple(5, 5)
c.render(1)
renderColor()

2、移動(dòng)功能

移動(dòng)功能要分兩個(gè)步驟來寫。一個(gè)是蛇頭的移動(dòng),一個(gè)是身體的移動(dòng)。貪吃蛇的身體它不是一個(gè)整理,是不能寫成一塊的。蛇頭動(dòng)的時(shí)候,身體它得扭來扭去,這才像個(gè)蛇。

蛇頭移動(dòng)很簡單,上下左右鍵對(duì)應(yīng)著蛇頭 X 和 Y 兩個(gè)值的加減。X 和 Y 超出范圍,代碼就會(huì)報(bào)錯(cuò)。就可以直接用 try catch 來判斷邊界。報(bào)錯(cuò)了就說明出界了,直接走 catch 的游戲結(jié)束。

注意: 這個(gè)游戲唯一麻煩一點(diǎn)的地方來了,怎么讓蛇身體能扭起來。相通一個(gè)邏輯,這個(gè)問題就迎刃而解了。

蛇身體怎么移動(dòng),是身體里的每個(gè)元素都往前移動(dòng)一格嗎,顯然不是。仔細(xì)觀察你會(huì)發(fā)現(xiàn),蛇移動(dòng)時(shí),身體的中間部分其實(shí)是不動(dòng)的。動(dòng)的只有最前端和最末端的兩格。也就是說蛇移動(dòng)時(shí),其實(shí)就是把身體最末端的格子移動(dòng)到了身體最前端,其他的都不需要?jiǎng)印G懊媛暶鞯纳眢w元素?cái)?shù)組就是這個(gè)時(shí)候用的。把身體的最后一個(gè)元素移動(dòng)到頭部,同時(shí)數(shù)組里的最后一個(gè)元素也要移動(dòng)到最前面去。

//上下左右移動(dòng)函數(shù)
const up = () {
//用try catch來判斷是否出界
try { //把移動(dòng)的函數(shù)寫在try里面,如果出界了就會(huì)報(bào)錯(cuò),然后走catch里的代碼
//移動(dòng)的時(shí)候先清除當(dāng)前格子的樣式
a.render(0)
a.y -= 1
//然后渲染新樣式
a.render(1)
} catch {
clearInterval(timer)
alert('游戲結(jié)束!')
location.reload()
}
//調(diào)用吃蘋果函數(shù)
eat()
//讓數(shù)組中的最后一個(gè)元素,移動(dòng)到頭部剛才所在的位置
bodyArr[bodyArr.length - 1].render(0)
//這個(gè)a.x,a.y+1就是頭部移動(dòng)前的坐標(biāo)
bodyArr[bodyArr.length - 1].x = a.x
bodyArr[bodyArr.length - 1].y = a.y + 1
bodyArr[bodyArr.length - 1].render(1)
//把身體數(shù)組里的最后一個(gè)元素移到最開頭
bodyArr.unshift(bodyArr.pop())
renderColor()
//調(diào)用判斷游戲結(jié)束函數(shù)
end()
}
const down = () {
try {
a.render(0)
a.y += 1
a.render(1)
}
catch {
clearInterval(timer)
alert('游戲結(jié)束!')
location.reload()
}
eat()
//讓數(shù)組中的最后一個(gè)元素,移動(dòng)到頭部剛才所在的位置
bodyArr[bodyArr.length - 1].render(0)
bodyArr[bodyArr.length - 1].x = a.x
bodyArr[bodyArr.length - 1].y = a.y - 1
bodyArr[bodyArr.length - 1].render(1)
bodyArr.unshift(bodyArr.pop())
renderColor()
end()
}
const right = () {
try {
a.render(0)
a.x += 1
a.render(1)
}
catch {
clearInterval(timer)
alert('游戲結(jié)束!')
location.reload()
}
eat()
//讓數(shù)組中的最后一個(gè)元素,移動(dòng)到頭部剛才所在的位置
bodyArr[bodyArr.length - 1].render(0)
bodyArr[bodyArr.length - 1].x = a.x - 1
bodyArr[bodyArr.length - 1].y = a.y
bodyArr[bodyArr.length - 1].render(1)
bodyArr.unshift(bodyArr.pop())
renderColor()
end()
}
const left = () {
try {
a.render(0)
a.x -= 1
a.render(1)
}
catch {
clearInterval(timer)
alert('游戲結(jié)束!')
location.reload()
}
eat()
//讓數(shù)組中的最后一個(gè)元素,移動(dòng)到頭部剛才所在的位置
bodyArr[bodyArr.length - 1].render(0)
bodyArr[bodyArr.length - 1].x = a.x + 1
bodyArr[bodyArr.length - 1].y = a.y
bodyArr[bodyArr.length - 1].render(1)
bodyArr.unshift(bodyArr.pop())
renderColor()
end()
}

3、寫鍵盤事件

寫鍵盤事件的時(shí)候要加一個(gè)判斷,讓這個(gè)蛇只能夠相對(duì)它自身左右移動(dòng)。不能掉頭,也不能向前沖,向前沖很容易就撞到墻了。

let num = 1
document.addEventListener('keydown', function (e) {
//flag是暫停功能的變量
if (flag) {
if (e.key === 'ArrowDown') {
//蛇頭只能夠向左或者向右移動(dòng),否則沖太快容易死。也不可以調(diào)頭。
if (num == 2 || num == 4) {
down()
num = 3
}
} else if (e.key === 'ArrowRight') {
if (num == 1 || num == 3) {
right()
num = 2
}
} else if (e.key === 'ArrowLeft') {
if (num == 1 || num == 3) {
left()
num = 4
}
} else if (e.key === 'ArrowUp') {
if (num == 2 || num == 4) {
up()
num = 1
}
}
}
})

4、吃蘋果功能

吃蘋果功能分為 3 個(gè)步驟

1.判斷頭部和蘋果有沒有重合,重合的話,就讓這個(gè)蘋果消失,讓分?jǐn)?shù) +1。

2.生成隨機(jī)坐標(biāo)來渲染蘋果,判斷一下這個(gè)坐標(biāo)上是否與蛇身體重合了,重合的話就要重新生成坐標(biāo)。

3.生成一個(gè)新的身體實(shí)例,并且把這個(gè)新實(shí)例添加到身體數(shù)組中。

//得分
let fen = 0
//吃蘋果
const eat = () {
//如果頭部和蘋果重合了
if (arr[a.y][a.x].apple == 1) {
//清除這個(gè)蘋果
arr[a.y][a.x].apple = 0
//分?jǐn)?shù)加1
fen++
//調(diào)用判斷游戲勝利函數(shù)
win()
//渲染分?jǐn)?shù)
document.querySelector('.defen span').innerHTML = fen
//用循環(huán)來生成新蘋果,滿足條件就退出循環(huán)
while (true) {
const x = Math.floor(Math.random() * 16)
const y = Math.floor(Math.random() * 16)
//判斷蘋果不能出現(xiàn)在身體上
if (!arr[y][x].head && !arr[y][x].body) {
arr[y][x].apple = 1
break
}
}
//生成新的身體實(shí)例
let b = new Body(bodyArr[bodyArr.length - 1].x, bodyArr[bodyArr.length - 1].y)
b.render(1)
bodyArr.push(b)
}
}

5、頭部碰到身體游戲失敗的功能

和吃蘋果的邏輯一樣,就判斷頭部和身體是不是重合的。

//碰到身體游戲失敗判定
const end = () {
//如果頭部和身體重合了
if (arr[a.y][a.x].body == 1) {
clearInterval(timer)
alert('游戲結(jié)束!')
location.reload(true)
}
}

6、自動(dòng)移動(dòng)的功能

自動(dòng)移動(dòng)可以通過間歇函數(shù)來實(shí)現(xiàn),然后不能單純的在間歇函數(shù)的回調(diào)里面寫上下左右的某一個(gè),要判斷一下蛇當(dāng)前的移動(dòng)方向是什么。然后來一個(gè)分?jǐn)?shù)越高速度越快的功能。

//自動(dòng)向前移動(dòng)功能
let timer
//封裝一個(gè)向前移動(dòng)的函數(shù)
function move() {
if (num == 1) {
up()
} else if (num == 2) {
right()
} else if (num == 3) {
down()
} else {
left()
}
}
//寫自動(dòng)移動(dòng)的間歇函數(shù)
time()
function time() {
//來個(gè)分越高速度越快的功能
if (fen <= 20) {
timer = setInterval(function () {
move()
}, 250)
} else if (fen > 20 && fen <= 40) {
clearInterval(timer)
timer = setInterval(function () {
move()
}, 200)
} else {
clearInterval(timer)
timer = setInterval(function () {
move()
}, 150)
}
}

7、暫停功能和判斷游戲勝利

這兩個(gè)比較簡單,就一起說了。暫停功能就是讓定時(shí)器停止,并且讓flag變量變?yōu)閒alse。這樣就不能再去控制蛇了。這個(gè)游戲一共有256個(gè)格子,勝利的條件就是身體有255個(gè)元素,因?yàn)橐獪p去一個(gè)頭部。

//暫停功能
let flag = true
document.addEventListener('keydown', function (e) {
if (flag) {
if (e.key === 'Enter') {
clearInterval(timer)
flag = !flag
}
} else {
if (e.key === 'Enter') {
time()
flag = true
}
}
})
//勝利條件,身體數(shù)組的元素等于255個(gè)就獲勝
const win = () {
if (bodyArr.length == 255) {
clearInterval(timer)
alert('游戲勝利!')
location.reload()
}
}

寫在最后

游戲到這里就寫完了,代碼雖然看起來多,但是并沒有什么難的地方,想到就能寫。唯一麻煩一點(diǎn)的就是那個(gè)身體的移動(dòng),相通了就很簡單了。

責(zé)任編輯:姜華 來源: 前端YUE
相關(guān)推薦

2020-08-20 20:30:49

C語言小游戲貪吃蛇

2022-11-09 11:57:17

原生JS五子棋

2012-06-05 14:42:57

Silverlight

2021-06-15 09:18:51

鴻蒙HarmonyOS應(yīng)用

2024-12-17 17:46:05

Android原生控件貪吃蛇

2022-07-25 14:17:04

JS應(yīng)用開發(fā)

2015-07-31 11:26:24

Swift貪吃蛇

2023-10-17 10:20:53

VueReact

2021-09-02 15:25:53

鴻蒙HarmonyOS應(yīng)用

2024-01-18 11:22:41

C++Windows開發(fā)

2022-10-28 09:33:10

Linux貪吃蛇

2023-05-11 08:26:56

2021-04-20 11:40:12

Linux圖形庫curses

2021-04-13 06:35:13

Elixir語言編程語言軟件開發(fā)

2016-09-22 21:12:14

2016-09-19 21:24:08

PythonAsyncio游戲

2022-03-24 07:57:58

Python水果忍者游戲

2020-11-30 06:20:13

javascript

2016-09-14 21:17:47

PythonAsyncio游戲

2025-02-27 09:31:05

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

美女网站在线免费欧美精品| 亚洲国产欧美精品| 亚洲国产激情一区二区三区| 欧美日韩福利| 国产精品久久久久av| 98视频精品全部国产| 亚洲国产91精品在线观看| 蜜桃av在线免费观看| 亚洲成人激情综合网| h色视频在线观看| 亚洲视频在线观看三级| 日本超碰在线观看| 国产亚洲精品中文字幕| 男人女人黄一级| 国产精品污www在线观看| xx欧美撒尿嘘撒尿xx| 中文字幕精品三区| 明星乱亚洲合成图.com| 亚洲人成网站色在线观看| 成视频年人免费看黄网站| 国产精品国产三级国产| 777免费视频| 亚洲国产精品视频| 黄色免费在线播放| 欧美一级午夜免费电影| 精品一性一色一乱农村| 精品国产乱码久久久久久牛牛| 四虎亚洲精品| 亚洲色图15p| 欧美日韩中出| 国产成人精品日本亚洲| 日韩欧美在线中字| 国产精华一区二区三区| 蜜桃伊人久久| 成人免费看片'免费看| 不卡影院免费观看| 任你操这里只有精品| 亚洲视频香蕉人妖| 中文字幕av高清在线观看| 在线观看91视频| 二区三区在线观看| 亚洲日本中文字幕| av不卡一区二区| 成人av电影天堂| 玖玖精品视频| 欧美黑人在线观看| 亚洲美女屁股眼交| 米奇精品一区二区三区| 亚洲奶大毛多的老太婆| 天堂精品久久久久| 国产精品福利在线观看| 亚洲大胆视频| 欧美大黑帍在线播放| 综合电影一区二区三区| 国产youjizz在线| 国产午夜精品久久久 | a视频在线观看| 亚洲视频第一页| 欧美中文一区| 精品中文字幕人| 成人国产一区二区三区精品| 日韩欧美国产片| 欧美军同video69gay| yw.尤物在线精品视频| 国产精品美女呻吟| 精品一区二区三区欧美| 日本高清中文字幕| 日韩成人激情视频| 欧美**vk| 9色视频在线观看| 亚洲一区二区视频| 91破解版在线观看| 97色伦亚洲国产| 国产欧美亚洲一区| 久久婷婷国产精品| 欧美精品aⅴ在线视频| 97se亚洲| 亚洲国产精品一区在线观看不卡| 亚洲欧美日韩成人高清在线一区| 黄色影院在线看| 国产日韩精品一区二区| 99免费精品视频| 久草中文在线| 日韩av片电影专区| 国产东北露脸精品视频| 国产三区四区在线观看| 久久亚洲成人精品| 久久久亚洲人| 中文字幕av在线播放| 久久在线视频在线| 亚洲欧美日韩国产综合精品二区 | 在线一区视频| 99免费视频| 亚洲精品电影久久久| 日韩欧美一区二区三区在线视频| 久久精品在线免费视频| 色妹子一区二区| **精品中文字幕一区二区三区| 国产精品一区二区a| 国产精品区一区二区三| 日韩电影av| 品久久久久久久久久96高清| 激情av一区二区| 成人高潮a毛片免费观看网站| 国产成人三级视频| 欧美疯狂性受xxxxx喷水图片| 欧美军人男男激情gay| av免费中文字幕| 日韩理论片久久| 性感少妇一区| 国产美女视频一区二区三区 | 久久青草免费| 亚洲资源视频| 欧美午夜精品久久久久久超碰| 妖精一区二区三区精品视频| 91av资源网| 亚洲天堂免费视频| 日韩福利电影在线| 91高清在线视频| 91超碰在线免费观看| 午夜天堂影视香蕉久久| 在线视频亚洲专区| 三级短视频在线| 久久琪琪电影院| 国产日韩欧美高清在线| 欧美不卡在线观看| 日韩欧美xxxx| 97国产在线观看| 中文字幕一区二区三区精华液 | 色哟哟入口国产精品| 国产精品一区二区在线观看网站| segui88久久综合| 亚洲欧美国产不卡| 日韩精品一区二区在线| 天堂久久一区二区三区| 欧美人与牲禽动交com | 欧美一级视频| 污污的网站在线看| 性欧美.com| 亚洲国产天堂久久国产91| 蜜臀精品一区二区三区在线观看 | 国产a久久精品一区二区三区| 91福利国产成人精品播放| 久久久99免费视频| 2023国产精品| **爰片久久毛片| 国产主播色在线| 91精品视频在线播放| 欧美亚州韩日在线看免费版国语版| 亚洲黄色大片| 热色播在线视频| 国产aaa一级片| 日韩美女视频中文字幕| 天天色综合成人网| 亚洲影视综合| 免费成人动漫| 成人一区二区三| 国产成人在线一区| 欧美日韩亚洲视频| 视频一区视频二区中文字幕| 日韩不卡免费高清视频| 五月婷婷丁香综合网| 国产精品pans私拍| 欧美影院精品一区| 精品一区二区三区免费毛片爱| 成人国产精品一区二区网站| www.三区| 韩国成人一区| 最近的2019中文字幕免费一页| 国产精品传媒视频| 激情欧美国产欧美| 欧洲亚洲两性| 成人18免费| 999精品视频一区二区三区| 精品av久久707| 中文av字幕一区| 一区二区三区成人精品| 四虎精品永久免费| 最近中文视频在线| 亚洲视频小说| 欧美亚洲成人xxx| 欧美另类高清zo欧美| 国产91丝袜在线18| 国产成人影院| 国产三级在线播放| 91香蕉视频导航| 成人片在线免费看| 日韩色av导航| 欧美色综合天天久久综合精品| 国产成人精品免费在线| 日韩理论在线| 影音成人av| gogogo高清在线观看免费完整版| 强伦女教师2:伦理在线观看| 日本国产精品视频| 亚洲国产精品专区久久| 一区二区欧美精品| 成人午夜视频网站| 伊人久久大香线蕉综合热线| 日韩国产在线不卡视频|