Для этого мы создадим Джойнт. В JBox2D суставы используются для привязки тел к миру или друг к другу. Мы создадим статическое круглое тело, которое будет служить осью для нашего флиппера, и свяжем с ним ящик с помощью RevoluteJoint.
Чтобы упростить код, мы сначала определим базовый класс JointBuilder и RevoluteJointBuilder:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
public abstract class JointBuilder, T extends JointDef> { protected World world; protected T jointDef; protected JointBuilder(World world, T jointDef) { this .world = world; this .jointDef = jointDef; } public K bodyA(Body a) { jointDef.bodyA = a; return (K) this ; } public K bodyB(Body b) { jointDef.bodyB = b; return (K) this ; } public K userData(Object userData) { jointDef.userData = userData; return (K) this ; } public K type(JointType type) { jointDef.type = type; return (K) this ; } public K collideConnected( boolean coco) { jointDef.collideConnected = coco; return (K) this ; } public Joint build() { return world.createJoint(jointDef); } } |
А вот RevoluteJointBuilder:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
public class RevoluteJointBuilder extends JointBuilder { public RevoluteJointBuilder(World world, Body a, Body b, Vec2 anchor) { super (world, new RevoluteJointDef()); jointDef.initialize(a, b, anchor); } public RevoluteJointBuilder enableLimit( boolean enable) { jointDef.enableLimit = enable; return this ; } public RevoluteJointBuilder enableMotor( boolean motor) { jointDef.enableMotor = motor; return this ; } public RevoluteJointBuilder localAnchorA(Vec2 localAnchorA) { jointDef.localAnchorA = localAnchorA; return this ; } public RevoluteJointBuilder localAnchorB(Vec2 localAnchorB) { jointDef.localAnchorB = localAnchorB; return this ; } public RevoluteJointBuilder lowerAngle( float lowerAngle) { jointDef.lowerAngle = lowerAngle; return this ; } public RevoluteJointBuilder maxMotorTorque( float maxMotorTorque) { jointDef.maxMotorTorque = maxMotorTorque; return this ; } public RevoluteJointBuilder motorSpeed( float motorSpeed) { jointDef.motorSpeed = motorSpeed; return this ; } public RevoluteJointBuilder referenceAngle( float referenceAngle) { jointDef.referenceAngle = referenceAngle; return this ; } public RevoluteJointBuilder upperAngle( float upperAngle) { jointDef.upperAngle = upperAngle; return this ; } } |
Теперь мы можем изменить наш HelloWorld-пример следующим образом:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
public class HelloWorld extends Application { public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage primaryStage) { World world = new World( new Vec2( 0 , -2f), true ); primaryStage.setTitle( "Hello World!" ); NodeManager.addCircleProvider( new MyNodeProvider()); new CircleBuilder(world).userData( "ball" ).position( 0 .1f, 4 ).type(BodyType.DYNAMIC).restitution( 1 ).density( 2 ).radius(.15f).friction(.3f).build(); final Body flipperBody = new BoxBuilder(world).position( 0 , 2 ).type(BodyType.DYNAMIC).halfHeight(.02f).halfWidth(.2f).density( 2 ).friction( 0 ).userData( "flipper" ).build(); Vec2 axis = flipperBody.getWorldCenter().add( new Vec2(.21f, 0 )); Body axisBody = new CircleBuilder(world).position(axis).type(BodyType.STATIC).build(); new RevoluteJointBuilder(world, flipperBody, axisBody, axis).upperAngle(.6f).lowerAngle(-.6f) .enableMotor( true ).enableLimit( true ).maxMotorTorque(10f).motorSpeed(0f).build(); Scene scene = new Scene( new WorldView(world, 200 , 400 , 50 ), 500 , 600 ); // ground new BoxBuilder(world).position( 0 , -1f).halfHeight( 1 ).halfWidth( 5 ).build(); primaryStage.setScene(scene ); primaryStage.show(); } } |
Это отобразит нашу сцену, и вы увидите, как сустав предотвращает падение динамического бокса на землю и как он ограничивает его движение.
Следующий шаг — позволить пользователю управлять им. Для этого мы будем применять силу, когда пользователь нажимает клавишу. Добавьте это после создания экземпляра сцены:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
scene.setOnKeyPressed( new EventHandler() { @Override public void handle(KeyEvent ke) { if (ke.getCode() == KeyCode.LEFT) { flipperBody.applyTorque(-15f); } } }); scene.setOnKeyReleased( new EventHandler() { @Override public void handle(KeyEvent ke) { if (ke.getCode() == KeyCode.LEFT) { flipperBody.applyTorque(15f); } } }); |
Это все на данный момент. В следующих частях этого урока мы сделаем немного больше пользовательского рендеринга и создадим несколько хороших пользовательских узлов.
Ссылка: События и силы с JBox2D и JavaFX от нашего партнера JCG Тони Эппла в блоге Eppleton .