1. 程式人生 > >JavaScript貪吃蛇遊戲原始碼

JavaScript貪吃蛇遊戲原始碼

蛇物件

屬性:方向、一組蛇節(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