最近在做一個貪吃蛇的項(xiàng)目忌警,這是我第一次用js來實(shí)現(xiàn)做一款游戲搁拙,雖然很low,但出現(xiàn)預(yù)想的效果時還是很開心的,雖然做出了效果但還是對其中的一些還不太熟練法绵,在后續(xù)我會將游戲開始脐帝,地圖構(gòu)建凿歼,食物出現(xiàn),蛇的出現(xiàn)分別寫入一個文件,這樣更便于理解阀坏。
我們先定義一個游戲引擎用來定義游戲的開始哪工、結(jié)束以及場景的布置赂弓。
用創(chuàng)建對象來定義一個游戲gGameBox其中有地圖的屬性涉枫,以及地圖的所有坐標(biāo)。
var gGameBox = {
rows: 20, // 行數(shù)
cols: 20, // 列數(shù)
allTds: [], // 存儲所有的td元素對象
food: null, // 食物對象
snake: null, // 蛇對象
.
.
.//(以下到場景布置都是)
}
清除蛇尾定義清除屬性clear狡赐,由于蛇的移動是將蛇節(jié)的坐標(biāo)加++窑业,所以蛇身會一直增加,要清除蛇的小尾巴枕屉。
clear: function(){
for(var i = 0; i< gGameBox.allTds.length;i++){
for(var j=0;j<gGameBox.allTds[i].length;j++){
gGameBox.allTds[i][j].className = "";
}
}
},
定義一個方法用來判斷按鍵常柄,可以由上下左右來控制蛇的移動。(注意蛇不能在往左走的同時往右走搀庶,同理其他一樣)
keyControl: function() {
// onkeydown 鍵盤按下事件
window.onkeydown = function(e) {
// 獲取按鍵編碼
var c = e.keyCode;
if (c == 37){
if (gGameBox.snake.direct == "right"){
// 當(dāng)前是往右走拐纱,不能掉頭,終止函數(shù)
return ;
}
gGameBox.snake.direct = "left";
}else if (c == 38){
if (gGameBox.snake.direct == "down"){
return ;
}
gGameBox.snake.direct = "up";
}else if (c == 39){
if (gGameBox.snake.direct == "left"){
return ;
}
gGameBox.snake.direct = "right";
}else if (c == 40){
if (gGameBox.snake.direct == "up"){
return ;
}
gGameBox.snake.direct = "down";
}
}
},
定義一個方法布置場景哥倔,創(chuàng)建食物秸架,創(chuàng)建蛇,分別調(diào)用了food.js文件咆蒿、snake.js文件东抹。用定時器來實(shí)現(xiàn)蛇的移動、先清除蛇尾沃测、判斷鍵盤按鍵來控制蛇的方向缭黔、調(diào)用蛇的移動方法、讓食物隨機(jī)出現(xiàn)蒂破。
start: function() {
gGameBox.init(); // 游戲初始化
this.food = new Food();// 創(chuàng)建食物
this.snake = new Snake(); // 創(chuàng)建蛇
this.timer=setInterval(function(){
gGameBox.clear();
gGameBox.keyControl();
gGameBox.snake.move();
gGameBox.food.show();
},200);
},
init為布置場景的方法馏谨,在js中創(chuàng)建表格然后加入頁面中。
// 初始化
init: function() {
// 場景布置好, 用表格來做
var oTable = document.createElement("table");
for (var i = 0; i < gGameBox.rows; i++)
{
// 創(chuàng)建tr
var oTr = document.createElement("tr");
// 每一行附迷,定義1個空數(shù)組
var arr = [];
for (var j = 0; j < gGameBox.cols; j++) {
// 創(chuàng)建td
var oTd = document.createElement("td");
oTr.appendChild(oTd);
// 將td放到空數(shù)組中
arr.push(oTd);
}
// 將當(dāng)前行所有的td惧互,壓入到 allTds 屬性中
gGameBox.allTds.push(arr);
oTable.appendChild(oTr);
}
// 添加到body
document.body.appendChild(oTable);
}
Food.js文件
我們用外接文件來寫貪吃蛇中的食物哎媚。
先給食物的屬性橫坐標(biāo)x,縱坐標(biāo)y,并讓食物一開始的坐標(biāo)就是隨機(jī)出現(xiàn)的(調(diào)用函數(shù)change())。
function Food() {
// 坐標(biāo)
this.x = 0;
this.y = 0;
// 一開始就隨機(jī)位置
this.change();
}
在食物的原型中加入食物的方法(show為食物出現(xiàn)在頁面中定義了食物的樣式喊儡,change為食物出現(xiàn)的位置為隨機(jī)的)拨与。
// 方法1: 出現(xiàn)在環(huán)境中
Food.prototype.show = function() {
gGameBox.allTds[this.y][this.x].className = "food";
}
// 方法2: 改變位置, 隨機(jī)的
Food.prototype.change = function() {
this.x = parseInt(Math.random() * gGameBox.cols);
this.y = parseInt(Math.random() * gGameBox.rows);
this.show();
}
snake.js文件
我們用外接文件來寫貪吃蛇中的蛇(注意蛇很有靈性需要特別小心)。
先定義了一個arr數(shù)組用來存放蛇節(jié)的坐標(biāo)艾猜。x其實(shí)為表格的列數(shù)买喧,y為表格的行數(shù)。
direct為讓蛇一開始便讓其往右邊移動匆赃。
fresh為讓蛇出現(xiàn)在地圖中淤毛。
function Snake(){
this.arr = [
{x: 5, y: 1},
{x: 4, y: 1},
{x: 3, y: 1},
{x: 2, y: 1},
{x: 1, y: 1},
];
this.direct = "right";
this.fresh();
}
在蛇的原型中加入讓蛇顯示的行為。
Snake.prototype.fresh = function(){
for(var i = 0; i<this.arr.length; i++){
var x = this.arr[i].x;
var y = this.arr[i].y;
gGameBox.allTds[y][x].className = "snake"
}
}
在蛇的原型中加入蛇的移動行為move炸庞,并判斷按鍵后改變蛇的移動方向钱床,給出判斷游戲結(jié)束(蛇死亡)的條件。給出判斷是否吃到食物的條件埠居,如果吃到就在蛇尾增加一節(jié)讓食物再隨機(jī)出現(xiàn)一個,更新蛇的位置事期。蛇的移動是通過在蛇頭加一個表格滥壕,蛇尾減去一個表格實(shí)現(xiàn)的unshift加一個蛇頭,pop刪除一個蛇尾然后更新蛇的位置兽泣。
Snake.prototype.move = function(){
var x=this.arr[0].x;
var y=this.arr[0].y;
if(this.direct == "right"){
x++;
}else if (this.direct =="down"){
y++;
}else if (this.direct == "left"){
x--;
}else if (this.direct =="up"){
y--;
}
//判斷蛇是否over
if(x >=gGameBox.cols|| y>=gGameBox.rows||x<0||y<0){
clearInterval(gGameBox.timer);
alert("GG");
return;
}
//判斷蛇是否吃到food
if(x == gGameBox.food.x && y==gGameBox.food.y){
this.arr.unshift({x:x,y:y});
gGameBox.food.change();
this.fresh();
return;
}
this.arr.unshift({x: x, y: y});
this.arr.pop();
this.fresh();
}