利用Canvas+js实现贪吃蛇(4)

Author Avatar
Peipei Wong 6月 25, 2016
  • 在其它设备中阅读本文章

将贪吃蛇改造成面向对象,类似插件的东西。

过程中,要把握好this的指向,因为这个,调试了好大会
将randFood进行了修正,添加了一个配置参数与默认参数合并方法,其他的都还是一样的。
html代码没有改,在第一篇文章里

function tanchishe(options) {
    this.canvas = options.canvas;
    this.span_score = options.span_score;
    this.context = this.canvas.getContext('2d');
    this.snake = new Array(); //蛇身数组
    this.snakeLength = 1; //蛇身长度
    this.direct = options.direct || 37; //移动方向
    this.food_x; //食物的坐标   可以改为object对象
    this.food_y;
    this.score = 0; // 得分
    this.timer; //setInterval


    var defaults = {
        maxNumber: 630, // 最大长宽,这里的画布是正方形
        stride: 15, //每个小方块的长宽,
        speed: 300 // 移动速度
    }
    this.settings(options, defaults);
    this.init();
    this.update();


    var self = this;
    document.onkeydown = function(event) {
        console.log(self.direct)
        var event = event || window.event;
        clearInterval(self.timer);
        // 37:左 38:上 39:右  40:下
        var newDir = (event.keyCode > 36 && event.keyCode < 41) ? event.keyCode : 40;
        // 处理反方向
        if (Math.abs(self.direct - newDir) == 2) {
            alert("头碰到身体了,Game over!");
        } else {
            self.direct = newDir;
            self.update();
        }
    }
}


// 将配置参数和默认参数合并
tanchishe.prototype.settings = function(options, defaults) {
    this.ops = options || {};


    for (var i in defaults) {
        if (typeof options[i] === 'undefined') {
            options[i] = defaults[i];
        } else if (typeof options[i] === 'object') {
            for (var deepDef in defaults[i]) {
                if (typeof options[i][j] === 'undefined') {
                    options[i][j] = defaults[i][j];
                }
            }
        }
    }
}


// 随机生成食物
tanchishe.prototype.randFood = function() {
    // 保证生成的食物会在小方格里
    // 小方格的个数
    var shang = this.ops.maxNumber / this.ops.stride;
    // 小方格个数的整数部分
    var zheng = shang / 10;
    // 小方格的个位
    var yu = shang % 10;
    do {
        this.food_x = Math.ceil(Math.random() * zheng + yu) * this.ops.stride + 1;
        this.food_y = Math.ceil(Math.random() * zheng + yu) * this.ops.stride + 1;
    } while (this.isBody(this.food_x, this.food_y));


}


// 判断食物是否在蛇的身体上
tanchishe.prototype.isBody = function(param_x, param_y) {
    // 判断蛇头是否碰到了蛇身
    for (var i = 0; i < this.snakeLength - 1; i++) {
        if (this.snake[i].x === param_x && this.snake[i].y === param_y) {
            return true;
        }
    }
    // 判断食物是否在蛇的身体上
    var snakeLast = this.snake[this.snakeLength - 1];
    if (snakeLast) {
        if (snakeLast.x === param_x && snakeLast.y === param_y) {
            return true;
        }
    }
    return false;
}


// 定时更新画面
tanchishe.prototype.update = function() {
    var self = this;
    self.timer = setInterval(function() {
        // 到达边界
        if (self.snake[0].x < 1 || self.snake[0].y < 1 || self.snake[0].x > self.ops.maxNumber || self.snake[0].y > self.ops.maxNumber) {
            clearInterval(self.timer);
            alert('出边界了,Game over!');
        } else {
            // 重新绘制贪吃蛇
            self.drawSnake();


            // 检测是否吃到食物
            self.checkFood();
        }
    }, self.ops.speed)
}


// 绘制贪吃蛇
tanchishe.prototype.drawSnake = function() {
    // 擦出蛇尾巴
    var snakeLast = this.snake[this.snakeLength - 1],
        snakeHead = this.snake[0];
    this.clear(snakeLast.x, snakeLast.y);


    // 删除尾巴
    this.snake.pop();
    // 增加头
    this.addHead(snakeHead.x, snakeHead.y);
}


// 增加头
tanchishe.prototype.addHead = function(param_x, param_y) {
    var newX, newY;
    // 37:左 38:上 39:右  40:下
    switch (this.direct) {
        case 37:
            newX = param_x - this.ops.stride;
            newY = param_y;
            break;
        case 38:
            newY = param_y - this.ops.stride;
            newX = param_x;
            break;
        case 39:
            newX = param_x + this.ops.stride;
            newY = param_y;
            break;
        case 40:
            newY = param_y + this.ops.stride;
            newX = param_x;
            break;
    }


    // 增加蛇头
    // 检测头是否 碰到身体
    if (this.snakeLength > 3 && this.isBody(newX, newY)) {
        clearInterval(this.timer);
        alert("头碰到身体了,Game over!");
    } else {
        this.snake.unshift({
            x: newX,
            y: newY
        });
        this.draw(this.snake[0].x, this.snake[0].y);
    }
}


// 检测是否吃到食物
tanchishe.prototype.checkFood = function() {
    if (this.snake[0].x === this.food_x && this.snake[0].y === this.food_y) {
        // 增加头
        this.snakeLength += 1;
        this.addHead(this.food_x, this.food_y);
        // 改变分数
        this.score += 10;
        this.span_score.innerHTML = this.score;
        // 改变速度
        this.speed = (this.speed > 100) ? (this.speed - 20) : this.speed;
        this.randFood();
        console.log(this.snake)
        console.log(this.food_x)
        console.log(this.food_y)
        this.draw(this.food_x, this.food_y);
    }
}


// 清除
tanchishe.prototype.clear = function(param_x, param_y) {
    this.context.clearRect(param_x, param_y, this.ops.stride - 2, this.ops.stride - 2);
}


// 画小方块
tanchishe.prototype.draw = function(param_x, param_y) {
    this.context.fillRect(param_x, param_y, this.ops.stride - 2, this.ops.stride - 2);
}


// 初始化函数
tanchishe.prototype.init = function() {
    this.canvas.width = this.ops.maxNumber;
    this.canvas.height = this.ops.maxNumber;
    this.context.lineWidth = 1;
    this.context.fillStyle = '#69D69E';
    this.context.strokeStyle = "#89EFA3";
    var i = 0;
    while (i <= this.ops.maxNumber) {
        this.context.moveTo(0, i);
        this.context.lineTo(this.ops.maxNumber, i);
        this.context.stroke();


        this.context.moveTo(i, 0);
        this.context.lineTo(i, this.ops.maxNumber);
        this.context.stroke();
        i += this.ops.stride;
    }
    this.snake.push({
        x: 31,
        y: 61
    });
    this.randFood();
    this.draw(this.food_x, this.food_y);
    this.draw(this.snake[0].x, this.snake[0].y);
}


function tcs(options) {
    return new tanchishe(options);
}

在html中调用就行了

window.onload=function(){
    tcs({
        canvas : document.getElementById('myCanvas'),
        span_score : document.getElementById('score'),
        maxNumber : 630, // 最大长宽,这里的画布是正方形
        stride : 30, //每个小方块的长宽,
        speed : 300 // 移动速度
    });
}