11RIA 闪客社区 - 最赞 Animate Flash 论坛

搜索
查看: 1883|回复: 0
上一主题 下一主题

[2D 物理引擎] 【9RIA—ladeng6666】—【Box2D系列教程 30】FilterData让Box2D碰撞分类进行

[复制链接] TA的其它主题
发表于 2018-2-6 11:41:01 | 显示全部楼层 |阅读模式

【游客模式】——注册会员,加入11RIA 闪客社区吧!一起见证Flash的再次辉煌……

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

转载:9RIA游戏开发者社区(天地会)
作者:ladeng6666(拉登大叔)
作者博客:http://www.ladeng6666.com/blog/


【Box2D系列教程-导航帖】—拉登大叔出品(总贴)


上一节课,我们学会了用b2Body的isSensor属性制作一个Box2D感应区域。当刚体的isSensor属性为true是,不会参与物理碰撞模拟,实际上,我们可以用Box2D的另一个特性实现相同的效果,它就是今天我们要学的FilterData类。

Filter是"过滤"的意思,所以FilterData可以简单的理解成用来过滤碰撞刚体(比如接下来哦我么要实现的矩形只与矩形刚体碰撞,圆形只与圆形刚体碰撞)。FilterData有3个属性:groupIndex、categoryBits和maskBits,他们的用法如下:

    groupIndex:表示刚体的分组信息。相同groupIndex属性的刚体属性一个组,groupIndex为正数时,刚体只和同组的刚体发生碰撞。groupIndex为负数时,刚体只和同组之外的刚体进行碰撞。
    categoryBits:表示刚体的分组信息,但不决定要碰撞的分组对象。另外,值得注意的,这个值必须是2的N次方。当然设置成其他值,程序不会报错,但是实际的碰撞分类效果,可能会出现意想不到的差错。
    maskBits:表示刚体要碰撞的那个刚体分组对象。这个值通常是另外一个FilterData对象的categoryBits属性,表示只与该类刚体发生碰撞。如果要对多组刚体进行碰撞,可以设置maskBits为多个categoryBits的加合。如要和categoryBits分别为2和4的刚体组都进行碰撞,可以设置maskBits属性为6。
举个例子,比如,圆形刚体的categoryBits和maskBits分别为2和2,矩形刚体的categoryBits和maskBits分别为4和4。那么圆形与矩形刚体之间不会发生碰撞,只有相同形状刚体之间才会发生碰撞。

FilterData对象可以通过赋值给b2FixtureDef对象filter属性来设置,非常简单吧!

[Actionscript3] 纯文本查看 复制代码
var fixtureRequest:b2FixtureDef = new b2FixtureDef();
fixtureRequest.filter = filter;

在下面的示例中,我没有在文档类中设置b2Fixture.filter属性,而是直接在LDEasyBox.createBod()中添加了一个filter的可选参数,变更后的createBox()方法如下,重点部分已用黄色标示。
[Actionscript3] 纯文本查看 复制代码
  public static function createBox(
                                world:b2World, 
                                posX:Number, 
                                posY:Number, 
                                boxWidth:Number, 
                                boxHeight:Number, 
                                isStatic:Boolean = false, 
                                userData:*= null, 
                                isSensor:Boolean = false, 
                                filter:b2FilterData = null 
                        ):b2Body {
                        //1.创建刚体需求b2BodyDef
                        var bodyRequest:b2BodyDef = new b2BodyDef();
                        bodyRequest.type = isStatic? b2Body.b2_staticBody:b2Body.b2_dynamicBody;
                        bodyRequest.position.Set(posX / pixelPerMeter, posY / pixelPerMeter);//记得米和像素的转换关系
                        //Ladeng6666是Flash元件库中的一个图片
                        if ( userData != null) {
                                bodyRequest.userData = userData;
                                //设定上衣的尺寸
                                bodyRequest.userData.width = boxWidth;
                                bodyRequest.userData.height = boxHeight;
                                //需手动将上衣添加到舞台上
                                //addChild(bodyRequest.userData);
                        }
                        //2.创建形状
                        var shapeBox:b2PolygonShape = new b2PolygonShape();
                        shapeBox.SetAsBox(boxWidth / pixelPerMeter / 2, boxHeight / pixelPerMeter / 2);
                        //2.Box2D世界工厂更具需求创建createBody()生产刚体
                        var box:b2Body = world.CreateBody(bodyRequest);

                        //3.创建敢提形状需求b2ShapeDef的子类
                        var fixtureRequest:b2FixtureDef = new b2FixtureDef();
                        fixtureRequest.density = 3;
                        fixtureRequest.friction = 0.3;
                        fixtureRequest.restitution = 0.2;
                        fixtureRequest.shape = shapeBox;
                        fixtureRequest.isSensor = isSensor;
                        if (filter != null) {
                                fixtureRequest.filter = filter;
                        }

                        //4.b2Body刚体工厂根据需求createShape生产形状                

                        box.CreateFixture(fixtureRequest);
                        return box;
                }


同样createCircle()方法也做出了相同的修改。
说了这么多,让我们看看示例吧!



完整的代码和注释如下:
[Actionscript3] 纯文本查看 复制代码
package  
{
        import Box2D.Dynamics.b2Body;
        import Box2D.Dynamics.b2FilterData;
        import Box2D.Dynamics.b2World;
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.MouseEvent;
        /**
         * ...
         * @author ladeng6666
         */
        public class FilterDataTest extends Sprite
        {
                //创建Box2D世界
                private var world:b2World;
                private var pressedBody:b2Body;
                //创建更重Filter数据
                private var boxFilter:b2FilterData;
                private var circleFilter:b2FilterData;
                private var wallFilter:b2FilterData;

                public function FilterDataTest() 
                {
                        //实例化Box2D世界
                        world = LDEasyBox2D.createWorld();
                        addChild(LDEasyBox2D.createDebug(world));
                        LDEasyBox2D.stage = stage;
                        //实例化刚体Filter对象
                        createFilter();
                        //因为要指定包裹墙体的FilterData,所有我修改了createWrapWall方法,把它放到这里了。
                        createWrapWall();
                        //创建经过FilterData分类的刚体
                        createBodies();
                        //添加事件侦听器
                        addEventListener(MouseEvent.MOUSE_DOWN, mouseEventHandler);
                        stage.addEventListener(MouseEvent.MOUSE_UP, mouseEventHandler);
                        addEventListener(Event.ENTER_FRAME, loop);

                }

                private function createFilter():void 
                {
                        //创建Box刚体FilterData分类数据,记得只能是2的N次方
                        boxFilter = new b2FilterData();
                        //设置刚体分类为2
                        boxFilter.categoryBits = 2
                        //设置刚体只与分类为10(即类别2矩形刚体+类别8包裹墙体)的刚体进行碰撞
                        boxFilter.maskBits = 10;

                        //创建Box刚体FilterData分类数据,记得只能是2的N次方
                        circleFilter = new b2FilterData();
                        //设置刚体分类为4
                        circleFilter.categoryBits = 4;
                        //设置刚体只与分类为12(即类别4圆形刚体+类别8包裹墙体)的刚体进行碰撞
                        circleFilter.maskBits = 12;

                        //设置包裹墙体的分类为8
                        wallFilter = new b2FilterData();
                        wallFilter.categoryBits = 8;
                }
                //更新Box2D引擎模拟
                private function loop(e:Event):void 
                {
                        LDEasyBox2D.updateWorld(world);
                }

                private function createBodies():void 
                {
                        for (var i:int = 0; i < 5; i++) {
                                //随机创建5个矩形刚体,并设置它的碰撞分类为boxFilter,即只与矩形刚体和墙体碰撞
                                LDEasyBox2D.createBox(world, Math.random() * 400 + 50, 30, 30, 30,false,null,false,boxFilter);
                                //随机创建5个矩形刚体,并设置它的碰撞分类为circleFilter,即只与圆形刚体和墙体碰撞
                                LDEasyBox2D.createCircle(world, Math.random() * 400 + 50,15,30,false,null,false,circleFilter);
                        }
                        //在舞台中间添加一个静态的长条刚体,设置它的碰撞分类是boxFilter,
                        //这样矩形刚体可以落在这个长条上,而圆形刚体不行
                        LDEasyBox2D.createBox(world, 275, 200, 350, 20, true, null, false, boxFilter);
                }
                private function createWrapWall():void {
                        var w:Number = 550;
                        var h:Number = 400;
                        var wallThick:Number = 20;//in pixels
                        //在创建墙体时,设置它的碰撞分类,让它可以同时与矩形和圆形刚体进行碰撞
                        LDEasyBox2D.createBox(world, w/2, 0, w, wallThick, true, null, false, wallFilter);
                        LDEasyBox2D.createBox(world, w/2, h, w, wallThick, true, null, false, wallFilter);
                        LDEasyBox2D.createBox(world, 0, h/2, wallThick, h, true, null, false, wallFilter);
                        LDEasyBox2D.createBox(world, w, h/2, wallThick, h, true, null, false, wallFilter);
                }
                //鼠标拖动刚体
                private function mouseEventHandler(e:MouseEvent):void 
                {
                        if (e.type == MouseEvent.MOUSE_DOWN) {
                                pressedBody = LDEasyBox2D.getBodyAtMouse(world);
                                if (pressedBody != null) {
                                        LDEasyBox2D.startDragBody(world, pressedBody);
                                }
                        }else if (e.type == MouseEvent.MOUSE_UP) {
                                LDEasyBox2D.stopDragBody(world);
                        }

                }

        }

}


下载:
OK 2012-09-01 如何固定动态刚体.rar (444.58 KB, 下载次数: 0)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

站长推荐 上一条 /1 下一条

感谢所有支持论坛的朋友:下面展示最新的5位赞助和充值的朋友……更多赞助和充值朋友的信息,请查看:永远的感谢名单

SGlW(66139)、 anghuo(841)、 whdsyes(255)、 longxia(60904)、 囫囵吞澡(58054)

下面展示总排行榜的前3名(T1-T3)和今年排行榜的前3名的朋友(C1-C3)……更多信息,请查看:总排行榜今年排行榜

T1. fhqu1462(969)、 T2. lwlpluto(14232)、 T3. 1367926921(962)  |  C1. anghuo(147)、 C2. fdisker(27945)、 C3. 囫囵吞澡(58054)



快速回复 返回顶部 返回列表