[入门教程]使用Cocos2d-html5游戏引擎编写一个简单的游戏 第九回合:碰撞检测

碰撞检测

  哇靠?添加敌机之后是不是有种坑爹的感觉,子弹从敌机上穿过,飞机碰到敌机也不会撞毁。没关系,下面我们就为游戏加入碰撞检测。几乎每个游戏都有碰撞检测,有的复杂,有的简单,这里我们只使用最简单游戏检测就好。

 我们假设每个精灵(飞机,子弹,敌机)都是一个长、宽分别和X轴、Y轴平行的矩形。这个矩形包裹住了这些精灵,如果两个矩形有交集,我们就认为两个元素发生了碰撞。
var MyLayer = cc.LayerColor.extend({
    plane:null,
    _bullets:null,
    _targets:null,

    init:function () {

        // 1. super init first
        // 必须调用父类init()方法,很多bug都是由于没有调用父类init()方法造成的
        this._super();

        // 用来装子弹的数组
        this._bullets = ];
        // 用来装敌机
        this._targets = ];

        // 设置Layer的背景
        this.setColor(cc.c4(126,126,126,126));

        // 获得游戏可视的尺寸
        var winSize = cc.Director.getInstance().getWinSize();
        // 获取屏幕坐标原点
        var origin = cc.Director.getInstance().getVisibleOrigin();

        // 创建一个飞机,游戏中大部分物体都能使用cc.Sprite表示
        // 飞机的图案按照cc.rect(x,y,width,height)从图片中截取
        // 以(x,y)为左上角,width为宽,height为高的矩形
        this.plane = cc.Sprite.create(s_Plane,cc.rect(2,168,62,75));
        // 将飞机设置在屏幕底部,居中的位置
        // 图片的锚点在矩形的中心点,设置的就是这个点的位置
        this.plane.setPosition(cc.p(origin.x + winSize.width/2 , origin.y + this.plane.getContentSize().height/2));

        this.addChild(this.plane,1);

        // 设置定时器,定时器每隔0.2秒调用一次addBullet方法
        this.schedule(this.addBullet,0.2);
        // 添加增加敌机的定时器
        this.schedule(this.addTarget,0.4);
        // 添加碰撞检测,不加第二个参数,默认为每帧执行一次
        this.schedule(this.updateGame);

        // 将层设置为可触摸
        this.setTouchEnabled(true);

        return true;
    },

    onTouchesMoved:function(touches,event){
        var touch = touches;
        var location = touch.getLocation();
        if(this.onClickFlag){
            this.plane.setPosition(location);
        }
    },

    onTouchesEnded:function(touches, event){
        this.onClickFlag = false;
    },

    onTouchesBegan:function(touches,event){
        var touch = touches;
        var location = touch.getLocation();
        if(cc.rectContainsPoint(this.plane.getBoundingBox(),location)){
            this.onClickFlag = true;
        }
    },

    addBullet:function(){

        var winSize = cc.Director.getInstance().getWinSize();
        var origin = cc.Director.getInstance().getVisibleOrigin();
        // 获得飞机的位置
        var planePosition = this.plane.getPosition();
        // 子弹穿越屏幕要花费的秒数
        var bulletDuration = 1;

        // 创建一个子弹
        var bullet = cc.Sprite.create(s_Plane,cc.rect(66,237,7,20));

        // 根据飞机的位置,初始化子弹的位置
        bullet.setPosition(cc.p(planePosition.x,planePosition.y+bullet.getContentSize().height));

        // 一个移动的动作
        // 第一个参数为移动到目标所需要花费的秒数,为了保持速度不变,需要按移动的距离与屏幕高度按比例计算出花费的秒数
        var actionMove = cc.MoveTo.create(bulletDuration * ((winSize.height - planePosition.y - bullet.getContentSize().height/2)/winSize.height),
                cc.p(planePosition.x,
                    origin.y + winSize.height + bullet.getContentSize().height/2));
        // 设置一个回调函数,移动完毕后回调spriteMoveFinished()方法。
        var actionMoveDone = cc.CallFunc.create(this.spriteMoveFinished,this);
        // 让子弹执行动作
        bullet.runAction(cc.Sequence.create(actionMove,actionMoveDone));
        // 为子弹设置标签,以后可以根据这个标签判断是否这个元素为子弹
        bullet.setTag(6);

        this._bullets.push(bullet);
        this.addChild(bullet,0);
    },

    addTarget:function(){

        var target = cc.Sprite.create(s_Plane,cc.rect(201,88,39,27));
        target.setTag(1);

        var winSize = cc.Director.getInstance().getWinSize();

        // 设置敌机随机出现的X轴的值
        var minX = target.getContentSize().width/2;
        var maxX = winSize.width - target.getContentSize().width/2;
        var rangeX = maxX - minX;
        var actualX = Math.random() * rangeX + minX;
        // 在一定范围内随机敌机的速度
        var minDuration = 2.5;
        var maxDuration = 4;
        var rangeDuration = maxDuration - minDuration;
        var actualDuration = Math.random() * rangeDuration + minDuration;

        target.setPosition(cc.p(actualX, winSize.height + target.getContentSize().height/2));

        var actionMove = cc.MoveTo.create(actualDuration ,cc.p(actualX, 0 - target.getContentSize().height));
        var actionMoveDone = cc.CallFunc.create(this.spriteMoveFinished,this);

        target.runAction(cc.Sequence.create(actionMove,actionMoveDone));

        this.addChild(target,1);
        this._targets.push(target);
    },
    updateGame:function(){
        var targets2Delete = ];

        var i ;
        //遍历屏幕上的每个敌机
        for( i in this._targets ){
            //console.log("targetIterator");
            var target = this._targets i ];
            // 获得敌机的碰撞矩形
            var targetRect = target.getBoundingBox();

            var bullets2Delete = ];
            // 对于每个敌机,遍历每个屏幕上的子弹,判断是否碰撞
            for(i in this._bullets){
                var bullet = this._bullets i ];
                var bulletRect = bullet.getBoundingBox();
                // 判断两个矩形是否碰撞
                if(cc.rectIntersectsRect(bulletRect,targetRect)){
                    // 碰撞则将子弹加入待删除列表
                    bullets2Delete.push(bullet);
                }
            }
            // 如果待删除的子弹数组的内容大于零,说明敌机碰到了子弹,将敌机加入待删除数组
            if(bullets2Delete.length > 0){
                targets2Delete.push(target);
            }

            //删除发生碰撞的每个子弹
            for(i in bullets2Delete){
                var bullet = bullets2Delete i ];
                var index = this._bullets.indexOf(bullet);
                if (index > -1) {
                    this._bullets.splice(index, 1);
                }
                this.removeChild(bullet);
            }

            bullets2Delete = null;
        }
        //删除发生碰撞的每个敌机
        for( i in targets2Delete){
            var target = targets2Delete i ];

            var index = this._targets.indexOf(target);
            if (index > -1) {
                this._targets.splice(index, 1);
            }

            this.removeChild(target);
        }

        targets2Delete = null;

    },

    spriteMoveFinished:function(sprite){
        // 将元素移除出Layer
        this.removeChild(sprite, true);
        if(sprite.getTag()==1){
            // 把目标从数组中移除
            var index = this._targets.indexOf(sprite);
            if (index > -1) {
                this._targets.splice(index, 1);
            }
        } else if(sprite.getTag()==6){
            // 把子弹从数组中移除
            var index = this._bullets.indexOf(sprite);
            if (index > -1) {
                this._bullets.splice(index, 1);
            }
        }
    }

});

var MyScene = cc.Scene.extend({
    onEnter:function () {
        this._super();
        var layer = new MyLayer();
        this.addChild(layer);
        layer.init();
    }
});

```


      运行成功之后,子弹碰到敌机之后两个都回消失。


上一篇:http://www.cocoachina.com/bbs/read.php?tid=188220
下一篇:http://www.cocoachina.com/bbs/read.php?tid=188225

Uncaught TypeError: undefined is not a function
在var targetRect = target.getBoundingBox();这一句~

不好意思,论坛把数组中的 i ]当做特殊字符处理了。。所以没有显示出来。
现在已经更正,有4个改动的地方。

代码中木有飞机和敌机的碰撞检测啊。。应该怎么实现呢。。
现在没有办法跳到GAME OVER界面。
求大神指教

???更正哪里了???请问现在的是更改以后的么??

:2: :14:

请问你的getBoundingBox()解决了么