面向对象编程-贪吃蛇小游戏

来源:互联网 发布:python多进程 join 编辑:程序博客网 时间:2024/05/20 15:41

页面中的地图map

html结构

    <div id = "map"></div>

样式

    #map{        width:800px;        height:600px        margin:0 auto;        background-color:#ccc;        position:relative;    }

食物的对象

  • Food
    • 属性
      • 宽度width
      • 高度height
      • 背景色bgColor
      • 横向坐标x
      • 纵向坐标y
    • 方法:
      • 出现在地图上
书写贪吃蛇食物小点的构造函数
function Food(options){    options = options||{};    this.width = options.width||20;    this.height = options.height||20;    this.bgColor = options.bgColor||"blue"    this.x = options.x||0;    this.y = options.y||0;}

等同于构造函数function Food(width,height,bgColor){
};
Food(options){};options是一个置入的对象作为形参,可以多个参数传入,优点

    function Foodoptions){        ...    }var f = new Food({        width:50,        height:50,        ....    });
在Food的原型对象上创建共同的行为render渲染函数

将食物小块随机放在map地图上

Food.prototype.render = function(target){    //创建一个div    var div = document.createElement("div");    target.appendChild(div);    //设置div的一些样式 width height 背景色 left top    div.style.width = this.width+"px";    div.style.height = this.height+"px";    div.style.backgroundColor = this.bgColor;    //设置div的left值与top值    //this.x是0-800/20之间的随机数    this.x = parseInt(Math.random()*target.offsetWidth/this.width);    this.y = parseInt(Math.random()*target.offsetHeight/this.height);    div.style.left = this.x*this.width+"px";    div.style.top = this.y*this.height+"px";    div.style.position = "absolute";}

蛇的对象

  • Snake由多个小方块格div组成
    • 属性
      • width蛇的小方块格宽度
      • height蛇的小方块格高度
      • headColor蛇头颜色
      • bodyColor身体颜色
    • 方法
      • 渲染render()
      • 移动move()

创建Snake构造函数

function Snake(options){    options = options||{};    this.width = options.width ||20;    this.height = options.height ||20;    this.headColor = options.headColor ||"blue";    this.bodyColor = options.bodyColor||"pink";    //蛇的核心,蛇是由一个个小方块组成,默认蛇是由三个小方块组成    this.body = [        {x:2,y:0,bgColor:this.headColor},        {x:1,y:0,bgColor:this.bodyColor},        {x:0,y:0,bgColor:this.bodyColor}    ];    this.direction = "right";}
在原型中创建Snake通用渲染方法
Snake.prototype.render = function(target){    for(var i = 0;i<this.body.length;i++){        var span = document.createElement("span");        target.appendChild(span);        span.style.width = this.width+"px";        span.style.height = this.height+"px";        span.style.backgroundColor = this.body[i].bgColor;        span.style.position = "absolute";        span.style.left = this.body[i].x*this.width;        span.style.top = this.body[i].y*this.height;    }}
在原型对象中创建Snake通用的移动方法
Snake.prototype.move = function(target,food){//移动的思路:    //1. 移动蛇的身体    //2. 根据方向移动蛇头    //3. 删除整条蛇    //4. 重新渲染这条蛇    for (var i = this.body.length-1;i>0;i--){//控制蛇尾的变化    //蛇尾开始变为上一个块儿,可以不用记录上一个块儿的位置,更加方便,蛇尾是数组的第一个值    this.body[i].x = this.body[i-1].x;    this.body[i].y = this.body[i-1].y;    }    switch(this.direction){//控制蛇头的方向和变化    //记录一个方向条件,判断,方向的的变化控制x的增减或y,改蛇头        case "right":        this.body[0].x++;        break;        case "left":        this.body[0].x--;        break;        case "top":        this.body[0].y--;        break;        case "bottom":        this.body[0].y++;        break;    }    //用于蛇的身体加长,吃food,改变蛇的自身    //1. 判断蛇头的位置与食物的位置是否重合。    //2. 把移动前的那个蛇尾位置push到body中,添加蛇尾的思想    //3. 把原先的食物删除    //4. 重新渲染一个新的食物     if(head.x === food.x && head.y === food.y){            this.body.push({                x:last.x,                y:last.y,                bgColor:this.bodyColor            });        //删除食物,让食物重新渲染        var div = target.querySelector("div");        target.removeChild(div);        food.render(target);        }    //去除所有的span标签    var spans =target.querySelectorAll("span");    for(var i = 0;i < spans.length;i++){    target.removeChild(span[i]);    }}

游戏对象的封装

  • 游戏构造函数,管理所有的对象,地图
  • 属性
    • 蛇 食物 地图
  • 方法开始游戏

游戏对象以及初始化

function Game(target){    this.target = target;    this.snake = new Snake();    this.food = new Food();    //初始化游戏    this.init();}Game.prototype.init = function(){    //渲染蛇和食物    this.snake.render(this.target);    this.food.render(this.target);    var that = this;    //由于在下面的函数中要使用当前函数中的this    //但是下面的函数中有自己的this,如果直接用this,是访问不到我们这个函数中的this的    //所以我们声明一个新的变量that 将当前函数中的this赋值给这个that    //that和this的值就是相同的了    //在下面的函数中我们就可以使用that来访问到当前函数中的this了!        //onkeyup事件只能给有焦点的东西注册,或者是document        //document.onkeyup = function (e) {       // console.log(e.keyCode);可以打印出来按键的code字符    //}     document.onkeyup = function(e){         switch(e.keyCode){             case 37://控制左键             if(that.snake.direction != "right"){                 that.snake.direction = "left"             }             break;             //后面三个控制方向一样               case 38://控制上键             if(that.snake.direction != "bottom"){                 that.snake.direction = "top"             }             break;  case 39://控制右键             if(that.snake.direction != "left"){                 that.snake.direction = "right"             }             break;  case 40://控制下键             if(that.snake.direction != "top"){                 that.snake.direction = "bottom"             }             break;         }     }}

游戏开始的方法

var timer;Game.prototype.start = function(){    var that = this;//that存储外部this;    timer = setInterval(function(){    //在定时器中this是指的window对象        that.snake.move(that.target,that.food);        //撞墙的逻辑限制,如果蛇头的位置超出了地图,则说明暂停,停止定时器        var head = that.snake.body[0];//蛇头        if(head.x<0||head.x>that.target.offsetWidth/that.snake.width-1||head.y<0||head.y>that.target.offsetHeight/that.snake.height-1){            clearInterval(timer);            alert("已撞墙,game over");        }        //撞身体的判断,判断蛇头和身体位置是否重合,重合即失败        for(var i = 3;i < that.snake.body.length;i++){            if(head.x === that.snake.body[i].x&& head.y ===that.snake.body[i].y){                clearInterval(timer);                alert("撞自己,game over");            }        }    },150)}
沙箱模式封装

沙箱模式其实就是一个自调用函数
沙箱的作用,就是对代码起到保护作用,隔离作用

(function(window,undefined){    var a = 10;    var b = 100;    function Food(){    }    //将Food暴露到沙箱外面    window.Food = Food;})(window)var food = new Food();

运用了;(function(){})();函数自调用隔离,前后加分号用来防止前后结束,习惯。
+ 传参的必要性:
如果在沙箱中使用的沙箱外部的内容,那么就必须将内容以传参的形式传递到沙箱中进行使用
+ 原因:
+ 可以实现逻辑上的隔离
+ 有利于代码压缩

代码压缩

将所有不必要的空格和换行全部移除,将所有的变量全部重新命名成单个字母的形式,有利于代码压缩

tip:最后将所有的构造函数封装起来

//Food,命名新建food.js,以调用;(function(window,undefined){    function Food(options){    options = options||{};    this.width = options.width||20;    this.height = options.height||20;    this.bgColor = options.bgColor||"blue"    this.x = options.x||0;    this.y = options.y||0;}    Food.prototype.render = function(target){    //创建一个div    var div = document.createElement("div");    target.appendChild(div);    //设置div的一些样式 width height 背景色 left top    div.style.width = this.width+"px";    div.style.height = this.height+"px";    div.style.backgroundColor = this.bgColor;    //设置div的left值与top值    //this.x是0-800/20之间的随机数    this.x = parseInt(Math.random()*target.offsetWidth/this.width);    this.y = parseInt(Math.random()*target.offsetHeight/this.height);    div.style.left = this.x*this.width+"px";    div.style.top = this.y*this.height+"px";    div.style.position = "absolute";}window.Food = Food;})(window);
//蛇部,命名snake.js以调用    ;(function(window,undefined){        function Snake(options){    options = options||{};    this.width = options.width ||20;    this.height = options.height ||20;    this.headColor = options.headColor ||"blue";    this.bodyColor = options.bodyColor||"pink";    //蛇的核心,蛇是由一个个小方块组成,默认蛇是由三个小方块组成    this.body = [        {x:2,y:0,bgColor:this.headColor},        {x:1,y:0,bgColor:this.bodyColor},        {x:0,y:0,bgColor:this.bodyColor}    ];    this.direction = "right";}//蛇旋渲染Snake.prototype.render = function(target){    for(var i = 0;i<this.body.length;i++){        var span = document.createElement("span");        target.appendChild(span);        span.style.width = this.width+"px";        span.style.height = this.height+"px";        span.style.backgroundColor = this.body[i].bgColor;        span.style.position = "absolute";        span.style.left = this.body[i].x*this.width+"px";        span.style.top = this.body[i].y*this.height+"px";    }}//蛇部移动Snake.prototype.move = function(target,food){//移动的思路:    //1. 移动蛇的身体    //2. 根据方向移动蛇头    //3. 删除整条蛇    //4. 重新渲染这条蛇    for (var i = this.body.length-1;i>0;i--){//控制蛇尾的变化    //蛇尾开始变为上一个块儿,可以不用记录上一个块儿的位置,更加方便,蛇尾是数组的第一个值    this.body[i].x = this.body[i-1].x;    this.body[i].y = this.body[i-1].y;    }    switch(this.direction){//控制蛇头的方向和变化    //记录一个方向条件,判断,方向的的变化控制x的增减或y,改蛇头        case "right":        this.body[0].x++;        break;        case "left":        this.body[0].x--;        break;        case "top":        this.body[0].y--;        break;        case "bottom":        this.body[0].y++;        break;    }        var head = this.body[0];        var last =this.body[this.body.length - 1];    //用于蛇的身体加长,吃food,改变蛇的自身    //1. 判断蛇头的位置与食物的位置是否重合。    //2. 把移动前的那个蛇尾位置push到body中,添加蛇尾的思想    //3. 把原先的食物删除    //4. 重新渲染一个新的食物     if(head.x === food.x && head.y === food.y){            this.body.push({                x:last.x,                y:last.y,                bgColor:this.bodyColor            });        //删除食物,让食物重新渲染        var div = target.querySelector("div");        target.removeChild(div);        food.render(target);        }    //去除所有的span标签    var spans =target.querySelectorAll("span");    for(var i = 0;i < spans.length;i++){    target.removeChild(spans[i]);    }    //删除之后重新显现    this.render(target);}    window.Snake = Snake;    })(window);
//游戏对象封装,命名Game.js以调用;(function(window,undefined){    function Game(target){    this.target = target;    this.snake = new Snake();    this.food = new Food();    //初始化游戏    this.init();}Game.prototype.init = function(){    //渲染蛇和食物    this.snake.render(this.target);    this.food.render(this.target);    var that = this;    //由于在下面的函数中要使用当前函数中的this    //但是下面的函数中有自己的this,如果直接用this,是访问不到我们这个函数中的this的    //所以我们声明一个新的变量that 将当前函数中的this赋值给这个that    //that和this的值就是相同的了    //在下面的函数中我们就可以使用that来访问到当前函数中的this了!        //onkeyup事件只能给有焦点的东西注册,或者是document        //document.onkeyup = function (e) {        //console.log(e.keyCode);可以打印出来按键的code字符       //}     document.onkeyup = function(e){         switch(e.keyCode){             case 37://控制左键             if(that.snake.direction != "right"){                 that.snake.direction = "left"             }             break;             //后面三个控制方向一样               case 38://控制上键             if(that.snake.direction != "bottom"){                 that.snake.direction = "top"             }             break;  case 39://控制右键             if(that.snake.direction != "left"){                 that.snake.direction = "right"             }             break;  case 40://控制下键             if(that.snake.direction != "top"){                 that.snake.direction = "bottom"             }             break;         }     }}var timer;Game.prototype.start = function(){    var that = this;//that存储外部this;    timer = setInterval(function(){    //在定时器中this是指的window对象        that.snake.move(that.target,that.food);        //撞墙的逻辑限制,如果蛇头的位置超出了地图,则说明暂停,停止定时器        var head = that.snake.body[0];//蛇头        if(head.x<0||head.x>that.target.offsetWidth/that.snake.width-1||head.y<0||head.y>that.target.offsetHeight/that.snake.height-1){            clearInterval(timer);            alert("已撞墙,game over");        }        //撞身体的判断,判断蛇头和身体位置是否重合,重合即失败        for(var i = 3;i < that.snake.body.length;i++){            if(head.x === that.snake.body[i].x&& head.y ===that.snake.body[i].y){                clearInterval(timer);                alert("撞自己,game over");            }        }    },150)}window.Game = Game;})(window);

封装完毕调用
找地图对象作为参数放入封装的代码中

var map = document.getElementById("map");var g = new Game(map);g.start();//可以用个按钮装起来,开始。//好了,开始玩贪吃蛇吧。
原创粉丝点击