自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

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

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

前言

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

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

仍然是用 16 * 16 的二維數(shù)組來繪制,對這個數(shù)組進行遍歷。第一層遍歷的時候創(chuàng)建 tr,第二層遍歷的時候創(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 個,蛇頭,身體和蘋果。就用 3 個構(gòu)造函數(shù)來生成坐標(biāo),以及給對應(yīng)坐標(biāo)的那個對象里面添加不同的屬性。用構(gòu)造函數(shù)寫既方便查找,也方便修改。然后寫個渲染函數(shù),格子里面對應(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')
}
//如果是其他的值,就把這個樣式清空
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
}
}
//依次渲染默認出現(xiàn)的頭部,身體和蘋果
let a = new Head(10, 10)
a.render(1)
//聲明一個存放身體元素的數(shù)組,移動以及判斷獲勝都需要用到這個數(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、移動功能

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

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

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

蛇身體怎么移動,是身體里的每個元素都往前移動一格嗎,顯然不是。仔細觀察你會發(fā)現(xiàn),蛇移動時,身體的中間部分其實是不動的。動的只有最前端和最末端的兩格。也就是說蛇移動時,其實就是把身體最末端的格子移動到了身體最前端,其他的都不需要動。前面聲明的身體元素數(shù)組就是這個時候用的。把身體的最后一個元素移動到頭部,同時數(shù)組里的最后一個元素也要移動到最前面去。

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

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

let num = 1
document.addEventListener('keydown', function (e) {
//flag是暫停功能的變量
if (flag) {
if (e.key === 'ArrowDown') {
//蛇頭只能夠向左或者向右移動,否則沖太快容易死。也不可以調(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 個步驟

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

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

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

//得分
let fen = 0
//吃蘋果
const eat = () {
//如果頭部和蘋果重合了
if (arr[a.y][a.x].apple == 1) {
//清除這個蘋果
arr[a.y][a.x].apple = 0
//分數(shù)加1
fen++
//調(diào)用判斷游戲勝利函數(shù)
win()
//渲染分數(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
}
}
//生成新的身體實例
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、自動移動的功能

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

//自動向前移動功能
let timer
//封裝一個向前移動的函數(shù)
function move() {
if (num == 1) {
up()
} else if (num == 2) {
right()
} else if (num == 3) {
down()
} else {
left()
}
}
//寫自動移動的間歇函數(shù)
time()
function time() {
//來個分越高速度越快的功能
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、暫停功能和判斷游戲勝利

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

//暫停功能
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個就獲勝
const win = () {
if (bodyArr.length == 255) {
clearInterval(timer)
alert('游戲勝利!')
location.reload()
}
}

寫在最后

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

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

2020-08-20 20:30:49

C語言小游戲貪吃蛇

2022-11-09 11:57:17

原生JS五子棋

2021-06-15 09:18:51

鴻蒙HarmonyOS應(yīng)用

2012-06-05 14:42:57

Silverlight

2024-12-17 17:46:05

Android原生控件貪吃蛇

2022-07-25 14:17:04

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

2015-07-31 11:26:24

Swift貪吃蛇

2024-01-18 11:22:41

C++Windows開發(fā)

2021-09-02 15:25:53

鴻蒙HarmonyOS應(yīng)用

2022-10-28 09:33:10

Linux貪吃蛇

2023-10-17 10:20:53

VueReact

2021-04-20 11:40:12

Linux圖形庫curses

2023-05-11 08:26:56

2021-04-13 06:35:13

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

2016-09-22 21:12:14

2022-03-24 07:57:58

Python水果忍者游戲

2020-11-30 06:20:13

javascript

2016-09-19 21:24:08

PythonAsyncio游戲

2016-09-14 21:17:47

PythonAsyncio游戲

2025-02-27 09:31:05

點贊
收藏

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