Home » Java » Desktop Java » JBox2D and JavaFX: Events and forces

About Toni Epple

JBox2D and JavaFX: Events and forces

In yesterdays samples you saw how you can create a simple world, and display it with WorldView, and how to provide custom Renderers. Now we’re going to add some user input. We’ll create a control that behaves like a flipper in a pinball machine.

To do that we’ll create a Joint. In JBox2D Joints are used to constrain bodies to the world or to each other. We’ll create a static circular Body that will serve as the axis for our flipper, and bind a Box to it via a RevoluteJoint.

To simplify the code, we’ll first define a JointBuilder base class and a RevoluteJointBuilder:

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);
 }
}

And here’s the RevoluteJointBuilder:

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;
 }

}

Now we can modify our HelloWorld-Example like this:

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();
 }
}

This will display our scene and you’ll see how the Joint prevents the dynamic Box from falling to the ground and how it constrains it’s movement.

The next step is to allow the user to control it. For this we’ll apply a force when the user presses a key. Add this after the instantiation of the scene:

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);
 }

}
 });

That’s it for now. In the next parts of this tutorial we’ll do a bit more custom rendering and create some nice custom Nodes.

Reference: Events and forces with JBox2D and JavaFX from our JCG partner Toni Epple at the Eppleton blog.

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you our best selling eBooks for FREE!

1. JPA Mini Book

2. JVM Troubleshooting Guide

3. JUnit Tutorial for Unit Testing

4. Java Annotations Tutorial

5. Java Interview Questions

6. Spring Interview Questions

7. Android UI Design

and many more ....

Leave a Reply

Your email address will not be published. Required fields are marked *

*


eight × 8 =

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Do you want to know how to develop your skillset and become a ...

Subscribe to our newsletter to start Rocking right now!

To get you started we give you our best selling eBooks for FREE!
Get ready to Rock!
To download the books, please verify your email address by following the instructions found on the email we just sent you.

THANK YOU!

Close