前端小遊戲
前端小遊戲——簡易貪吃蛇
-
概要: 使用前端基礎技術實現簡易版貪吃蛇,涉及到的技術點有:html、css、javascript、jQuery
-
要實現的功能: ①生成蛇移動的介面,這裡使用二維陣列(矩陣);②畫出蛇;③蛇可以自動移動,並根據鍵盤的上下左右改變方向;④隨機生成食物(食物不在蛇的身上產生);⑤吃食物,當蛇吃到食物時,蛇身變長,並且重新生成一個食物;⑥吃到食物後速度變快;⑦蛇死亡,分為兩種情況,一個是吃到自己,另一個是撞牆;⑧結束遊戲並重置畫面(蛇的位置)。
-
web介面:
-
html部分:
<div id="mainpanel" class="mainpanel"></div>
<div id="end" class="end">遊戲結束!</div>
<p>
<input id="starBtn" type="button" value="開始" />
<input id="endBtn" type="button" value="結束" />
得分:<span id= "point">0</span>
</p>
- css部分:
.mainpanel{
border: 1px solid black;
height: 400px;
width: 800px;
margin: 0px auto;
font-size: 1px;
}
.innerbg{
height: 18px;
width: 18px;
margin: 1px;
background-color: lightgray;
float: left;
}
.snake{
background-color: goldenrod;
}
.food{
background-color: lightgreen;
}
.end{
width: 200px;
height: 100px;
border: 5px solid darkgray;
background-color: #D3D3D3;
border-radius: 10px;
position: absolute;
top: 30%;
left: 50%;
margin-left: -100px;
display: none;
text-align: center;
line-height: 100px;
}
p{
text-align: center;
}
- JS部分:
定義全域性變數
//蛇橫縱座標
var snakeX = [4,5,6,7];
var snakeY = [4,4,4,4];
//初始蛇頭的位置
var snakeXHead = 7;
var snakeYHead = 4;
/*
蛇頭的初始朝向
37左
38上
39右
40下
*/
var direction = 39;
//食物的橫縱座標
var foodX;
var foodY;
var moveTime = 100; //蛇移動的初始速度
var score = 0; //分數
var startGame; //計時函式返回的物件名
var state = true; //判斷是否生成食物
var turn = true; //判斷是否繼續接受鍵盤的輸入
基礎陣列:
var basearr = new Array(40);
for(var i = 0;i<40;i++){
basearr[i] = new Array(20);
}
畫蛇:
function drawSnake(){
for(var i = 0;i<snakeX.length;i++){
if(snakeX[i]<=39&&snakeX[i]>=0&&snakeY[i]<=19&&snakeY[i]>=0){ //判斷是否超出畫面
basearr[snakeX[i]][snakeY[i]].addClass("snake");
}
}
}
清除蛇:
function clearSnake(){
for(var i = 0;i<snakeX.length;i++){
basearr[snakeX[i]][snakeY[i]].removeClass("snake");
}
}
蛇移動:
①每次畫蛇前,先清除原有的陣列;
②根據鍵盤的輸入判斷蛇頭的方向後移動;
③每次移動後用shift()函式清楚陣列中的第一個元素;
④其他功能函式。eat()–>吃食物;death()–>死亡;drawSnake()–>畫蛇
function snakeMove(){
clearSnake();
turn = true;
switch(direction){
case 39:snakeX.push(++snakeXHead);snakeY.push(snakeYHead);break;
case 37:snakeX.push(--snakeXHead);snakeY.push(snakeYHead);break;
case 38:snakeX.push(snakeXHead);snakeY.push(--snakeYHead);break;
case 40:snakeX.push(snakeXHead);snakeY.push(++snakeYHead);break;
}
snakeX.shift();
snakeY.shift();
eat();
death();
drawSnake();
}
食物出現:
①用random函式隨機生成食物的X、Y座標;
②遍歷迴圈蛇身陣列,判斷當隨機生成的食物在蛇身上時不生成食物,並繼續迴圈直到不在為止。
function foodShow(){
do{
foodX = Math.floor(Math.random()*39+0);
foodY = Math.floor(Math.random()*19+0);
state = false;
for(var i = 0;i<snakeX.length;i++){
if(snakeX[i]==foodX&&snakeY[i]==foodY){
console.log("在蛇身上出現!不生成!")
state = true;
}
}
}while(state)
basearr[foodX][foodY].addClass("food");
console.log("食物座標:"+foodX,foodY);
}
吃食物動作: 當蛇頭的XY座標與食物的XY座標一致時,吃到食物(碰撞事件)。
①分數+1;
②蛇速度變快,重置計時函式的時間,而後重新呼叫計時函式;
③移除當前食物,再次生成食物;
④使用unshift()函式給陣列的開頭新增一個新的元素並返回新的長度。
function eat(){
if(snakeXHead==foodX&&snakeYHead==foodY){
score += 1;
moveTime -= 2;
clearTimeout(startGame);
startGame = setInterval(snakeMove,moveTime);
$("#point").html(score);
console.log("蛇移動速度"+moveTime);
$(".food").removeClass('food');
foodShow();
snakeX.unshift(foodX);
snakeY.unshift(foodY);
}
}
死亡:
①當蛇頭的XY座標和自身XY座標重合時(吃到自己),呼叫clearInterval()函式停止計時函式,遊戲結束;
②當蛇頭的XY座標超過介面長度時(撞牆),呼叫clearInterval()函式停止計時函式,遊戲結束;
function death(){
for(var i =0;i<snakeX.length-1;i++){
if(snakeX[i] == snakeXHead && snakeY[i] == snakeYHead){
clearInterval(startGame);
$("#end").show();
console.log("吃到自己啦!")
}
if(snakeXHead>39 ||snakeXHead<0 || snakeYHead>19 || snakeYHead<0 ){
clearInterval(startGame);
$("#end").show();
console.log("出界啦!")
}
}
}
重置頁面:
function initGame(){
$("#mainpanel").html("");//防止疊加介面
//重置座標面板
for(var y = 0;y<20;y++){
for(var x = 0;x<40;x++){
var mycontent = $('<div class = "innerbg"></div>');
basearr[x][y] = mycontent;
$("#mainpanel").append(basearr[x][y]);
}
}
snakeX =[4,5,6,7];
snakeY =[4,4,4,4];
drawSnake();
snakeXHead = 7;
snakeYHead = 4;
direction = 39;
turn = true;
moveTime = 100;
}
- jQuery部分:
建立畫面: 40*20
for(var y = 0;y<20;y++){
for(var x = 0;x<40;x++){
var mycontent = $('<div class = "innerbg"></div>');
basearr[x][y] = mycontent;
$("#mainpanel").append(basearr[x][y]);
}
}
drawSnake();//建立初始蛇
通過鍵盤輸入改變蛇移動的方向:
①限定接受鍵盤輸入的範圍(37-40);
②Math.abs(direction-event.keyCode)!=2
用於判斷不能直接掉頭移動。例:當蛇頭右移動時不能接收←、當蛇頭向下移動時不能接收 ↑;
③turn作用:例如當蛇正在向下移動,此時快速按 → ↑,會導致蛇頭穿過自己(死亡),為了防止這種情況發生,加入一個布林變數turn,一次只接收一個按鍵的輸入,當蛇再次移動時將turn的值變更為true;
$(document).keyup(function(event){
if(turn&&event.keyCode<=40&&event.keyCode>=37&&Math.abs(direction-event.keyCode)!=2){
direction = event.keyCode;
turn = false;
}
})
開始按鈕繫結監聽事件:
①禁用開始按鈕,開啟結束按鈕;
②重置畫面
③開始計時函式,生成食物
$("#starBtn").click(function(){
$(this).prop("disabled",true);
$("#endBtn").prop("disabled",false);
initGame()
$("#end").hide();
startGame = setInterval(snakeMove,moveTime);
foodShow();
})
結束按鈕繫結監聽事件:
①結束計時函式
②清空分數
③禁用結束按鈕,開啟開始按鈕;
④移除畫面中的食物,展示結束彈窗;
$("#endBtn").click(function(){
clearInterval(startGame);
score = 0;
$("#point").html(score);
$(this).prop("disabled",true);
$("#starBtn").prop("disabled",false);
$(".food").removeClass('food');
$("#end").show();
})
總結: 一週的前端技術學習後實現的貪吃蛇小遊戲。總體思路容易理通,關鍵點在於處理每個動過時的邏輯需要更細緻,否則執行時就會出一些bug。
難點歸納:
①為了實現蛇的動態移動,需要考慮到每次增加元素後要及時刪除一個元素,才能實現動態移動。
②如何防止食物不在蛇身上出現?
首先要考慮到出現在蛇身上時的食物XY座標是與蛇的XY陣列座標相重合的,使用do while迴圈並遍歷蛇身陣列進行判斷,當重合時將while迴圈條件實現為true,直到不重合fasle跳出do while迴圈生成食物。
③吃食物時如何讓蛇變長?
這個動作的實現方法很多,我是直接使用unshift()函式增加元素,也可以進行判斷,當吃到食物時不用shift()刪除元素就可以。
④怎麼讓蛇每次吃到食物後速度變快?
在吃到食物時,先要停止當前的計時函式,而後再次呼叫setInterval()函式,並將時間設為變數,每次吃到食物後做減法。