面向对象 贪吃蛇案例

一、案例演示

贪吃蛇游戏,利用面向对象思想绘制,实现吃到食物和碰到边界死亡功能。

二、知识点

面向对象编程、边界检测、吃掉食物后随机生成食物、吃到食物往蛇的尾巴加上一节 

三、案例中的对象:食物、蛇、游戏对象

食物对象。

//创建数组用来保存每一个小方块食物
var elements = [];

食物的属性:所在位置、宽高度、颜色

function Food(x, y, width, height, color) {
            //如果没有传入x值,则默认值为0
            this.x = x || 0;
            this.y = y || 0;
            this.width = width || 20;
            this.height = height || 20;
            this.color = color || 'green';
        }

通过原型设置初始化方法,实现随机产生食物对象,并渲染到map上。如果直接在Food的构造函数中写初始化方法,调用一次需要开辟一块内存,多次调用就要开辟多个内存。但在原型上添加方法则只需要开辟一次内存,节省了空间。

 Food.prototype.init = function (map) {
  // 随机食物的位置,map.宽度/food.宽度,总共有多少分food的宽度,随机一下。然后再乘以food的宽度
  this.x = parseInt(Math.random() * map.offsetWidth / this.width) * this.width;
  this.y = parseInt(Math.random() * map.offsetHeight / this.height) * this.height;

  // 动态创建食物对应的div
  var div = document.createElement('div');
  map.appendChild(div);
  div.style.position = position;
  div.style.left = this.x + 'px';
  div.style.top = this.y + 'px';
  div.style.width = this.width + 'px';
  div.style.height = this.height + 'px';
  div.style.backgroundColor = this.color;
  elements.push(div);
}

当贪吃蛇吃到食物时,食物需要删除。 通过定义私有函数(外部不能访问)来删除食物

 function remove() {
            // elements数组中有这个食物(储存盒)
            for(i = 0; i < elements.length; i++) {
                var ele = elements[i];
                // 删除页面上div
                ele.parentNode.removeChild(ele);
                // 删除elements数组中的元素
                elements.splice(i, 1);
            }
        }

因此初始化init方法中应该调用remove方法。 

通过自调用函数,进行封装,通过window暴露Food对象

  //把Food暴露给window,外部可以使用 
   window.Food=Food;

蛇对象。

/创建数组存放小蛇的每个身体部分
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: 'black'},
                {x: 1, y: 2, color: 'black'}
                // {x: 0, y: 2, color: 'red'}
            ];
            this.direction = direction || 'right';
        }

通过原型设置初始化方法,把蛇渲染到map上 。 

Snake.prototype.init = function(map) {
            //删除原先的小蛇
            remove();
            //循环创建div
            for(var i = 0; i < this.body.length; i++) {
                //数组中的每一元素都是一个对象 obj
                var obj = this.body[i];
                var div = document.createElement('div');
                map.appendChild(div);
                div.style.left = obj.x * this.width + 'px';
                div.style.top = obj.y * this.height + 'px';
                div.style.position = "absolute";
                div.style.backgroundColor = obj.color;
                div.style.width = this.width + 'px';
                div.style.height = this.height + 'px';
                //把div加入到elements数组中--为了删除
                elements.push(div)
            }
        }

通过原型添加move方法,让蛇动起来

 Snake.prototype.move = function (food, map) {
            // 让蛇身体的每一部分往前移动一下
            var i = this.body.length - 1;
            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 'left':
                    this.body[0].x -= 1;
                    break;
                case 'right':
                    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];
                this.body.push({
                    x: last.x,
                    y: last.y,
                    color: last.color
                })
                // 把现在的食物对象删除,并重新随机渲染一个食物对象
                food.init(map);
            }

        }

通过定义私有函数来删除蛇

 function remove(){
        //    获取数组
            var i = elements.length - 1;
            for(; i >= 0; i--) {
                // 删除页面上渲染的蛇
                elements[i].parentNode.removeChild(elements[i]);
                // 删除elements数组中的元素
                elements.splice(i, 1);
            }
        }

通过自调用函数,进行封装,通过window暴露Snake对象

window.Snake=Snake;

 游戏对象。游戏对象用来管理游戏中的所有对象和开始游戏

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
利用面向对象的方法,实现贪吃蛇。 1. 利用面向对象的思想实现——一个食物对象、一个蛇对象、一个游戏总控对象。 2. 在使用××.prototype= {}重写原型对象的时候,一定要加上一句constructor:该对象。不然会造成实例化出来的实例的constructor为object。 3. 在underscore中,使用_.random(a,b)即可获得a-b中的一个随机数。 4. 在求食物的随机位置的时候,用到了panel.clientHeight/this.height - 1) * this.height。 原理是使用盒子的高度/小球的高度,可以算得最多放多少个小球。因为要控制小球不能超过边界,所以总数量要减去1,数量×高度即为随机位置的最大值。 5. 在蛇对象中,用body数组存放蛇身体每一个部分对象。蛇的绘制过程就是遍历body,在面板上绘制。 6. 蛇的移动分为两部分。 ① 蛇节移动到前一个蛇节的位置。直到蛇头后一个蛇节移动到蛇头的位置。 ② 根据direction判断蛇头如何移动。 注意:在游戏绘制的过程中,界面的每一次绘制都要**删除**之前的绘制,不然会叠加到一起。 7. 在蛇的闭包中建一个局部数组,存储蛇对象,可以更加方便的删除操作。 8. 只有在原型对象中的方法和属性,外界是可以调用的。 9. 蛇的移动(动画)必然需要定时器协助。定时器的时间,即象征着刷新速度,也就是难度。 10. this所在的函数在哪一个对象中,this就指向谁。单独写一个函数的时候,如果调用之前对象的this,需要备份指针(将对象的this赋值给另一个变量)。 11. JavaScript原生的键盘按下事件(keydown) 中,事件有一个keyCode属性,其值代表按下的键。其中:37—left、38—top、39—right、40—bottom。 12. 边界控制。通过判断蛇头与最大X和Y的关系,判断是否碰到边界。 13. confirm()方法用于显示一个带有指定消息和确认及取消按钮的对话框。 14. window.location.reload(); 重新加载当前文档 15. window.close() 方法用于关闭浏览器窗口。 16. 与食物的碰撞检测:如果蛇头和食物坐标重叠,将蛇尾添加到body中。并重新绘制一个食物点,将之前的食物删掉。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值