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.

Related Whitepaper:

Java Essential Training

Author David Gassner explores Java SE (Standard Edition), the language used to build mobile apps for Android devices, enterprise server applications, and more!

The course demonstrates how to install both Java and the Eclipse IDE and dives into the particulars of programming. The course also explains the fundamentals of Java, from creating simple variables, assigning values, and declaring methods to working with strings, arrays, and subclasses; reading and writing to text files; and implementing object oriented programming concepts. Exercise files are included with the course.

Get it Now!  

Leave a Reply


× 5 = twenty five



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.

Sign up for our Newsletter

15,153 insiders are already enjoying weekly updates and complimentary whitepapers! Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

As an extra bonus, by joining you will get our brand new e-books, published by Java Code Geeks and their JCG partners for your reading pleasure! Enter your info and stay on top of things,

  • Fresh trends
  • Cases and examples
  • Research and insights
  • Two complimentary e-books