书名:代码本色:用编程模拟自然系统
作者:Daniel Shiffman
译者:周晗彬
ISBN:978-7-115-36947-5
目录
5.11 Box2D关节
1)旋转关节
- 旋转关节用一个锚点将两个物体连接在一起,这个锚点有时候称作“枢轴点”。
- 旋转关节还有一个“角度”用于描述物体间的相对转动。
-
创建旋转关节的方法和创建距离关节一样。
图5-11
2)创建旋转关节的方法
- 步骤1:确保有两个物体
假设我们有两个盒子对象,每个盒子对象分别有一个指向Box2D物体对象的引用。
Box box1 = new Box();
Box box2 = new Box();
- 步骤2:定义关节
现在,我们需要创建一个RevoluteJointDef对象。
RevoluteJointDef rjd = new RevoluteJointDef();
- 步骤3:配置关节的属性
旋转关节最关键的属性就是连接的物体和物体之间的共同锚点(也就是它们相互连接的位置),这几个属性都通过initialize()函数设置。
rjd.initialize(box1.body, box2.body, box1.body.getWorldCenter());
函数的前两个参数指定了两个物体对象,最后一个参数指定了锚点,本例的锚点位于第一个物体的中央。
RevoluteJoint还有一个令人激动的特性,你可以加上驱动马达,让它自主旋转。比如:
rjd.enableMotor = true; 开启马达
rjd.motorSpeed = PI*2; 设置马达的速度
rjd.maxMotorTorque = 1000.0; 设置马达的强度
- 在程序运行过程中,你可以关闭或者开启这个驱动马达。
- 最后,旋转关节的旋转程度可以被限制在两个角度之间。(默认情况下,它可以旋转360度,也就是2π弧度。)
rjd.enableLimit = true;
rjd.lowerAngle = -PI/8;
rjd.upperAngle = PI/8;
- 步骤4:创建关节
RevoluteJoint joint = (RevoluteJoint) box2d.world.createJoint(rjd);
把上述所有步骤放在一个类中,我们把这个类叫做风车类(Windmill),它的作用是用旋转关节将两个物体连接在一起。在本例中,box1物体的密度等于0,因此只有box2会绕着锚点旋转。
3)示例
示例代码5-7 旋转的风车
class Windmill {
RevoluteJoint joint; 风车对象(Windmill)由两个Box对象和一个关节组成
Box box1;
Box box2;
Windmill(float x, float y) {
// Initialize positions of two boxes
box1 = new Box(x, y-20, 120, 10, false); 在本例中,Box类需要一个布尔参数决定Box对象是固定的
box2 = new Box(x, y, 10, 40, true);
// Define joint as between two bodies
RevoluteJointDef rjd = new RevoluteJointDef();
rjd.initialize(box1.body, box2.body, box1.body.getWorldCenter());
关节将两个物体连在一起,锚点在第一个物体的中央
// Turning on a motor (optional)
rjd.motorSpeed = PI*2; // how fast? 这是一个马达
rjd.maxMotorTorque = 1000.0; // how powerful?
rjd.enableMotor = false; // is it on?
// There are many other properties you can set for a Revolute joint
// For example, you can limit its angle between a minimum and a maximum
// See box2d manual for more
// Create the joint
joint = (RevoluteJoint) box2d.world.createJoint(rjd);创建关节
}
// Turn the motor on or off
void toggleMotor() {开启或关闭马达
joint.enableMotor(!joint.isMotorEnabled());
}
boolean motorOn() {
return joint.isMotorEnabled();
}
void display() {
box2.display();
box1.display();
// Draw anchor just for debug
Vec2 anchor = box2d.coordWorldToPixels(box1.body.getWorldCenter());
fill(0);
noStroke();
ellipse(anchor.x, anchor.y, 8, 8);
}
}