007--自找麻煩之 面向對象(貪喫蛇)

其實,成功者一顆寂寞孤獨的心,因爲成功者的造就本就是用寂寞孤獨堆積而成!

1. 面向對象的編程思想:根據需求,抽象出相關的對象,總結對象的特徵和行爲,把特徵變成屬性,行爲變成方法,然後定義(js)構造函數,實例化對象,通過對象調用屬性和方法,完成相應的需求

2. 方法需要共享就放到構造函數的原型上,不需要共享的話就直接放到構造函數裏面

3. 以貪喫蛇舉例:兩個小對象(蛇,食物)即是要兩個構造函數,一個大對象(把整個遊戲看成一個對象,這個遊戲裏面有蛇,食物,地圖)

        每個對象用一個自調用函數包裹起來

        食物:寬,高,顏色,橫縱座標(先定義構造函數,然後創建對象);

                 在頁面顯示出來是食物的行爲(方法)

        parentNode 是元素的父元素,removeChild("ele")是刪除子元素ele

//自調用函數----食物的
  (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";
    }

    //爲原型添加初始化的方法(作用:在頁面上顯示這個食物)
    //因爲食物要在地圖上顯示,所以,需要地圖的這個參數(map---就是頁面上的.class=map的這個div)
    Food.prototype.init = function (map) {
      //先刪除這個小食物
      //外部無法訪問的函數
      remove();

      //創建div
      var div = document.createElement("div");
      //把div加到map中
      map.appendChild(div);
      //設置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() {
      //elements數組中有這個食物
      for (var i = 0; i < elements.length; i++) {
        var ele = elements[i];
        //找到這個子元素的父級元素,然後刪除這個子元素
        ele.parentNode.removeChild(ele);
        //再次把elements中的這個子元素也要刪除
        elements.splice(i, 1);
      }
    }

    //把Food暴露給Window,外部可以使用
    window.Food = Food;
  }());

        蛇 : 寬,高,方向 (寬和高是指蛇的每個小方塊的寬高) 

        倒循環:for(;i>0;i--){}    (第一個分號前面相當於i="你自己定的值")

(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.prototype.init = function (map) {
      //先刪除之前的小蛇
      remove();//===========================================

      //循環遍歷創建div
      for (var i = 0; i < this.body.length; i++) {
        //數組中的每個數組元素都是一個對象
        var obj = this.body[i];
        //創建div
        var div = document.createElement("div");
        //把div加入到map地圖中
        map.appendChild(div);
        //設置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];
        //把最後的蛇尾複製一個,重新的加入到小蛇的body中
        this.body.push({
          x:last.x,
          y:last.y,
          color:last.color
        });
        //把食物刪除,重新初始化食物
        food.init(map);
      }
    }
    ;//刪除小蛇的私有的函數=============================================================================
    function remove() {
      //刪除map中的小蛇的每個div,同時刪除elements數組中的每個元素,從蛇尾向蛇頭方向刪除div
      var i = elements.length - 1;
      for (; i >= 0; i--) {
        //先從當前的子元素中找到該子元素的父級元素,然後再弄死這個子元素
        var ele = elements[i];
        //從map地圖上刪除這個子元素div
        ele.parentNode.removeChild(ele);
        elements.splice(i, 1);
      }
    }

    //把Snake暴露給window,外部可以訪問
    window.Snake = Snake;
  }());

        遊戲對象

        這裏有一個bind方法,傳參數就能改變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.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是window
        //移動小蛇
        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) {
        //這裏的this應該是觸發keydown的事件的對象---document,
        //所以,這裏的this就是document
        //獲取按鍵的值
        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);
    };

    //把Game暴露給window,外部就可以訪問Game對象了
    window.Game = Game;
  }());

        外部的代碼只要兩行

//初始化遊戲對象
  var gm = new Game(document.querySelector(".map"));

  //初始化遊戲---開始遊戲
  gm.init();

        ps:鍵盤按下事件用document.οnkeydοwn=function(){}  ;

               addEventListener(event,function,capture/bubble);

最後將代碼重構,將三個自執行函數分別保存在三個js文件當中,然後主html文件中去引用 。     

4. 方法和函數是有區別的:方法得通過對象調用,函數直接自己調用

        


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章