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

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

[2D 物理引擎] 【9RIA—ladeng6666】—【Box2D系列教程 26】Box2D浮力效果

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

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

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

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


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


前些天有人问到Box2D如何实现浮力效果。今天我们就来学习一下。

Box2D浮力效果实现起来并不难。无非就是当刚体接触到水面时,对它施加一个向上的浮力。不过这个浮力受到刚体体积的影响,体积越大,收到的浮力也越大。同时还会因为受力点不在中心位置,而引起角度旋转。

额…。综合这些因素,用b2Body.ApplyForce实现起来似乎有些困难,所以我们要引入一个新的类:b2BuoyancyController。

b2BuoyancyController是b2Controller的一个子类,b2Controller类用来集成一些常用的功能,为用户免去复杂的算法。比如今天我们要学习的浮力效果,就可以用它的子类b2BuoyancyController来实现。

b2BuoyancyController和b2Body刚体不同。它是不可见的Box2D对象,也就是说,b2DebugDraw中不会绘制b2BuoyancyController的实例。但是当它与刚体发生碰撞时,Box2D会自动计算所浮力,并施加到刚体上,进而模拟漂浮效果。

b2BuoyancyController的构造函数非常简单,没有任何参数。

[Actionscript3] 纯文本查看 复制代码
var bc:b2BuoyancyController = new b2BuoyancyController();


它常用的公共属性有:
    normal:指定水面法向量的方向,也就垂直水面的方向,通常保持默认的(0,-1)不变。
    offset:指定水面的偏移量。注意它的方向与AS3中的y轴方向相反,也就是说如果我们想设置水面位置的y为200,那么offset属性应该是-200/30。
    density:设置水的密度。确切的讲,是设置液体介质的密度。我们知道,只有漂浮物的密度小于液体介质的密度时,才可以漂浮在该介质上。(当然,要讲到刚结构的轮船可以漂浮在水上,就要讲到排水量要大于轮船的重量上了,话题就扯远啦,就此打住。)
    linearDrag:设置漂浮物在水中移动的阻尼值。或者我们可以把它想象成水的粘稠度。这个属性值越大,漂浮物移动的速度越慢。
    angularDrag:设置漂浮物在水中旋转的阻尼值。
    velocity:设置水流动的速度。

b2BuoyancyController用起来也很简单,首先创建一个b2BuoyancyController实例。

[Actionscript3] 纯文本查看 复制代码
//实例化b2BuoyancyController对象
fuliController = new b2BuoyancyController();

然后设置它们的一些属性,比如水面的位置、方向、密度等等。
[Actionscript3] 纯文本查看 复制代码
//设置水面的法向量
fuliController.normal.Set(0, -1);
//设置水面的位置
fuliController.offset = -200 / m_physScale;
//设置水的密度,因为我们创建的刚体密度是3,所以水的密度要大于3
fuliController.density = 5.0;
//设置刚体在水中的移动阻尼
fuliController.linearDrag = 10;
//设置刚体在水中的旋转阻尼
fuliController.angularDrag = 6;

然后,将fuliController添加到b2world世界中
[Actionscript3] 纯文本查看 复制代码
//将水面、浮力控制器添加到世界中
world.AddController(fuliController);

创建刚体后,如果希望它与fuliController交互,实现漂浮效果,则用b2BanyancyController.AddBody方法,将漂浮物体添加到fuliController中
[Actionscript3] 纯文本查看 复制代码
//将刚体添加到水面上
fuliController.AddBody(body);

[Actionscript3] 纯文本查看 复制代码
是不是很简单?在下面的效果中,用鼠标拖动刚体,看看浮力的效果是不是很满意?!


完整的代码和注释如下:
[Actionscript3] 纯文本查看 复制代码
package  
{
        import Box2D.Common.Math.b2Vec2;
        import Box2D.Dynamics.b2Body;
        import Box2D.Dynamics.b2World;
        import Box2D.Dynamics.Controllers.b2BuoyancyController;
        import Box2D.Dynamics.Controllers.b2Controller;
        import flash.events.Event;
        import flash.events.MouseEvent;

        import flash.display.Sprite;
        /**
         * ...
         * @author ladeng6666
         */
        public class FuliTest extends Sprite
        {
                //声明世界变量
                private var world:b2World;
                //定义浮力控制器,也就是水面
                private var fuliController:b2BuoyancyController;
                //因为b2BuoyancyController是不可见的,所以我们专门为它定一个图层
                private var controllerLayer:Sprite;
                //像素和米的转换关系
                private const m_physScale:Number = 30;

                public function FuliTest() 
                {
                        //创建世界
                        initWorld();
                        //创建水面,浮力控制器
                        createController();
                        //创建刚体
                        for (var i:int = 0; i < 8; i++) {
                                createBodies();
                        }

                }

                private function createBodies():void 
                {
                        //创建刚体
                        var body:b2Body = LDEasyBox2D.createBox(world, Math.random()*400+50, Math.random()*50+30, Math.random()*20+30, Math.random()*20+30);
                        //将刚体添加到水面上
                        fuliController.AddBody(body);
                }
                //创建水面、即浮力控制器
                private function createController():void 
                {
                        //实例化b2BuoyancyController对象
                        fuliController = new b2BuoyancyController();
                        //设置b2BuoyancyController对象的一些基本属性
                        //设置水面的法向量
                        fuliController.normal.Set(0, -1);
                        //设置水面的位置
                        fuliController.offset = -200 / m_physScale;
                        //设置水的密度,因为我们创建的刚体密度是3,所以水的密度要大于3
                        fuliController.density = 5.0;
                        //设置刚体在水中的移动阻尼
                        fuliController.linearDrag = 10;
                        //设置刚体在水中的旋转阻尼
                        fuliController.angularDrag = 6;

                        //将水面、浮力控制器添加到世界中
                        world.AddController(fuliController);

                        //因为b2BuoyancyController是不可见的,所以要为水面添加一个图层,专门绘制水面
                        controllerLayer = new Sprite();
                        addChild(controllerLayer);

                        controllerLayer.graphics.lineStyle(1,0x0000ff,1);
                        controllerLayer.graphics.moveTo(0,200);
                        controllerLayer.graphics.lineTo(550,200);

                        controllerLayer.graphics.lineStyle();
                        controllerLayer.graphics.beginFill(0x0000ff,0.2);
                        controllerLayer.graphics.drawRect(0, 200, 550, 300);
                        controllerLayer.graphics.endFill();
                }

                private function initWorld():void 
                {
                        //创建b2World世界
                        world = LDEasyBox2D.createWorld();
                        addChild(LDEasyBox2D.createDebug(world));
                        LDEasyBox2D.createWrapWall(world, this);
                        LDEasyBox2D.stage = this;

                        addEventListener(Event.ENTER_FRAME, loop);
                        stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseEventHandler);
                        stage.addEventListener(MouseEvent.MOUSE_UP, mouseEventHandler);
                }
                private function mouseEventHandler(e:MouseEvent):void 
                {
                        //鼠标按下后拖动刚体,弹起后释放刚体
                        if (e.type == MouseEvent.MOUSE_DOWN) {
                                var body:b2Body = LDEasyBox2D.getBodyAtMouse(world);
                                if (body != null) {
                                        LDEasyBox2D.startDragBody(world, body);
                                }
                        }else if (e.type == MouseEvent.MOUSE_UP) {
                                LDEasyBox2D.stopDragBody(world);
                        }
                }
                private function loop(e:Event):void 
                {
                        LDEasyBox2D.updateWorld(world);
                }

        }

}



下载:
OK 2012-09-22 Box2D漂浮效果.rar (293.15 KB, 下载次数: 2)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

站长推荐 上一条 /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)



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