原生JS實現貪吃蛇(修改版)

效果:
在這裏插入圖片描述在這裏插入圖片描述在這裏插入圖片描述在這裏插入圖片描述
代碼:
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";
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章