HTML 5 + CSS 3 + JavaSript 實現貪喫蛇
參考代碼:經典貪喫蛇源碼(含註釋)
源代碼
<!DOCTYPE html>
<html>
<head>
<title>Retro Snake</title>
<link rel="icon" href="https://raw.githubusercontent.com/CourserLi/JavaScirpt-snake/master/head.ico" type="image/x-icon"/>
<style type="text/css">
body {background-image:url(https://raw.githubusercontent.com/CourserLi/JavaScirpt-snake/master/pic.jpg);background-size:100%;}
body {background-repeat:no-repeat;}
body {margin:100px;text-align:center;}
h1 {font-size:210%;}
h1 {font-family:Georgia,Serif;}
</style>
</head>
<body>
<!--設置id,寬400像素,高400像素,背景顏色設置爲灰色-->
<canvas id="canv" width="400" height="400" style="background-color:gray"></canvas>
</canvas>
<h1>Courser Li</h1>
<script>
//聲明變量
//設置canvas畫布的繪圖的環境,當前唯一支持的參數是2d
var box=document.getElementById('canv').getContext('2d'); //用於繪製矩形的變量
//聲明一個變量表示蛇
var snake;
//聲明鍵盤事件的變量,1表示向右,-1向左,20向下,-20向上
var direction;
//聲明蛇頭
var n;
//聲明食物變量
var food;
//聲明速度初始變量
speed=100;
//繪製地圖
function draw(point,color)
{
//fillStyle()方法爲設置用於填充繪畫的顏色
box.fillStyle=color;
//fillRect()方法用於繪製“被填充”的矩形
box.fillRect(point%20*20+1,~~(point/20)*20+1,18,18); //行 列 長 寬(長寬不能大於20,因爲要在矩形直接留間隙)
}
//各種變量初始化,背景初始化
function ready()
{
//循環繪製地圖塊
for(var i=0;i<400;i++)
draw(i,"#313131");
//對蛇和食物進行靜態賦值並繪製到地圖上
snake=[66,65,64];
direction=1; //起始方向向右
food=344;
draw(food,"yellow");
draw(66,"#00b7ee");
draw(65,"#00b7ee");
draw(64,"#00b7ee");
}
//自動運行函數
(function(){ready();}());
//核心算法
function run()
{
//在遊戲開始以後“開始遊戲”按鈕變爲不可點擊狀態
document.getElementById("butn").setAttribute("disabled",true);
//用unshift()方法向數組的開頭添加一個新元素,新元素爲蛇下一步所移動的座標
snake.unshift(n=snake[0]+direction);
//邊界判斷,如果蛇頭碰到上下左右四個邊或者碰到自己的身子
//遊戲結束,初始化遊戲,將“開始遊戲”按鈕設置爲可以點擊,點擊開始按鈕可以重新進行遊戲
if(snake.indexOf(n,1)>0||n<0||n>399||(direction==-1&&n%20==19)||(direction==1&&n%20==0))
{
ready();
document.getElementById("butn").removeAttribute("disabled");
return alert("遊戲結束");
}
//如果蛇頭沒有碰到邊界或蛇身,在地圖上繪製蛇頭
draw(n,"#00b7ee");
//如果蛇頭喫到了食物(座標相同)
if(n==food)
{
//隨機在地圖上產生一個新食物,新事物不能於蛇身子重合
//Math.random()是令系統隨機選取大於等於 0.0 且小於 1.0 的僞隨機 double 值
while(snake.indexOf(food=~~(Math.random()*400))>=0);
//繪製食物
draw(food,"yellow");
}
//如果蛇頭沒有喫到食物
else
{
//將蛇尾元素刪除並且根據刪除的座標繪製爲地圖塊的顏色
draw(snake.pop(),"#313131");
}
//每100毫秒重複執行一次該函數
setTimeout(arguments.callee,speed);
}
//添加鍵盤事件
document.onkeydown=function(e)
{
//如果蛇當前橫着走,當鍵盤輸入up時,將蛇頭方向改爲向上,輸入down時將蛇頭方向改爲向下
if((direction==1||direction==-1)&&(snake[0]-snake[1]==1||snake[0]-snake[1]==-1))
{
if(e.keyCode==38) //上
direction=-20;
if(e.keyCode==40) //下
direction=20;
}
//如果蛇當前豎着走,當鍵盤輸入left時向左,right時向右
if((direction==20||direction==-20)&&(snake[0]-snake[1]==20||snake[0]-snake[1]==-20))
{
if(e.keyCode==39) //右
direction=1;
if(e.keyCode==37) //左
direction=-1;
}
}
</script>
<div>
<button id="butn" type="button" onclick="run()">開始遊戲</button>
</div>
</body>
</html>
相關屬性與方法
<canvas id="canvas" width="300" height="300" style="background-color:write">
var box=document.getElementById('canv').getContext('2d'); //兩種方法寫在一起
box.fillStyle = 'green'; //繪製矩形的顏色
box.fillRect(10, 10, 150, 100); //描繪矩形的位置及大小
canvas 元素
直接在 html 標籤中設置 width 和 height 屬性並使用 JavaScript 來指定畫布背景爲白色
.getElementById()
方法
獲取 < canvas > 標籤的引用
.getContext()
方法
渲染圖像(目前只有 2d)
fillStyle
屬性
讓長方形變成綠色
.fillRect()
方法
將它的左上角放在(10, 10),把它的大小設置成寬150高100
補充
JavaScript中 ~~ 的使用方法
~~ 代表雙非按位取反運算符
對於正數,它向下取整;對於負數,向上取整;對於非數字,取值爲 0
~~0; // => 0
~~null; // => 0
~~{}; // => 0
~~false; // => 0
~~true; // => 1
~~1.9; // => 1
~~-1.9; // => -1
JavaScript中 .indexOf
方法
返回 某個指定的字符串值在字符串中首次出現的位置 或 元素在列表中首次出現的位置,若找不到則返回 -1
var str="Hello world!"
document.write(str.indexOf("Hello") + "<br/>")
document.write(str.indexOf("World") + "<br/>")
document.write(str.indexOf("world"))
output:
0
-1
6
解決bug
問題: 若 run 函數一輪循環接收多個鍵位會導致遊戲強制結束
解決方法: 調整鍵盤事件僅當 snake 數組前兩個元素相鄰時(矩形緊挨時)才能執行,而只有 run 函數結束上一輪循環時,snake 數組纔開始接收鍵位,也就是一輪循環,只能接收一個鍵位
原:
if(direction==1||direction==-1)
if(direction==20||direction==-20)
改:
if((direction==1||direction==-1)&&(snake[0]-snake[1]==1||snake[0]-snake[1]==-1))
if((direction==20||direction==-20)&&(snake[0]-snake[1]==20||snake[0]-snake[1]==-20))
原本我還想加入一些有趣的玩法,奈何實力不足,我想等我有能力了再重新加入這些玩法,想加入的玩法如下:
- 隨着時間貪喫蛇的速度會減少,但吃了一個食物速度會增加 一點,相當於競速模式,獲勝的條件即速度到達某個值 或 長度大於某個值(這個我本可以實現,但無法具體在網頁上顯示具體數值就,所以還是不加了)
- 添加暫停按鈕(最好加個快捷鍵)
- 失敗與勝利的彈出窗口改變樣式
- 貪喫蛇初始位置隨機(本代碼是靜態生成,但食物是動態生成的)
- 顏色隨着位置的改變而改變(七彩蛇)