貪吃蛇是一款非常經(jīng)典的小游戲,概念起源于1976年由美國一家街機(jī)游戲Blockade(參見下圖),后來經(jīng)過無數(shù)次迭代,在1998年,成為諾基亞手機(jī)預(yù)裝的小游戲,相信也能激起很多人的回憶。這次,我將在OpenHarmony操作系統(tǒng)基礎(chǔ)上通過JS來實(shí)現(xiàn)貪吃蛇。
最終,我必須承認(rèn),自己做的貪吃蛇,卻被自己菜哭了,自己寫的貪吃蛇自己都不會(huì)玩(ps:我曾經(jīng)可是在不會(huì)死亡的情況下完了好長時(shí)間>_<)。實(shí)現(xiàn)的效果如下:
要有個(gè)游戲的容器空間設(shè)計(jì) 定義蛇的身體
要隨機(jī)生成食物
要人工控制蛇的移動(dòng)
吃掉食物身體變長
撞到障礙物(包括自身)會(huì)死亡,游戲重啟或結(jié)束
下面就針對以上情況來分別描述。
參數(shù)屬性:
名稱 | 類型 | 備注 |
result | number | 分?jǐn)?shù) |
conW | number | 容器寬度 |
conH | number | 容器高度 |
snakeBody | number | 蛇身體單位 |
h | number | 網(wǎng)格的y長度 |
w | number | 網(wǎng)格的x長度 |
grid | Array | 網(wǎng)格地圖 |
food | object | 食物 |
timeId | number | 定時(shí)器id |
level | number | 游戲難度級(jí)別 |
des | Object | 蛇的四個(gè)方向 |
isStart | Boolean | 判斷是否開始 |
snake | Object | 蛇 |
currDes | object | 當(dāng)前蛇前進(jìn)的方向 |
isEndP | Boolean | 判斷游戲是否結(jié) |
函數(shù)咯列表:
名稱 | 參數(shù) | 備注 |
init | 無 | 初始化函數(shù) |
onShow | 無 | 框架生命周期鉤子函數(shù) |
isEnd | newHead : object | 判斷游戲是否結(jié)束 |
setIsEnd | 無 | 設(shè)置游戲結(jié)束相關(guān)數(shù)據(jù) |
randomFood | 無 | 隨機(jī)生成食物 |
addHead | des : object | 增加新頭 |
move | des : object | 蛇的移動(dòng) |
intervalMove | d :object | 蛇自動(dòng)移動(dòng) |
isCuurDes | value:object ,x1:string,x2:string | 定時(shí)器id |
clickBut | m:object | 操作蛇的移動(dòng)的點(diǎn)擊事件 |
reInit | 無 | 重新開始游戲 |
在onShow鉤子函數(shù)那里獲取到游戲容器的寬高,其實(shí)我是不想在這里獲取的,但沒辦法,好像getBoundingClientRect()需要掛載后才能拿到值,在這之前的鉤子函數(shù)中都拿不到具體的屬性值。
拿到容器寬高后,根據(jù)蛇的身體長度(就是每個(gè)小圓點(diǎn))來確定要?jiǎng)澐侄嗌賯€(gè)格子,形成一個(gè)坐標(biāo)軸,后面食物,蛇的移動(dòng)都根據(jù)這坐標(biāo)軸來確定。
onShow(){ // 第一次初始化
this.conH = this.$refs["con"].getBoundingClientRect().height ;
this.conW = this.$refs["con"].getBoundingClientRect().width ;
this.h = Math.floor(this.conH / this.snakeBody);
this.w = Math.floor(this.conW / this.snakeBody);
for (var i = 0; i < this.w; i++) { //繪制網(wǎng)格
this.grid.push([])
for (var j = 0; j < this.h; j++) {
this.grid[i].push({
x: i,
y: j
});
}
}
this.init(); //初始化函數(shù)
}
用一個(gè)數(shù)組實(shí)現(xiàn),數(shù)組索引0為蛇的尾巴,索引length-1為頭。
init(){
const snakePos = [ //蛇的初始化的身體
{
x : 0,
y : 0,
flag : 'b',
id : Math.random()
},
{
x : 1,
y : 0,
flag : 'b',
id : Math.random()
},
{
x : 2,
y : 0,
flag : 'h',
id : Math.random()
}
];
this.snake.snakePos = snakePos; //把初始化的身體賦給蛇
this.randomFood(); //隨機(jī)生成食物
}
食物隨機(jī)生成,位置在網(wǎng)格中任意位置,但不能生成在蛇的身體位置中。
randomFood(){ //隨機(jī)生成食物
while(true){
let x = Math.floor(Math.random() * this.conW);
let y = Math.floor(Math.random() * this.conH);
x = x - (x % this.snakeBody); //x,y化為和蛇身體倍數(shù)的坐標(biāo)
y = y - (y % this.snakeBody);
let is = this.snake.snakePos.find((item)=>{
return item.x == x && item.y == y;
})
this.food.x = x;
this.food.y = y;
if(!is) { //當(dāng)食物的位置不為蛇不和蛇的位置重疊就跳出結(jié)束死循環(huán)
break;
}
}
}
蛇的移動(dòng)是通過對數(shù)組的push和shift實(shí)現(xiàn),蛇有移動(dòng)的方向,根據(jù)方向來修改新增蛇頭的x和y的值。移動(dòng)圖如下:
des:{//蛇的方向
"-20":{ // 向上移動(dòng)一位
x:0,
y:-1,
flag: ''
},
"20":{//向下
x:0,
y:1,
flag: ''
},
"10":{ //右
x:1,
y:0,
flag: ''
},
"-10":{ //左
x:-1,
y:0,
flag: ''
}
},
addHead(des){
//添加蛇頭 des為蛇的方向,一共有四個(gè)方向上下左右,每次移動(dòng)是都會(huì)傳一個(gè)方向過來
const oHead = this.snake.snakePos[this.snake.snakePos.length -1];
const newHead ={
x : oHead.x + des.x,
y : oHead.y + des.y,
flag : 'h',
id : Math.random()
}
this.isEnd(newHead);
this.snake.snakePos.push(newHead);
oHead.flag = 'b';
},
move(des){ // 蛇移動(dòng)時(shí),原頭變身體,原尾巴去掉,也就是push一個(gè)頭,shift一個(gè)尾巴
this.addHead(des);
this.snake.snakePos.shift();
},
當(dāng)蛇頭的x >= 地圖的x最大值 || x < 0 || 蛇頭的Y >= 地圖的Y最大值 || Y < 0 || 蛇頭的(x,y) == 蛇身體任意一個(gè) (x,y)。
isEnd(newHead){//判定蛇是是否死亡
if(newHead.x >= this.w || newHead.x < 0 || newHead.y >= this.h || newHead.y < 0){
this.setIsEnd();
}
let is = this.snake.snakePos.find((item)=>{ //循環(huán)查詢是否撞到自己
return item.x == newHead.x && item.y == newHead.y;
})
if(is){
this.setIsEnd(); //結(jié)束游戲
}
},
setIsEnd(){
clearInterval(this.timeId); //清除蛇的移動(dòng)定時(shí)器
this.isEndP = true; //這個(gè)屬性是用來是否顯示游戲結(jié)果界面
}
-20,20,10,-10,原本是一開用來判定是否當(dāng)前移動(dòng)的方向是否和原來的方向沖突,后來發(fā)現(xiàn)還是用坐標(biāo)軸香,也就懶得改了。
intervalMove(d){ // 自動(dòng)跑
if(!this.isStart) return;//判定是否開始
clearInterval(this.timeId); //清除以前的定時(shí)時(shí)器
this.timeId = setInterval(()=>{
const head = this.snake.snakePos[this.snake.snakePos.length - 1];
this.move(d);
if(this.snakeBody * head.x == this.food.x && this.food.y == this.snakeBody * head.y ){ //蛇吃到食物
this.addHead(d); //新增蛇頭,這個(gè)不去除尾巴
this.randomFood(); //再次重新生成食物
this.result++; //分?jǐn)?shù)
}
},1000/this.level); //this.level級(jí)別,決定蛇移動(dòng)的速度
},
isCuurDes(value = '',x1,x2){
// 判斷當(dāng)前蛇的方向,x1 為新方向,x2為以前的方向,主要是判斷點(diǎn)擊的按鈕是否左右,上下沖突
if((+x1 + +x2) == 0 ) return false; //這里+x1,+x2 是用來把字符串轉(zhuǎn)成數(shù)字
if(this.isEndP) return;//當(dāng)游戲結(jié)束無法再修改方向
this.currDes = value; //存下方向
return true;
},
clickBut(m){// 點(diǎn)擊按鈕
const value = m.target.dataSet.value;
switch(value){
case "-20":{ //上
//判斷方向是否相反,如果相反則不切換方向
this.isCuurDes(this.des[value],this.des[value].y,this.currDes.y)
&& this.intervalMove(this.des[value]);
break;
}
case "20":{// 下
this.isCuurDes(this.des[value],this.des[value].y,this.currDes.y)
&& this.intervalMove(this.des[value]);
break;
}
case "-10":{ //左
this.isCuurDes(this.des[value],this.des[value].x,this.currDes.x)
&& this.intervalMove(this.des[value]);
break;
}
case "10":{ // 右
this.isCuurDes(this.des[value],this.des[value].x,this.currDes.x)
&& this.intervalMove(this.des[value]);
break;
}
case "1": { //開始或暫停
if(this.isEndP) return
this.isStart = !this.isStart;
if(this.isStart && !this.isEndP){
this.intervalMove(this.currDes);
}else{
clearInterval(this.timeId);
}
break;
}
}
}
![](https://file1.elecfans.com//web2/M00/98/1F/wKgZomTnS8qAcX02AAAFsrxz3WU428.gif)
![]() |
![](https://file1.elecfans.com//web2/M00/98/1F/wKgZomTnS8uAO2OtAAPARPYvRao315.png)
![](https://file1.elecfans.com//web2/M00/98/1F/wKgZomTnS8uAZseoAAY5QEfgqIk993.png)
![](https://file1.elecfans.com//web2/M00/98/1F/wKgZomTnS8uAbFG3AAFY0l8hkEc080.png)
原文標(biāo)題:玩嗨OpenHarmony:基于OpenHarmony的貪吃蛇小游戲
文章出處:【微信公眾號(hào):開源技術(shù)服務(wù)中心】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
-
開源技術(shù)
+關(guān)注
關(guān)注
0文章
389瀏覽量
7991 -
OpenHarmony
+關(guān)注
關(guān)注
25文章
3744瀏覽量
16578
原文標(biāo)題:玩嗨OpenHarmony:基于OpenHarmony的貪吃蛇小游戲
文章出處:【微信號(hào):開源技術(shù)服務(wù)中心,微信公眾號(hào):共熵服務(wù)中心】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評(píng)論請先 登錄
相關(guān)推薦
OpenHarmony程序分析框架論文入選ICSE 2025
![<b class='flag-5'>OpenHarmony</b>程序分析框架論文入選ICSE 2025](https://file1.elecfans.com/web3/M00/04/96/wKgZO2d2KGCAUcJVAAAk9btwCMQ998.png)
FPGA打磚塊小游戲設(shè)計(jì)思路
50萬獎(jiǎng)金池!開放原子大賽——第二屆OpenHarmony創(chuàng)新應(yīng)用挑戰(zhàn)賽正式啟動(dòng)
第三屆OpenHarmony技術(shù)大會(huì)星光璀璨、致謝OpenHarmony社區(qū)貢獻(xiàn)者
第三屆OpenHarmony技術(shù)大會(huì) “OpenHarmony開發(fā)者激勵(lì)計(jì)劃”授牌儀式圓滿舉行
![第三屆<b class='flag-5'>OpenHarmony</b>技術(shù)大會(huì) “<b class='flag-5'>OpenHarmony</b>開發(fā)者激勵(lì)計(jì)劃”授牌儀式圓滿舉行](https://file1.elecfans.com/web1/M00/F3/55/wKgZoWcVzxCASN0LAAAYOsR_Kuo899.jpg)
OpenHarmony年度技術(shù)俱樂部、個(gè)人及活動(dòng)評(píng)選結(jié)果公示
基于ArkTS語言的OpenHarmony APP應(yīng)用開發(fā):HelloOpenharmony
![基于ArkTS語言的<b class='flag-5'>OpenHarmony</b> APP應(yīng)用開發(fā):Hello<b class='flag-5'>Openharmony</b>](https://file.elecfans.com/web2/M00/26/21/pYYBAGG5jjSALfrEAAAwAa9Oig8799.png)
河南大學(xué)OpenHarmony技術(shù)俱樂部正式揭牌成立
![河南大學(xué)<b class='flag-5'>OpenHarmony</b>技術(shù)俱樂部正式揭牌成立](https://file1.elecfans.com/web2/M00/06/04/wKgaombWxOqAQD0cAAAfRRDqwjM483.jpg)
openharmony移植AT32F407編譯時(shí)錯(cuò)誤
鴻蒙OpenHarmony【創(chuàng)建工程并獲取源碼】
![鴻蒙<b class='flag-5'>OpenHarmony</b>【創(chuàng)建工程并獲取源碼】](https://file1.elecfans.com/web2/M00/C9/99/wKgaomYeL0WAZFDHAAACSiKnE8w930.jpg)
OpenHarmony南向開發(fā)實(shí)例:【游戲手柄】
![<b class='flag-5'>OpenHarmony</b>南向開發(fā)實(shí)例:【<b class='flag-5'>游戲</b>手柄】](https://file1.elecfans.com/web2/M00/C9/E0/wKgaomYeg_GAHETqALAXuJVZaow524.jpg)
OpenHarmony南向能力征集令
OpenAtom OpenHarmony 4.1 Release版本正式發(fā)布
OpenHarmony內(nèi)核編程實(shí)戰(zhàn)
![<b class='flag-5'>OpenHarmony</b>內(nèi)核編程實(shí)戰(zhàn)](https://file1.elecfans.com/web2/M00/8F/50/wKgZomTMciWAD54NAABOGP2pQZY452.png)
評(píng)論