Box2D 关节——”马达关节” b2RevoluteJoint
昨天我们学习了 Box2D 的“距离关节”b2DistanceJoint,并用它模拟了一个简单的自行车。今天我们来学习”马达关节” b2RevoluteJoint 。
“马达关节”b2RevoluteJoint同样连接了两个刚体bodyA和bodyB。不过和”马达关节”不同的是,它只有一个节点anchor,所以两个刚体都只能围绕这一个节点选择。另外,我们可以在这个节点anchor位置施加一个作用力maxMotorTorque,这样节点就会想马达一样转起来,所以我把它叫做”马达关节”。
还是不好理解,对吧!那就再打个比方,我把b2RevoluteJoint关节比作….电风扇。风扇叶是bodyA,马达是anchor,底座是bodyB,下面的图可以更好的解释这一点:
如上图所示,因为节点anchor在bodyA的圆心处,所以bodyA会围绕着节点anchor旋转。
b2RevoluteJoint的initialize方法结构如下:
public function Initialize( bA:b2Body, bB:b2Body, anchor:b2Vec2 ) : void
bA即bodyA,bB即bodyB,anchor即节点,具体的功能,我在前面都讲过了,就不再赘述了。
另外,如前面提到的,通过设置b2RevoluteJointDef的maxMotorTorque、motorSpeed和enableMotor,可以模拟马达旋转。这三个参数的作用分别如下:
- enableMotor:决定是否使用motor
- motorSpeed:设置最大的角速度
- maxMotorTorque:要达到角速度应用的扭矩力
这三个属性是让节点转起来的必要条件,缺一不可!记住哦。
用b2RevoluteJoint实现风扇的效果如下:
完整的代码和注释如下:
package { import Box2D.Collision.Shapes.b2PolygonShape; import Box2D.Collision.Shapes.b2Shape; import Box2D.Common.Math.b2Vec2; import Box2D.Dynamics.b2Body; import Box2D.Dynamics.b2BodyDef; import Box2D.Dynamics.b2FixtureDef; import Box2D.Dynamics.b2World; import Box2D.Dynamics.Joints.b2RevoluteJoint; import Box2D.Dynamics.Joints.b2RevoluteJointDef; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.geom.Point; /** * http://www.ladeng6666.com * @author ladeng6666 */ public class RevoluteJointTest extends Sprite { private var world:b2World; private var debugSprite:Sprite; private var bodyA:b2Body, bodyB:b2Body; private var posA:Point, posB:Point; public function RevoluteJointTest() { LDEasyBox2D.stage = stage; world=LDEasyBox2D.createWorld(); debugSprite=LDEasyBox2D.createDebug(world); addChild(debugSprite); //创建地面, LDEasyBox2D.createWrapWall(world, stage); createBodies(); createRevoluteJoint(); addEventListener(Event.ENTER_FRAME, loop); stage.addEventListener(MouseEvent.MOUSE_DOWN, onStageMouseDown); stage.addEventListener(MouseEvent.MOUSE_UP, onStageMouseUp); } private function createRevoluteJoint():void { //创建马达关节需求 var revoluteJoint:b2RevoluteJointDef = new b2RevoluteJointDef(); //用bodyA、bodyB和anchor节点初始化马达关节 revoluteJoint.Initialize( bodyA, bodyB, new b2Vec2(posA.x / 30, posA.y / 30)); //设置连接的两个刚体之间不进行碰撞检测 revoluteJoint.collideConnected = false; //开启马达 revoluteJoint.enableMotor = true; //设置马达的最大角速度,单位为 弧度/秒,如设置为Math.PI,即每秒钟转180度 revoluteJoint.motorSpeed = Math.PI; //设置最大的扭力值 revoluteJoint.maxMotorTorque = 500; //创建马达关节 world.CreateJoint(revoluteJoint); } //创建bodyA和bodyB刚体 private function createBodies():void { //设置两个刚体的坐标位置 posA = new Point(275, 100); posB = new Point(275, 300); //创建一个十字刚体,赋值给bodyA var bodyDef:b2BodyDef = new b2BodyDef(); bodyDef.type = b2Body.b2_dynamicBody; bodyDef.position.Set(posA.x / 30, posA.y / 30); bodyA = world.CreateBody(bodyDef); //设置刚体属性 var fixtureDef:b2FixtureDef = new b2FixtureDef(); fixtureDef.density = 3; fixtureDef.restitution = .2; fixtureDef.friction = .2; //设置刚体形状,并赋值给fixtureDef //一个横着的矩形 var shape:b2PolygonShape = new b2PolygonShape(); shape.SetAsBox(50/30, 5/30); fixtureDef.shape = shape; bodyA.CreateFixture(fixtureDef); //加一个竖着的矩形 shape.SetAsBox(5 / 30, 50 / 30); fixtureDef.shape = shape; //生成刚体bodyA的形状 bodyA.CreateFixture(fixtureDef); //创建bodyB刚体 bodyB = LDEasyBox2D.createBox(world, posB.x, posB.y, 200, 50); } 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); } } }
代码中用到了我写的静态类LDEasyBox2D,可以有效的简化代码,具体请参考这里。
点击刚体,还可以进行拖动,如果对鼠标拖动刚体,我建议你看看之前的让刚体听我的——鼠标拖动刚体。
联系作者
一直关注着…………………………………………….顶一个
谢谢兄弟的支持!
拉登兄, 文中
//设置马达的最大角速度,单位为 弧度/秒,如设置为Math.PI,即每秒钟转180度
revoluteJoint.motorSpeed = Math.PI;
如果用以下代码代替应该也有类似的效果。
body.SetAngle(angle);
body.SetAngularVelocity(Math.PI);
另外,关于
motorSpeed:设置最大的角速度
maxMotorTorque:要达到角速度应用的扭矩力
motorSpeed设置角速度可以理解,那么maxMotorTorque和角速度到底有什么关系呢? 推动力还是阻力?我不太清楚这个属性的具体意义。
你设置角度的方法也是正确的。
关于maxMotorTorque是指要达到指定的角度的,可以施加的最大扭力。示例中,固定了底座,风扇可以转,但是固定了风扇,底座是不会绕着风扇转的,因为maxMotorTorque的力度不够,无法转动底座!
拉登大叔,您好,我是box2dweb新手,请问您有没有尝试在box2dweb中添加ropeJoint功能?