效果:
代碼:
index.html:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>貪吃蛇</title>
<link rel="stylesheet" type="text/css" href="index.css">
</head>
<body>
<div class="wrapper">
<div class="score"></div>
<div class="content">
<div class="over">
<p>Game Over</p>
<p class="overScore"></p>
</div>
<div class="start btn">開始遊戲</div>
<div class="continue btn">繼續遊戲</div>
<div class="box"></div>
</div>
</div>
<script type="text/javascript" src="index.js"></script>
</body>
</html>
index.css:
*{
margin: 0;
padding: 0;
}
.wrapper{
width: 550px;
height: 590px;
border: 1px solid #777;
margin: 30px auto;
}
.score{
width: 550px;
height: 39px;
background-color: #bbb;
border-bottom: 1px solid #777;
font: bold 20px/40px serif;
color: #444;
text-align: center;
}
.content{
width: 550px;
height: 550px;
background-color: #ddd;
position: absolute;
}
.box{
width: 550px;
height: 550px;
}
.over{
width: 300px;
height: 100px;
font: bold 45px/70px serif;
color: #555;
text-align: center;
margin: 50px auto;
display: none;
position: absolute;
left: 125px;
}
.overScore{
font-size: 30px;
}
.btn{
width: 300px;
height: 70px;
background-color: #eee;
border: 2px solid #777;
font: bold 40px/70px serif;
text-align: center;
color: #444;
cursor: pointer;
position: absolute;
left: 123px;
top: 238px;
}
.continue{
display: none;
z-index: 1;
}
.snake{
width: 8px;
height: 8px;
background-color: #fff;
border: 1px solid #777;
position: absolute;
}
.eyes{
width: 2px;
height: 2px;
background-color: #777;
position: absolute;
}
.leftEyeUp{
left: 1px;
top: 3px;
}
.rightEyeUp{
left: 5px;
top: 3px;
}
.leftEyeLeft{
left: 3px;
top: 1px;
}
.rightEyeLeft{
left: 3px;
top: 5px;
}
.food{
width: 8px;
height: 8px;
background-color: #fff;
border: 1px solid #333;
border-radius: 50%;
position: absolute;
}
index.js:
var snake = null, // snake的實例
food = null, // food的實例
game = null; // game的實例
var score = document.getElementsByClassName("score")[0];
var over = document.getElementsByClassName("over")[0];
var overScore = document.getElementsByClassName("overScore")[0];
// 開始遊戲
function startGame() {
startBtn.style.display = "none";
over.style.display = "none";
game = new Game();
game.init();
}
// start點擊事件(開始遊戲)
var startBtn = document.getElementsByClassName("start")[0];
startBtn.onclick = function (e) {
// e.stopPropagation(); // 取消冒泡
startGame();
}
// box點擊事件(暫停遊戲)
var box = document.getElementsByClassName("box")[0];
box.onclick = function () {
if (game.state === "start") {
game.pause();
}
}
// continue點擊事件(繼續遊戲)
var continueBtn = document.getElementsByClassName("continue")[0];
continueBtn.onclick = function (e) {
// e.stopPropagation(); // 取消冒泡
game.start();
}
// 鍵盤事件
document.onkeydown = function (e) {
if (e.which === 32) { // 空格
if (!game || game.state === "ready") {
startGame();
} else if (game.state === "start") {
game.pause();
} else if (game.state === "pause") {
game.start();
}
} else if (game.key) {
if (e.which === 38 && snake.direction !== snake.dirSet.down) { // 上
snake.direction = snake.dirSet.up;
game.key = false;
} else if (e.which === 40 && snake.direction !== snake.dirSet.up) { // 下
snake.direction = snake.dirSet.down;
game.key = false;
} else if (e.which === 37 && snake.direction !== snake.dirSet.right) { // 左
snake.direction = snake.dirSet.left;
game.key = false;
} else if (e.which === 39 && snake.direction !== snake.dirSet.left) { // 右
snake.direction = snake.dirSet.right;
game.key = false;
}
}
}
function Square(pos, className) {
this.x = pos[0]; // x座標(left)
this.y = pos[1]; // y座標(top)
this.className = className; // 類名
this.ele = document.createElement("div"); // Element
}
Square.prototype.create = function () {
this.ele.className = this.className;
this.ele.style.left = this.x + "px";
this.ele.style.top = this.y + "px";
box.appendChild(this.ele); // 放入box
}
function Snake() {
this.head = null; // 蛇頭
this.tail = null; // 蛇尾
this.eyes = []; // 眼睛
this.bodyPos = []; // 身體所佔位置
this.nextPos = []; // 蛇頭下一個點
direction = {}; // 方向
this.dirSet = { // 方向集合
up: {
x: 0,
y: -10,
leClass: "eyes leftEyeUp",
reClass: "eyes rightEyeUp"
},
down: {
x: 0,
y: 10,
leClass: "eyes leftEyeUp",
reClass: "eyes rightEyeUp"
},
left: {
x: -10,
y: 0,
leClass: "eyes leftEyeLeft",
reClass: "eyes rightEyeLeft"
},
right: {
x: 10,
y: 0,
leClass: "eyes leftEyeLeft",
reClass: "eyes rightEyeLeft"
}
};
}
// 初始化
Snake.prototype.init = function () {
// 創建蛇身
var snakeBody = [];
for (var i = 0; i < 5; i++) {
snakeBody[i] = new Square([270, 250 + i * 10], "snake");
this.bodyPos.push([270, 250 + i * 10]); // 更新蛇身所佔位置
snakeBody[i].create();
}
this.head = snakeBody[0]; // 更新蛇頭信息
this.tail = snakeBody[4]; // 更新蛇尾信息
// 形成鏈表關係
for (var i = 0; i < 5; i++) {
snakeBody[i].last = snakeBody[i - 1];
snakeBody[i].next = snakeBody[i + 1];
}
this.direction = this.dirSet.up;
// 創建眼睛
this.eyes[0] = document.createElement("i");
this.eyes[1] = document.createElement("i");
this.setEyesPos();
this.setEyes();
}
// 把眼睛放入蛇頭
Snake.prototype.setEyes = function () {
this.head.ele.appendChild(this.eyes[0]);
this.head.ele.appendChild(this.eyes[1]);
}
// 改變眼睛class
Snake.prototype.setEyesPos = function () {
this.eyes[0].className = this.direction.leClass;
this.eyes[1].className = this.direction.reClass;
}
// 是否與蛇身重複
Snake.prototype.isRepeat = function (pos) {
var len = this.bodyPos.length;
for (var i = 0; i < len; i++) {
if (pos[0] === this.bodyPos[i][0] && pos[1] === this.bodyPos[i][1]) {
return true;
}
}
return false;
}
// 獲得蛇頭下一個位置座標
Snake.prototype.getnextPos = function () {
this.nextPos[0] = this.head.x + this.direction.x;
this.nextPos[1] = this.head.y + this.direction.y;
}
// 移動
Snake.prototype.move = function () {
this.getnextPos();
if (this.isRepeat(this.nextPos) || this.nextPos[0] < 0 || this.nextPos[0] > 540 || this.nextPos[1] < 0 || this.nextPos[1] > 540) { // 撞到自己或撞牆
this.method.over.call(this);
} else if (this.nextPos[0] === game.food.x && this.nextPos[1] === game.food.y) { // 吃到食物
this.method.food.call(this);
} else {
this.method.go.call(this);
}
}
// 方法
Snake.prototype.method = {
// 向前走一格
go: function () {
// 更新蛇尾座標
this.tail.x = this.head.x;
this.tail.y = this.head.y;
// 把蛇尾放到蛇頭的位置
this.tail.ele.style.left = this.tail.x + "px";
this.tail.ele.style.top = this.tail.y + "px";
// 更新蛇頭座標
this.head.x = this.nextPos[0];
this.head.y = this.nextPos[1];
// 蛇頭前移一格
this.head.ele.style.left = this.head.x + "px";
this.head.ele.style.top = this.head.y + "px";
// 更新蛇身所佔位置座標
this.bodyPos.pop();
this.bodyPos.unshift([this.nextPos[0], this.nextPos[1]]);
// 更新鏈表關係
this.tail.last.next = null;
this.head.next.last = this.tail;
this.tail.next = this.head.next;
this.head.next = this.tail;
this.tail = this.tail.last;
this.head.next.last = this.head;
},
// 吃食物
food: function () {
// 分數+1
game.score++;
game.setScore();
game.changeFoodPos();
// 創建新蛇頭
var snakeHead = new Square(this.nextPos, "snake");
snakeHead.create();
// 更新蛇身所佔位置座標
this.bodyPos.unshift([this.nextPos[0], this.nextPos[1]]);
// 更新鏈表關係
this.head.last = snakeHead;
snakeHead.next = this.head;
snakeHead.last = null;
// 更新蛇頭信息
this.head = snakeHead;
this.setEyes();
},
// over
over: function () {
game.over();
}
}
function Game() {
this.timer = null; // 定時器
this.score = 0; // 分數
this.food = {}; // 食物
this.key = true; // 鎖
this.state = "ready"; // 遊戲狀態(未開始:ready,進行中:start,暫停:pause)
}
// 初始化
Game.prototype.init = function () {
snake = new Snake();
snake.init();
this.createFood();
this.setScore();
this.start();
}
// 開始遊戲
Game.prototype.start = function () {
this.state = "start";
continueBtn.style.display = "none";
// 啓動定時器
this.timer = setInterval(function () {
snake.move();
if (!game.key) {
snake.setEyesPos();
game.key = true;
}
}, 200);
}
// 暫停遊戲
Game.prototype.pause = function () {
this.state = "pause";
clearInterval(this.timer);
continueBtn.style.display = "block";
}
// 遊戲結束
Game.prototype.over = function () {
this.state = "ready";
clearInterval(this.timer);
overScore.innerText = "分數:" + this.score;
score.innerText = "";
over.style.display = "block";
startBtn.style.display = "block";
box.innerHTML = "";
}
// 設置分數
Game.prototype.setScore = function () {
score.innerText = "分數:" + this.score;
}
// 創建食物
Game.prototype.createFood = function () {
this.getFoodPos();
this.food = new Square([this.food.x, this.food.y], "food");
this.food.create();
}
// 獲得食物座標
Game.prototype.getFoodPos = function () {
var pos = [];
do {
pos[0] = Math.floor(Math.random() * 55) * 10;
pos[1] = Math.floor(Math.random() * 55) * 10;
} while (snake.isRepeat(pos));
this.food.x = pos[0];
this.food.y = pos[1];
}
// 更改食物位置
Game.prototype.changeFoodPos = function () {
this.getFoodPos();
this.food.ele.style.left = this.food.x + "px";
this.food.ele.style.top = this.food.y + "px";
}