snake

203 阅读2分钟
Title #map { width: 800px; height: 600px; background: #cccccc; position: relative; top: 0px; left: 0px; }
<div id="map"></div>
<script src="./line.js"></script>

<script src="./Food.js"></script>
<script src="./Snake.js"></script>
<script src="./Game.js"></script>

<script>

    new Game().start();
    // var game = new Game();
    // game.start();
</script>

/* 闭包实现沙箱模式 */

(function (w) { //(1)食物构造函数 function Food(width, height, left, top, bgc) { this.width = width || 20; this.height = height || 20; this.left = left || 0; this.top = top || 0; this.bgc = bgc || getRandomColor(); };

//(2)每一个食物都可以显示到页面,应该添加到原型中
Food.prototype.render = function (map) {
    //this : 指向调用这个方法的每一个食物对象

    //1.创建空标签 div
    var div = document.createElement('div');
    //2.设置样式
    div.style.width = this.width + 'px';
    div.style.height = this.height + 'px';
    div.style.position = 'absolute';
    //求随机格子数
    var geziX = map.offsetWidth / this.width;
    var geziY = map.offsetHeight / this.height;
    var x = Math.floor(Math.random() * geziX);
    var y = Math.floor(Math.random() * geziY);
    div.style.left = this.left || x * this.width + 'px';
    div.style.top = this.top || y * this.height + 'px';

    div.style.backgroundColor = this.bgc;
    //3.添加到页面
    map.appendChild(div);

    this.ele = div;//把dom元素存到对象的属性中(用于移除)
};

function getRandomColor() {

    var r = Math.floor(Math.random() * 256);
    var g = Math.floor(Math.random() * 256);
    var b = Math.floor(Math.random() * 256);
    return 'rgb(' + r + ',' + g + ',' + b + ')';
};

//暴露接口
w.Food = Food;

})(window);

game.js: (function (w) { //1.构造函数 : 游戏对象: 地图 蛇 食物 function Game() { this.food = new Food(); this.snake = new Snake(); this.map = document.getElementById('map');

    this.food.render(this.map);
    this.snake.render(this.map);
}

//2. start:开始游戏  监听键盘按键
Game.prototype.start = function () {
    //一级链 : this : game对象

    window.onkeydown = function (e) {
        //二级链  this : window
        console.log(e.keyCode);
        switch (e.keyCode) {// 细节: 蛇不能倒着移动
            case 37:
                //左
                console.log('左');
                if (this.snake.direction != 'right') {
                    this.snake.direction = 'left';
                };


                break;
            case 38:
                //上
                console.log('上');
                if (this.snake.direction != 'bottom') {
                    this.snake.direction = 'top';
                };

                break;
            case 39:
                //右
                console.log('右');
                if (this.snake.direction != 'left') {
                    this.snake.direction = 'right';
                };

                break;
            case 40:
                //下
                console.log('下');
                if (this.snake.direction != 'top') {
                    this.snake.direction = 'bottom';
                };
                break;
            default:
                return;//如果是其他的按钮,则不做任何处理
                break;
        };
        console.log('蛇移动');

        //3.事件处理
        //(1)蛇移动
        this.snake.move(this.map);
        //(2)蛇边界检测(只能在地图移动)
        if (this.snake.body[0].x < 0 || this.snake.body[0].x > this.map.offsetWidth / this.snake.width - 1) {
            this.end();
        };

        if (this.snake.body[0].y < 0 || this.snake.body[0].y > this.map.offsetHeight / this.snake.height - 1) {
            this.end();
        };
        //(3)蛇吃食物
        //蛇头的位置和食物位置完全重叠
        if (this.snake.snakeElements[0].offsetLeft == this.food.ele.offsetLeft && this.snake.snakeElements[0].offsetTop == this.food.ele.offsetTop) {
            //alert('迟到东西了');
            this.snake.eat(this.food, this.map);

            //(4)刷新食物 : 只有迟到东西才刷新
            this.map.removeChild(this.food.ele);
            this.food = new Food();
            this.food.render(this.map);
        };
    }.bind(this);//将二级链中的this:window,修改成一级链中的this:game

}

//3. end:结束游戏  刷新页面
Game.prototype.end = function () {
    alert('Game Over');
    window.location.reload();
};

//4.暴露接口
w.Game = Game;

})(window);

snake.js: /* 沙箱模式 */ (function (w) {

//1.蛇对象构造函数
function Snake(width, height, direction) {
    this.width = width || 20;
    this.height = height || 20;
    this.direction = direction || 'right';
    this.body = [{
        x: 3,
        y: 2,
        bgc: 'red'
    }, {
        x: 2,
        y: 2,
        bgc: getRandomColor()
    }, {
        x: 1,
        y: 2,
        bgc: getRandomColor()
    }];
};

//2. render: 渲染到页面
Snake.prototype.render = function (map) {
    // this : 调用这个方法的每一个蛇对象

    this.snakeElements = [];//声明数组存储每一节身体div(用于移除)
    for (var i = 0; i < this.body.length; i++) {
        var section = this.body[i];
        console.log(section);

        //1.创建空标签
        var div = document.createElement('div');
        //2.设置样式
        div.style.width = this.width + 'px';
        div.style.height = this.height + 'px';
        div.style.position = 'absolute';
        div.style.left = section.x * this.width + 'px';
        div.style.top = section.y * this.height + 'px';
        div.style.backgroundColor = section.bgc;
        //3.添加到页面  
        map.appendChild(div);
        this.snakeElements.push(div);
    };
};



/* 3. move:蛇移动 */
Snake.prototype.move = function (map) {
    //this : 调用这个方向得蛇对象

    //1.倒着遍历蛇的身体,每一节都是前一节位置
    for (var i = this.body.length - 1; i > 0; i--) {// i > 0 蛇头不用遍历的
        console.log(this.body[i]);
        this.body[i].x = this.body[i - 1].x;
        this.body[i].y = this.body[i - 1].y;
    };
    //2.蛇头位置取决于移动方向
    switch (this.direction) {
        case 'left':
            this.body[0].x--;
            break;
        case 'top':
            this.body[0].y--;
            break;
        case 'right':
            this.body[0].x++;
            break;
        case 'bottom':
            this.body[0].y++;
            break;
    }
    //3.移除旧蛇(脱皮)
    this.remove();
    //4.显示新蛇
    this.render(map);
};

/* 4.remove:蛇移除 */
Snake.prototype.remove = function () {
    //this: 调用这个方法蛇对象
    for (var i = 0; i < this.snakeElements.length; i++) {
        this.snakeElements[i].parentNode.removeChild(this.snakeElements[i]);
    };
};

/* 5.eat 蛇吃食物  food: 吃到的食物  map:要显示的父元素
*/
Snake.prototype.eat = function (food, map) {
    //this : 调用这个方法的蛇对象
    //1. 记录当前蛇尾巴的位置 :将食物添加到蛇的尾巴位置
    var lastX = this.body[this.body.length - 1].x;
    var lastY = this.body[this.body.length - 1].y;
    this.body.push({
        x: lastX,
        y: lastY,
        bgc: food.bgc
    });
    //2. 移除旧蛇
    this.remove();
    //3. 显示新蛇
    this.render(map);
};

function getRandomColor() {

    var r = Math.floor(Math.random() * 256);
    var g = Math.floor(Math.random() * 256);
    var b = Math.floor(Math.random() * 256);
    return 'rgb(' + r + ',' + g + ',' + b + ')';
};

//暴露接口
w.Snake = Snake;

})(window)