9RIA-ladeng6666 发表于 2018-2-6 14:24:40

【9RIA—ladeng6666】—【Box2D系列教程 19】Box2D关节——”距离关节”b2DistanceJoint


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


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


在上一篇文章中,我们初步认识了Box2D中的b2Joint关节类。今天我们开始学习具体的Box2D关节类,即b2Joint的子类。首先我们从b2DistanceJoint类开始。

b2DistanceJoint关节,从它的名字可以猜到距离关节的作用:通过固定长度的关节将两刚体联系到一起,使这两个刚体始终保持一定的距离。可以像想象的出来吗?如果这样解释很难理解,那就想想自行车吧。把自行车的两个轱辘当成刚体,车架就是关节,两个轱辘可以自由的旋转,但是因为有车架的限制,两个轱辘之间始终保持一定的距离。


了解了b2DistanceJoint的定义,下面我们来看看创建过程。在初认识Box2D中的b2Joint关节类中,我们知道所有的关节都可以用initialize方法来创建,b2DistanceJoint也不例外,它的initialize方法结构如下:
        public function Initialize(
                bA:b2Body,
                bB:b2Body,
                anchorA:b2Vec2,
                anchorB:b2Vec2) : void

方法的每个参数功能如下:
    bA:即bodyA,关节连接的一个刚体。
    bB:即bodyB,关节连接的另一个刚体。
    anchorA:关节的端点A,通常为bodyA的中心位置。
    anchorB:关节的端点B,通常为bodyB的中心位置。
结合上图来看,两个车轮分别表示b2Distance的连接的两个刚体bA和bB,车轮中的两个红点分别表示关节的两个控制点,即车轮的中心点。

另外还可以用关节的collideConnected属性,设置关节连接的两个刚体之间是否进行碰撞检测。

在下面的示例中,我创建了两个大小不一的圆形刚体,大的为bodyA,小的为bodyB,选择右上角的radio选项,设置A或B为静态刚体,或者两个刚体都是动态刚体,同时给bodyA添加一个角速度,就成了一个简单的”自行车”。

attach://874.swf

完整的代码和注释如下:
package
{
        import Box2D.Common.Math.b2Vec2;
        import Box2D.Dynamics.b2Body;
        import Box2D.Dynamics.b2World;
        import Box2D.Dynamics.Joints.b2DistanceJoint;
        import Box2D.Dynamics.Joints.b2DistanceJointDef;
        import com.bit101.components.Panel;
        import com.bit101.components.RadioButton;
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.MouseEvent;
        import flash.geom.Point;

        /**
       * http://www.ladeng6666.com
       * @author ladeng6666
       */
        public class DistanceJointTest extends Sprite
        {
                private var world:b2World;
                private var debugSprite:Sprite;
                private var bodyA:b2Body, bodyB:b2Body;
                private var posA:Point, posB:Point;

                private var joint:b2DistanceJoint;

                public function DistanceJointTest()
                {
                        //设置Box2D舞台
                        LDEasyBox2D.stage = stage;
                        //用LDEasyBox2D快速创建世界
                        world=LDEasyBox2D.createWorld();
                        debugSprite=LDEasyBox2D.createDebug(world);
                        addChild(debugSprite);

                        //创建地面,
                        LDEasyBox2D.createWrapWall(world, stage);
                        //添加事件侦听器
                        addEventListener(Event.ENTER_FRAME, loop);
                        stage.addEventListener(MouseEvent.MOUSE_DOWN, onStageMouseDown);
                        stage.addEventListener(MouseEvent.MOUSE_UP, onStageMouseUp);

                        //创建关节连接的两个刚体
                        createBodies();
                        //创建关节
                        createDistanceJoint();
                        //设置右上角的UI
                        setUI();
                }

                private function createDistanceJoint():void
                {
                        //声明关节需求
                        var distanceJoint:b2DistanceJointDef = new b2DistanceJointDef();
                        //实例化关节需求
                        distanceJoint.Initialize(bodyA, bodyB, new b2Vec2(posA.x/30,posA.y/30), new b2Vec2(posB.x/30, posB.y/30));
                        distanceJoint.collideConnected = false;
                        //创建关节
                        joint=world.CreateJoint(distanceJoint) as b2DistanceJoint;
                }

                private function createBodies(staticA:Boolean=false,staticB:Boolean=false):void
                {
                        //设置连接刚体的坐标
                        posA = new Point(100, 100);
                        posB = new Point(200, 100);
                        //用LDEasyBox2D静态类创建两个刚体
                        bodyA = LDEasyBox2D.createCircle(world, posA.x, posA.y, 30, staticA);
                        //给刚体A添加一个角速度,这样可以做一个简单的自行车
                        bodyA.SetAngularVelocity(30/ 180 * Math.PI*30);
                        bodyB = LDEasyBox2D.createCircle(world, posB.x, posB.y, 10, staticB);

                }

                private function onStageMouseDown(e:MouseEvent):void
                {
                        //鼠标点击后,首先获取鼠标位置的刚体
                        var dragBody:b2Body = LDEasyBox2D.getBodyAtMouse(world);
                        //如果鼠标点击到了刚体
                        if (dragBody != null) {
                                //则开始拖动刚体
                                LDEasyBox2D.startDragBody(world,dragBody,10000*dragBody.GetMass());
                        }

                }

                private function onStageMouseUp(e:MouseEvent):void
                {
                        //鼠标弹起后,停止拖动刚体
                        LDEasyBox2D.stopDragBody(world);
                }

                private function loop(e:Event):void
                {
                        LDEasyBox2D.updateWorld(world);
                        //把下面的注释去点,看看更有趣的效果
                        //bodyA.ApplyTorque(5*bodyA.GetMass());
                }

                private function setUI():void {
                        var panel:Panel = new Panel(stage, 400, 30);
                        panel.width = 100;
                        panel.height = 60;
                        var radio1:RadioButton = new RadioButton(panel, 5, 5, "no static", true,onRadioChange);
                        var radio2:RadioButton = new RadioButton(panel, 5, 25, "bodyA is static", false,onRadioChange);
                        var radio3:RadioButton = new RadioButton(panel, 5, 45, "bodyB is static", false,onRadioChange);
                }

                private function onRadioChange(e:Event):void
                {
                        world.DestroyBody(bodyA);
                        world.DestroyBody(bodyB);
                        world.DestroyJoint(joint);

                        switch(e.target.label) {
                                case "no static":
                                        createBodies();
                                        break;
                                case "bodyA is static":
                                        createBodies(true);
                                        break;
                                case "bodyB is static":
                                        createBodies(false, true);
                                        break;
                        }
                        createDistanceJoint();
                }
        }

}

代码中用到了我写的静态类LDEasyBox2D。

点击刚体,还可以进行拖动,如果对鼠标拖动刚体,我建议你看看之前的让刚体听我的——鼠标拖动刚体。

页: [1]
查看完整版本: 【9RIA—ladeng6666】—【Box2D系列教程 19】Box2D关节——”距离关节”b2DistanceJoint

感谢所有支持论坛的朋友:下面展示最新的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)