JavaScript貪吃蛇遊戲原始碼
阿新 • • 發佈:2019-02-20
蛇物件
屬性:方向、一組蛇節(div,div,div)、地圖、食物
方法:生成蛇,增加蛇頭,計算新蛇頭的位置,蛇移動
食物物件
屬性:橫向位置、縱向位置、div元素、地圖
方法:隨機位置
遊戲物件
屬性:蛇,食物
方法:開始
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv ="X-UA-Compatible" content="ie=edge">
<title>貪吃蛇</title>
<link rel="stylesheet" href="css/index.css">
</head>
<body>
<div id="map">
<!-- <div class="snake-body" style="left:60px;top:0"></div>
<div class="snake-body" style="left:80px;top:0"></div>
<div class="snake-head" style="left:100px;top:0"></div> -->
<!--
【生成蛇的規律】
生成蛇,其實本質上就是不斷的增加新蛇頭。
若沒有蛇頭,則建立一個新蛇頭,設定位置為 0,0
若有蛇頭,則先把原有的蛇頭變為身體,再新增新的蛇頭。並且控制新蛇頭的位置,在舊蛇頭的基礎上計算新蛇頭的位置(根據方向來計算)。
-->
<!--
【蛇移動的規律】
把蛇的最後一節取出來,變為蛇頭。
舊的蛇頭變為身體
把最後一節新增到最前面,設定新蛇頭的位置
-->
</div>
<!-- 在這裡壓縮的目的是減少檔案體積,合併的目的是減少請求次數。 這樣可以提高程式的網頁的訪問速度。 -->
<script src="js/all.js" ></script>
<!-- 使用食物物件 -->
<script>
// 獲取頁面上的地圖元素
var map = document.querySelector('#map');
// 建立了一個食物物件
// var food1 = new Food(map);
// // 食物隨機一下
// food1.randomLoaction();
var game = new Game(map);
game.start();
</script>
</body>
</html>
/* 地圖 */
#map {
position: relative;
margin: 0 auto;
width: 900px;
height: 600px;
background-color: #1f575c;
box-shadow: 0px 0px 50px 20px green;
}
/* 蛇頭、蛇身體、食物基本樣式 */
.snake-head,
.snake-body,
.food {
position: absolute;
width: 18px;
height: 18px;
border: dotted 1px black;
/* border-radius: 17px; */
}
/* 蛇的身體 */
.snake-body {
background: pink;
}
/* 蛇頭樣式 */
.snake-head {
background-color: red;
}
/* 食物 */
.food {
background-color: #00ff00;
}
all.js
function Food(m) {
this.x = 0;
this.y = 0;
this.div = document.createElement("div");
this.div.className = "food";
this.map = m;
this.map.appendChild(this.div)
}
Food.prototype.randomLoaction = function () {
var maxX = 900 / 20 - 1;
var maxY = 600 / 20 - 1;
var indexX = getIntNum(0, maxX);
var indexY = getIntNum(0, maxY);
this.x = indexX * 20;
this.y = indexY * 20;
this.div.style.left = this.x + "px";
this.div.style.top = this.y + "px"
};
function getIntNum(min, max) {
var num = parseInt(Math.random() * (max - min + 1) + min);
return num
};
function Snake(m, f) {
this.direction = "right";
this.bodys = [];
this.map = m;
this.food = f;
this.createBodys()
}
Snake.prototype.createBodys = function () {
for (var i = 0; i < 3; i++) {
this.insertNewHead()
}
};
Snake.prototype.insertNewHead = function () {
var newHead = document.createElement("div");
newHead.className = "snake-head";
var location = this.getNewHeadLoaction();
newHead.style.left = location.left + "px";
newHead.style.top = location.top + "px";
this.map.appendChild(newHead);
var oldHead = this.bodys[0];
if (oldHead != undefined) {
oldHead.className = "snake-body"
}
this.bodys.unshift(newHead)
};
Snake.prototype.getNewHeadLoaction = function () {
var x = 0;
y = 0;
var oldHead = this.bodys[0];
if (oldHead == undefined) {
return {left: x, top: y}
}
x = oldHead.offsetLeft;
y = oldHead.offsetTop;
switch (this.direction) {
case"left":
x = x - 20;
break;
case"right":
x = x + 20;
break;
case"bottom":
y = y + 20;
break;
case"top":
y = y - 20;
break
}
return {left: x, top: y}
};
Snake.prototype.move = function () {
var obj = this.getNewHeadLoaction();
if (obj.left < 0 || obj.left == 900 || obj.top < 0 || obj.top == 600) {
alert("想不開死了");
return true
}
var last = this.bodys.pop();
last.className = "snake-head";
var oldHead = this.bodys[0];
oldHead.className = "snake-body";
this.bodys.unshift(last);
last.style.left = obj.left + "px";
last.style.top = obj.top + "px";
if (obj.left == this.food.x && obj.top == this.food.y) {
this.insertNewHead();
this.food.randomLoaction()
}
return false
};
function Game(m) {
this.food = new Food(m);
this.snake = new Snake(m, this.food)
}
Game.prototype.start = function () {
this.food.randomLoaction();
var snake = this.snake;
var flag = window.setInterval(function () {
var isDead = snake.move();
console.log(isDead);
if (isDead) {
clearInterval(flag)
}
}, 100);
document.onkeydown = function (e) {
var code = e.keyCode;
switch (code) {
case 37:
if (snake.direction != "right") {
snake.direction = "left"
}
break;
case 38:
snake.direction = "top";
break;
case 39:
snake.direction = "right";
break;
case 40:
snake.direction = "bottom";
break
}
}
};
food.js
(function (w) {
// 形參w用來接收window物件,目的是為了縮短訪問window的時間,提高程度效能。
// 1. 定義一個食物的建構函式
function Food(m) {
// 食物的橫向位置
this.x = 0;
// 食物的縱向位置
this.y = 0;
// 建立一個div元素
this.div = document.createElement('div');
// 設定div的類名
this.div.className = 'food';
// 地圖屬性
this.map = m;
// 把div放進地圖中
this.map.appendChild(this.div);
}
// 2. 定義一個隨機食物的方法放入原型中
Food.prototype.randomLoaction = function () {
// this代表誰?看將來的呼叫者。 this→呼叫者。
// 將來橫向的最大索引
var maxX = 900 / 20 - 1;
// 將來縱向的最大索引
var maxY = 600 / 20 - 1;
// 隨機出橫向和縱向的位置索引
//[0,maxX]
var indexX = getIntNum(0, maxX);
//[0,maxY]
var indexY = getIntNum(0, maxY);
// 計算位置,這裡的x和y並不會直接影響div,而是保留下來為了將來和蛇頭的位置對比。
this.x = indexX * 20;
this.y = indexY * 20;
// 設定div的left和top值
this.div.style.left = this.x + 'px';
this.div.style.top = this.y + 'px';
};
// 獲取n-m之間的隨機數 [n,m]
function getIntNum(min, max) {
// (max-min + 1) + min
var num = parseInt(Math.random() * (max - min + 1) + min);
return num;
}
// 把Food放到window中,就可以暴露出去
// window是物件
w.Food = Food;
}(window));
game.js
(function (w) {
// 遊戲建構函式
function Game(m) {
// 遊戲中的食物
this.food = new Food(m);
// 遊戲中的蛇
this.snake = new Snake(m, this.food);
}
// 開始方法
Game.prototype.start = function () {
//0. 隨機一下食物
this.food.randomLoaction();
// this → game
var snake = this.snake;
// 1. 開啟定時器,讓蛇不斷的移動
var flag = window.setInterval(function () {
// this代表window
// 2. 呼叫蛇的move方法
var isDead = snake.move();
console.log(isDead);
// 判斷是否死了
if (isDead) {
clearInterval(flag);
}
}, 100);
//2. 給文件註冊鍵盤按下事件
document.onkeydown = function (e) {
// 獲取鍵碼值
var code = e.keyCode;
// 判斷四種情況,更改蛇的方向,先判斷蛇的移動方向
switch (code) {
case 37: // 左側
if (snake.direction != 'right') {
snake.direction = 'left';
}
break;
case 38: // 上側
snake.direction = 'top';
break;
case 39: // 右側
snake.direction = 'right';
break;
case 40: // 下側
snake.direction = 'bottom';
break;
}
};
};
//通過window將Game暴露出去
w.Game = Game;
}(window));
snake.js
(function (w) {
// 建構函式
function Snake(m, f) {
// 蛇移動的方向 left top right bottom
this.direction = 'right';
// 蛇的節數 蛇節中的第0個div是蛇頭 後面其他的都是蛇身
this.bodys = [];
// 蛇的要追加的地圖
this.map = m;
// 蛇要吃的食物
this.food = f;
// 生成蛇
this.createBodys();
}
// 生成蛇
Snake.prototype.createBodys = function () {
// 增加三個新蛇頭,初始化為3節
for (var i = 0; i < 3; i++) {
this.insertNewHead();
}
};
// 增加蛇頭
Snake.prototype.insertNewHead = function () {
// 建立一個div,表示新的蛇頭
var newHead = document.createElement('div');
// 設定類名
newHead.className = 'snake-head';
// 計算新蛇頭的位置
var location = this.getNewHeadLoaction();
// 把計算好的位置設定給新蛇頭元素
newHead.style.left = location.left + 'px';
newHead.style.top = location.top + 'px';
// 把新蛇頭放入地圖中
this.map.appendChild(newHead);
// 獲取舊的蛇頭,看是否存在,若存在,把舊的蛇頭改為身體
var oldHead = this.bodys[0];
if (oldHead != undefined) {
oldHead.className = 'snake-body';
}
// 把新蛇節放到蛇的bodys中
this.bodys.unshift(newHead);
};
// 計算新蛇頭的位置,返回兩個資料
Snake.prototype.getNewHeadLoaction = function () {
// 定義兩個變數,分別表示計算後新蛇頭的位置
var x = 0; y = 0;
// 判斷是否有蛇頭
var oldHead = this.bodys[0];
// 若沒有蛇頭,將來返回 {left:0,top:0}
if (oldHead == undefined) {
return { left: x, top: y };
}
// 有蛇頭,則計算。 獲取原有蛇頭的位置
x = oldHead.offsetLeft;
y = oldHead.offsetTop;
// 根據蛇移動的方向計算
switch (this.direction) {
case 'left':
x = x - 20;
break;
case 'right':
x = x + 20;
break;
case 'bottom':
y = y + 20;
break;
case 'top':
y = y - 20;
break