1. 程式人生 > >javascript:用原生js模擬貪吃蛇遊戲練習

javascript:用原生js模擬貪吃蛇遊戲練習

本次練習所有的程式碼:可以直接複製全部然後執行看效果~

  1 <!DOCTYPE html>
  2 <html lang="en">
  3 <head>
  4   <meta charset="UTF-8">
  5   <title>title</title>
  6   <style>
  7     .map {
  8       width: 800px;
  9       height: 600px;
 10       background-color: #CCC;
 11       position
: relative; 12 } 13 </style> 14 </head> 15 <body> 16 <!--畫出地圖,設定樣式--> 17 <div class="map"></div> 18 <script> 19 20 21 //自呼叫函式----食物的 22 (function () { 23 var elements = [];//用來儲存每個小方塊食物的 24 //食物就是一個物件,有寬,有高,有顏色,有橫縱座標,先定義建構函式,然後建立物件 25
function Food(x, y, width, height, color) { 26 //橫縱座標 27 this.x = x || 0; 28 this.y = y || 0; 29 //寬和高 30 this.width = width || 20; 31 this.height = height || 20; 32 //背景顏色 33 this.color = color || "green"; 34 } 35 36 //為原型新增初始化的方法(作用:在頁面上顯示這個食物)
37 //因為食物要在地圖上顯示,所以,需要地圖的這個引數(map---就是頁面上的.class=map的這個div) 38 Food.prototype.init = function (map) { 39 //先刪除這個小食物 40 //外部無法訪問的函式 41 remove(); 42 43 //建立div 44 var div = document.createElement("div"); 45 //把div加到map中 46 map.appendChild(div); 47 //設定div的樣式 48 div.style.width = this.width + "px"; 49 div.style.height = this.height + "px"; 50 div.style.backgroundColor = this.color; 51 //先脫離文件流 52 div.style.position = "absolute"; 53 //隨機橫縱座標 54 this.x = parseInt(Math.random() * (map.offsetWidth / this.width)) * this.width; 55 this.y = parseInt(Math.random() * (map.offsetHeight / this.height)) * this.height; 56 div.style.left = this.x + "px"; 57 div.style.top = this.y + "px"; 58 59 //把div加入到陣列elements中 60 elements.push(div); 61 }; 62 63 //私有的函式---刪除食物的 64 function remove() { 65 //elements陣列中有這個食物 66 for (var i = 0; i < elements.length; i++) { 67 var ele = elements[i]; 68 //找到這個子元素的父級元素,然後刪除這個子元素 69 ele.parentNode.removeChild(ele); 70 //再次把elements中的這個子元素也要刪除 71 elements.splice(i, 1); 72 } 73 } 74 75 //把Food暴露給Window,外部可以使用 76 window.Food = Food; 77 }()); 78 79 //自呼叫函式---小蛇 80 (function () { 81 var elements = [];//存放小蛇的每個身體部分 82 //小蛇的建構函式 83 function Snake(width, height, direction) { 84 //小蛇的每個部分的寬 85 this.width = width || 20; 86 this.height = height || 20; 87 //小蛇的身體 88 this.body = [ 89 {x: 3, y: 2, color: "red"},// 90 {x: 2, y: 2, color: "orange"},//身體 91 {x: 1, y: 2, color: "orange"}//身體 92 ]; 93 //方向 94 this.direction = direction || "right"; 95 } 96 97 //為原型新增方法--小蛇初始化的方法 98 Snake.prototype.init = function (map) { 99 //先刪除之前的小蛇 100 remove();//=========================================== 101 102 //迴圈遍歷建立div 103 for (var i = 0; i < this.body.length; i++) { 104 //陣列中的每個陣列元素都是一個物件 105 var obj = this.body[i]; 106 //建立div 107 var div = document.createElement("div"); 108 //把div加入到map地圖中 109 map.appendChild(div); 110 //設定div的樣式 111 div.style.position = "absolute"; 112 div.style.width = this.width + "px"; 113 div.style.height = this.height + "px"; 114 //橫縱座標 115 div.style.left = obj.x * this.width + "px"; 116 div.style.top = obj.y * this.height + "px"; 117 //背景顏色 118 div.style.backgroundColor = obj.color; 119 //方向暫時不定 120 //把div加入到elements陣列中----目的是為了刪除 121 elements.push(div); 122 } 123 }; 124 125 //為原型新增方法---小蛇動起來 126 Snake.prototype.move = function (food, map) { 127 //改變小蛇的身體的座標位置 128 var i = this.body.length - 1;//2 129 for (; i > 0; i--) { 130 this.body[i].x = this.body[i - 1].x; 131 this.body[i].y = this.body[i - 1].y; 132 } 133 //判斷方向---改變小蛇的頭的座標位置 134 switch (this.direction) { 135 case "right": 136 this.body[0].x += 1; 137 break; 138 case "left": 139 this.body[0].x -= 1; 140 break; 141 case "top": 142 this.body[0].y -= 1; 143 break; 144 case "bottom": 145 this.body[0].y += 1; 146 break; 147 } 148 149 //判斷有沒有吃到食物 150 //小蛇的頭的座標和食物的座標一致 151 var headX=this.body[0].x*this.width; 152 var headY=this.body[0].y*this.height; 153 //判斷小蛇的頭的座標和食物的座標是否相同 154 if(headX==food.x&&headY==food.y){ 155 //獲取小蛇的最後-的尾巴 156 var last=this.body[this.body.length-1]; 157 //把最後的蛇尾複製一個,重新的加入到小蛇的body中 158 this.body.push({ 159 x:last.x, 160 y:last.y, 161 color:last.color 162 }); 163 //把食物刪除,重新初始化食物 164 food.init(map); 165 } 166 }; 167 168 //刪除小蛇的私有的函式============================================================================= 169 function remove() { 170 //刪除map中的小蛇的每個div,同時刪除elements陣列中的每個元素,從蛇尾向蛇頭方向刪除div 171 var i = elements.length - 1; 172 for (; i >= 0; i--) { 173 //先從當前的子元素中找到該子元素的父級元素,然後再弄死這個子元素 174 var ele = elements[i]; 175 //從map地圖上刪除這個子元素div 176 ele.parentNode.removeChild(ele); 177 elements.splice(i, 1); 178 } 179 } 180 181 //把Snake暴露給window,外部可以訪問 182 window.Snake = Snake; 183 }()); 184 185 //自呼叫函式---遊戲物件================================================ 186 (function () { 187 188 var that = null;//該變數的目的就是為了儲存遊戲Game的例項物件------- 189 190 //遊戲的建構函式 191 function Game(map) { 192 this.food = new Food();//食物物件 193 this.snake = new Snake();//小蛇物件 194 this.map = map;//地圖 195 that = this;//儲存當前的例項物件到that變數中-----------------此時that就是this 196 } 197 198 //初始化遊戲-----可以設定小蛇和食物顯示出來 199 Game.prototype.init = function () { 200 //初始化遊戲 201 //食物初始化 202 this.food.init(this.map); 203 //小蛇初始化 204 this.snake.init(this.map); 205 //呼叫自動移動小蛇的方法========================||呼叫了小蛇自動移動的方法 206 this.runSnake(this.food, this.map); 207 //呼叫按鍵的方法 208 this.bindKey();//======================================== 209 }; 210 211 //新增原型方法---設定小蛇可以自動的跑起來 212 Game.prototype.runSnake = function (food, map) { 213 214 //自動的去移動 215 var timeId = setInterval(function () { 216 //此時的this是window 217 //移動小蛇 218 this.snake.move(food, map); 219 //初始化小蛇 220 this.snake.init(map); 221 //橫座標的最大值 222 var maxX = map.offsetWidth / this.snake.width; 223 //縱座標的最大值 224 var maxY = map.offsetHeight / this.snake.height; 225 //小蛇的頭的座標 226 var headX = this.snake.body[0].x; 227 var headY = this.snake.body[0].y; 228 //橫座標 229 if (headX < 0 || headX >= maxX) { 230 //撞牆了,停止定時器 231 clearInterval(timeId); 232 alert("遊戲結束"); 233 } 234 //縱座標 235 if (headY < 0 || headY >= maxY) { 236 //撞牆了,停止定時器 237 clearInterval(timeId); 238 alert("遊戲結束"); 239 } 240 }.bind(that), 150); 241 }; 242 243 //新增原型方法---設定使用者按鍵,改變小蛇移動的方向 244 Game.prototype.bindKey=function () { 245 246 //獲取使用者的按鍵,改變小蛇的方向 247 document.addEventListener("keydown",function (e) { 248 //這裡的this應該是觸發keydown的事件的物件---document, 249 //所以,這裡的this就是document 250 //獲取按鍵的值 251 switch (e.keyCode){ 252 case 37:this.snake.direction="left";break; 253 case 38:this.snake.direction="top";break; 254 case 39:this.snake.direction="right";break; 255 case 40:this.snake.direction="bottom";break; 256 } 257 }.bind(that),false); 258 }; 259 260 //把Game暴露給window,外部就可以訪問Game物件了 261 window.Game = Game; 262 }()); 263 264 265 266 //初始化遊戲物件 267 var gm = new Game(document.querySelector(".map")); 268 269 //初始化遊戲---開始遊戲 270 gm.init(); 271 272 273 274 275 </script> 276 </body> 277 </html>
View Code

如下圖:單個方塊表示食物,三個方塊連線一起表示小蛇,其中紫色方塊是蛇頭,雖然看起來簡單,做起來也需要不少的步驟,我們先分析一下思路~

 

首先,建立一個地圖~然後座標隨機顯示食物方塊,每次食物被小蛇“吃掉”的時候重新初始化;

然後,設定固定位置顯示小蛇方塊,設定定時器,讓小蛇動起來,判斷小蛇是否“吃掉”食物,是則初始化食物,複製蛇身最後一個方塊加到小蛇身體最後~判斷小蛇是否“撞牆”,是則提示遊戲提示。

那麼具體步驟現在開始~

設定食物方塊的自呼叫函式

  • 設定方塊的建構函式,同時設定一個變數準備儲存每個小方塊食物:
(function () {
    var elements = [];
   
    function Food(x, y, width, height, color) {
      this.x = x || 0;
      this.y = y || 0;
      this.width = width || 20;
      this.height = height || 20;
      this.color = color || "green";
    }
//把Food暴露給window,外部可以訪問
window.Food = Food;
}());
  • 初始化食物,賦值並且在地圖上顯示出來,注意:記得把食物加到一開始設定的變數中 var elements = [ ];
Food.prototype.init = function (map) {
      remove();

      var div = document.createElement("div");
      map.appendChild(div);
      div.style.width = this.width + "px";
      div.style.height = this.height + "px";
      div.style.backgroundColor = this.color;
      div.style.position = "absolute";
      this.x = parseInt(Math.random() * (map.offsetWidth / this.width)) * this.width;
      this.y = parseInt(Math.random() * (map.offsetHeight / this.height)) * this.height;
      div.style.left = this.x + "px";
      div.style.top = this.y + "px";

      //把div加入到陣列elements中
      elements.push(div);
    };
  • 設定初始化食物的第一個步驟,先在地圖上刪除這個食物:
 function remove() {
      for (var i = 0; i < elements.length; i++) {
        var ele = elements[i];
        ele.parentNode.removeChild(ele);
        elements.splice(i, 1);
      }
    }

設定小蛇的自呼叫函式

  • 設定方塊的建構函式,同時設定一個變數準備儲存每個小蛇的單個身體:
(function () {
    var elements = [];
 function Snake(width, height, direction) {
      this.width = width || 20;
      this.height = height || 20;
      this.body = [
        {x: 3, y: 2, color: "red"},//頭
        {x: 2, y: 2, color: "orange"},//身體
        {x: 1, y: 2, color: "orange"}//身體
      ];
      //方向
      this.direction = direction || "right";
    }
//把Snake暴露給window,外部可以訪問
window.Snake = Snake;
}());
  • 設定小蛇初始化的函式
 Snake.prototype.init = function (map) {
      //先刪除之前的小蛇
      remove();
      for (var i = 0; i < this.body.length; i++) {
        var obj = this.body[i];
        var div = document.createElement("div");
        map.appendChild(div);
        div.style.position = "absolute";
        div.style.width = this.width + "px";
        div.style.height = this.height + "px";
        div.style.left = obj.x * this.width + "px";
        div.style.top = obj.y * this.height + "px";
        div.style.backgroundColor = obj.color
        //把div加入到elements陣列中----目的是為了刪除
        elements.push(div);
      }
    };
  • 設定小蛇動起來的函式:
    • 讓小蛇動起來相當於是改變了小蛇的座標
    • 判斷小蛇動起來的方向,然後座標對應處理
    • 判斷小蛇是否“吃到”了食物,是則初始化食物,並且把蛇身最後一個部分複製一分加到蛇身最後
Snake.prototype.move = function (food, map) {
      //改變小蛇的身體的座標位置
      var i = this.body.length - 1;//2
      for (; i > 0; i--) {
        this.body[i].x = this.body[i - 1].x;
        this.body[i].y = this.body[i - 1].y;
      }
      
      switch (this.direction) {
        case "right":
          this.body[0].x += 1;
          break;
        case "left":
          this.body[0].x -= 1;
          break;
        case "top":
          this.body[0].y -= 1;
          break;
        case "bottom":
          this.body[0].y += 1;
          break;
      }

      var headX=this.body[0].x*this.width;
      var headY=this.body[0].y*this.height;
     
      if(headX==food.x&&headY==food.y){
      
        var last=this.body[this.body.length-1];
        
        this.body.push({
          x:last.x,
          y:last.y,
          color:last.color
        });
        //把食物刪除,重新初始化食物
        food.init(map);
      }
    };
  • 不要忘記設定初始化小蛇的第一個步驟,在地圖上刪除這個小蛇:
 function remove() {
      var i = elements.length - 1;
      for (; i >= 0; i--) {
        var ele = elements[i];
        ele.parentNode.removeChild(ele);
        elements.splice(i, 1);
      }
    }

 

設定遊戲的自呼叫函式:

  • 設定遊戲的建構函式,同時設定一個變數準備儲存遊戲Game的例項物件:var that=this;
 (function () {
    var that = null;//該變數的目的就是為了儲存遊戲Game的例項物件------
    function Game(map) {
      this.food = new Food();//食物物件
      this.snake = new Snake();//小蛇物件
      this.map = map;//地圖
      that = this;//儲存當前的例項物件到that變數中------此時that就是this
    }

    //把Game暴露給window,外部就可以訪問Game物件了
    window.Game = Game;
  }());
  • 初始化遊戲:可以設定小蛇和食物顯示出來
 Game.prototype.init = function () {
      
      this.food.init(this.map);
     
      this.snake.init(this.map);
     
      this.runSnake(this.food, this.map);
     
      this.bindKey();
    };
  • 設定小蛇可以自動的跑起來
Game.prototype.runSnake = function (food, map) {

      var timeId = setInterval(function () {
        
        this.snake.move(food, map);
        this.snake.init(map);
        
        var maxX = map.offsetWidth / this.snake.width;
        var maxY = map.offsetHeight / this.snake.height;
     
        var headX = this.snake.body[0].x;
        var headY = this.snake.body[0].y;
        
        if (headX < 0 || headX >= maxX) {
          //撞牆了,停止定時器
          clearInterval(timeId);
          alert("遊戲結束");
        }
        
        if (headY < 0 || headY >= maxY) {
          //撞牆了,停止定時器
          clearInterval(timeId);
          alert("遊戲結束");
        }
      }.bind(that), 150);
    };
  • 設定使用者按鍵,改變小蛇移動的方向
 Game.prototype.bindKey=function () {

      document.addEventListener("keydown",function (e) {
         switch (e.keyCode){
          case 37:this.snake.direction="left";break;
          case 38:this.snake.direction="top";break;
          case 39:this.snake.direction="right";break;
          case 40:this.snake.direction="bottom";break;
        }
      }.bind(that),false);
    };

初始化遊戲物件,開始遊戲

var gm = new Game(document.querySelector(".map"));
gm.init();

好的,到這裡結束啦~

另外如果有前端學習者想要尋找夥伴一起合作專案,可以來我這個群~群內還有大神等你哈哈哈~

前端學習交流群 883726280