1. 程式人生 > >JavaScript寫貪吃蛇

JavaScript寫貪吃蛇

分析:

遊戲中有三個物件:地圖(map), 食物(food), 蛇(snake)

地圖很簡單就是一個div盒子,給樣式即可,蛇,和食物都是屬於地圖中的元素,相對於地圖不斷改變自己的座標值,不要忘了給地圖定位

食物

1,食物的建構函式,  屬性===width,height,backgroundColor,left,top,

2,方法======init()初始化方法, 食物的位置在map中是隨機的,要給 left,top設定隨機值,設定完成後將食物div 追加到map中

值得注意的是:要定義一個數組來儲存食物,寫一個私有函式通過遍歷這個陣列,找到食物div,並將它們從map中移除,同時清空陣列,方便在此使用

1,蛇的建構函式 

屬性====蛇是由一連串的div組成,這些div又分別是物件,它們有width,height,backgroundColor,left,top direction(蛇前進的方向) 將這些小div的樣式放在json資料中,並將json儲存在一個數組snakeBody中,在初始化蛇時,遍歷陣列,獲得小div的樣式json資料包,將這些樣式分別給div,這些div組成一條初始的蛇;

2,方法====init()初始化,遍歷snakeBody陣列,獲得樣式的json資料包,將樣式值給新建立的div,將div追加到map中,小蛇建立成功,

值得注意的是:初始化之前要刪除之前map內的小蛇,跟食物類似,事先建立一個數組,儲存小蛇body的div,寫一個移除小蛇私有函式,遍歷該陣列,找到所有div,將它們從map中移除,並清空陣列,方便下次使用

===move()  讓蛇動起來的方法:除了蛇頭(蛇頭通過改變left,top的值來移動),剩下的組成蛇身體的每個小div的位置等於前面一個div的位置,這樣蛇就移動了.   下面我們來解決蛇頭怎麼動的問題: 蛇頭要根據方向東,通過switch  case 語句,判斷對應的方向該往哪裡動一格.    

移動的同時要考慮蛇吃到食物,通過判斷食物的位置和蛇頭的座標相同來確定蛇吃到食物,這時向snakBody的樣式json資料的陣列中,新增一個樣式json資料包,讓資料包中的屬性和蛇尾的div的樣式屬性相同即可,然後初始化snake,初始化食物;

 

遊戲物件:

將前面封裝的物件新增到遊戲物件中

1,建構函式  屬性===food物件,snake物件,map物件

2,方法=====初始化init(); 這個方法主要完成四件事: 初始化food, 初始化snake, 讓蛇動起來, 開啟鍵盤監聽

===讓蛇動起來:要新增定時器,定時器中不斷呼叫snake物件的move方法,和init()方法,這樣蛇就動起來了,什麼時候停止?  蛇撞牆了,什麼是撞牆了? 蛇頭越界, 蛇頭座標小於最小值,或則大於最大值,這時清除定時器,彈出對話方塊,告訴使用者遊戲結束.

===開啟鍵盤監聽:使用者要操作,,改變蛇的移動方向,監聽上下左右鍵,來改變snake物件中direction屬性的值,從而改變蛇的移動方向

 

所有物件寫完,例項化 物件,呼叫初始化函式,遊戲開始................

程式碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>貪吃蛇</title>
    <style>
        .map {
            width: 800px;
            height: 800px;
            background-color: #ccc;
            margin: 0 auto;
            position: relative;
        }
    </style>
</head>
<body>
<div class="map">
</div>

<script>

    //自呼叫======================================================================================  食物
    (function (window) {
        var element = [];

        function Food(width, height, color, left, top) {
            this.width = width || 20;
            this.height = height || 20;
            this.color = color || 'green';
            this.left = left || 0;
            this.top = top || 0;
        }

        //新增初始化方法
        Food.prototype.init = function (map) {
            console.log('初始化食物');
            //初始化,清除陣列中的元素,私有函式,方法外定義
            remove();
            //建立小盒子元素
            var div = document.createElement('div');
            //獲得隨機左右值
            this.left = Math.floor(Math.random() * map.offsetWidth / this.width) * this.width;
            this.top = Math.floor(Math.random() * map.offsetHeight / this.height) * this.height;
            //為div新增樣式
            div.style.position = 'absolute';
            div.style.width = this.width + 'px';
            div.style.height = this.height + 'px';
            div.style.left = this.left + 'px';
            div.style.top = this.top + 'px';
            div.style.backgroundColor = this.color;
            //追加到地圖中
            map.appendChild(div);
            //存入陣列中
            element.push(div);
        };

        //清除陣列中的元素,以及map中的小方塊
        function remove() {
            for (var i = 0; i < element.length; i++) {
                var ele = element[i];
                //刪除map中的食物
                ele.parentElement.removeChild(ele);
                //刪除陣列中的元素
                element.splice(i, 1);
            }
        }

        //將變數暴露到window中
        window.Food = Food;
    })(window);


    //自呼叫======================================================================================  小蛇

    (function (window) {
        var element = [];//陣列儲存蛇
        //自定義蛇的建構函式
        function Snake(width, height, direction) {
            this.width = width || 20;
            this.height = height || 20;
            this.direction = direction || 'right';
            //蛇身體
            this.snakeBody = [
                {x: 3, y: 2, color: 'red'},
                {x: 2, y: 2, color: 'orange'},
                {x: 1, y: 2, color: 'orange'}
            ];
        }

        //讓小蛇初始化
        Snake.prototype.init = function (map) {
            console.log('初始化小蛇');
            //remove()  移除之前的蛇
            remove();
            //遍歷陣列為蛇身體的的每一個部分新增樣式
            for (var i = 0; i < this.snakeBody.length; i++) {
                var div = document.createElement('div');
                div.style.width = this.width + 'px';
                div.style.height = this.height + 'px';
                div.style.left = this.snakeBody[i].x*this.width + 'px';
                div.style.top = this.snakeBody[i].y*this.height + 'px';
                div.style.backgroundColor = this.snakeBody[i].color;
                div.style.position = 'absolute';
                //追加到map中
                map.appendChild(div);
                //新增到陣列中
                element.push(div);
            }

        };
        //讓小蛇移動
        Snake.prototype.move = function(food,map){
          //從蛇尾開始遍歷
            var i = this.snakeBody.length - 1;
            for (;i>0;i--){
               this.snakeBody[i].x = this.snakeBody[i-1].x;
               this.snakeBody[i].y = this.snakeBody[i-1].y;
            }
            //蛇頭運動
            switch(this.direction){
                case 'top':
                    this.snakeBody[0].y -= 1;break;
                case 'bottom':
                    this.snakeBody[0].y += 1; break;
                case 'left':
                    this.snakeBody[0].x -= 1; break;
                case 'right':
                    this.snakeBody[0].x += 1;
                    break;
            }

            //蛇吃食物,當蛇頭和食物重合時,即蛇吃到食物
            //獲得蛇頭座標
            var headX = this.snakeBody[0].x*this.width;
            // console.log(headX);
            var headY = this.snakeBody[0].y*this.height;
            // console.log(headY);
            if(headX == food.left && headY == food.top){
                //向snakeBody陣列中追加一個物件,這個物件的位置和最後一個位置的樣式相同
                //獲取身體的最後一個div
                console.log("食用");
                var last = this.snakeBody[this.snakeBody.length - 1];
                this.snakeBody.push({
                    x:last.x,
                    y:last.y,
                    color:last.color
                });
                //初始化食物
                food.init(map);
            }
            // this.init(map);
        };


        //私有函式,刪除蛇
        function remove() {
            var i = element.length - 1;
            for (; i >= 0; i--) {
                var ele = element[i];
                ele.parentElement.removeChild(ele);
                element.splice(i, 1);
            }
        }
        //暴露區域性變數
        window.Snake = Snake;
    })(window);

    //自呼叫======================================================================================  遊戲

    (function(window){
        //建立遊戲物件
        var that = null;
        function Game(map){
            this.food = new Food(20,20,'black');
            this.snake = new Snake();
            this.map = map;
            that = this;
        }

        //新增方法初始化遊戲
        Game.prototype.init = function(){
            this.food.init(this.map);
            this.snake.init(this.map);
            //小蛇跑起來
            this.runSnake(this.food,this.map);
            //監聽鍵盤
            this.keyDown();
        };

        //新增runSnake方法
        Game.prototype.runSnake = function(food,map){//這裡的food,map是形參  不用this,內部有效
            console.log('runSnake呼叫');
            var timeId = setInterval(function(){
                this.snake.move(food,map);
                this.snake.init(map);
                //判斷蛇頭撞牆,遊戲結束
                var headX = this.snake.snakeBody[0].x*this.snake.width;
                var headY = this.snake.snakeBody[0].y*this.snake.height;
                var maxX = map.offsetWidth;
                var maxY = map.offsetHeight;
                if(headX < 0 || headX > maxX){
                    alert('遊戲結束');
                    clearInterval(timeId);
                }
                if(headY < 0 || headY > maxY){
                    alert('遊戲結束');
                    clearInterval(timeId);
                }
            }.bind(that),200)
        };

        //新增鍵盤監聽
        Game.prototype.keyDown = function(){
            console.log('keyDown呼叫');
            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)
        };

        window.Game = Game;
    })(window);


    //建立遊戲物件
    var gm =new Game(document.querySelector('.map'));
    //初始化遊戲
    gm.init();

    //test
    // var food = new Food();
    // var map = document.querySelector('.map');
    // food.init(map); //測試通過
    //
    // var snake = new Snake(20,20,'right');
    // snake.init(map);
    // snake.move(food,map);
    // setInterval(function(){snake.move(food,map)},100);//定時器內的函式必須是匿名函式
</script>


</body>
</html>