JavaFX and JBox2D

                   JAVAFX  AND JBOX2D (GAME ENGINE)

Recently i was searching for the best 2d game engine API for java and i came across this blog  talking  about jbox2d ,I downloaded the api  jbox2d .To work around pixel conversion between jbox2d and javafx i decided to use the utility class from this project.

Utility Class Tweaking
This my utility class.

public class Utils {

    //Create a JBox2D world.
    public static final World world = new World(new Vec2(0.0f, -10.0f));
   
    //Screen width and height
    public static final int WIDTH = 800;
    public static final int HEIGHT = 600;
   
    //Convert a JBox2D x coordinate to a JavaFX pixel x coordinate
    public static float toPixelPosX(float posX) {
        float x = WIDTH*posX / 100.0f;
        return x;
    }

    //Convert a JavaFX pixel x coordinate to a JBox2D x coordinate
    public static float toPosX(float posX) {
        float x =   (posX*100.0f*1.0f)/WIDTH;
        return x;
    }
   
    //Convert a JBox2D y coordinate to a JavaFX pixel y coordinate
    public static float toPixelPosY(float posY) {
        float y = HEIGHT - (1.0f*HEIGHT) * posY / 100.0f;
        return y;
    }
   
    //Convert a JavaFX pixel y coordinate to a JBox2D y coordinate
    public static float toPosY(float posY) {
        float y = 100.0f - ((posY * 100*1.0f) /HEIGHT) ;
        return y;
    }
   
    //Convert a JBox2D width to pixel width
    public static float toPixelWidth(float width) {
        return WIDTH*width / 100.0f;
    }
   
    //Convert a JBox2D height to pixel height
    public static float toPixelHeight(float height) {
        return HEIGHT*height/100.0f;
    }

}

The walls

public ImageView walls(int x,int y,int width,int height){
    
        ImageView wall=new ImageView("file:wall.png");
        wall.setFitWidth(Utils.toPixelWidth(width));
        wall.setFitHeight(Utils.toPixelHeight(height));
        wall.setLayoutX(Utils.toPixelPosX(x)); 
        wall.setLayoutY(Utils.toPixelPosY(y));
        
        BodyDef bd = new BodyDef();
        bd.position.set(x,y);
       
  
        PolygonShape ps = new PolygonShape();
        ps.setAsBox(width,height);

        FixtureDef fd = new FixtureDef();
        fd.shape = ps;
        
        Body body = Utils.world.createBody(bd);
        body.createFixture(fd);
        wall.setUserData(body);
      
        return wall;
}
The Tennis
public ImageView ball(int x,int y){
   
        ImageView ball=new ImageView("file:tennis.png");
        ball.setSmooth(true);
        ball.setCache(true);


        ball.setLayoutX(Utils.toPixelPosX(x));
        ball.setLayoutY(Utils.toPixelPosY(y));
       
        BodyDef bd = new BodyDef();
        bd.type = BodyType.DYNAMIC;
        bd.position.set(x,y);
       
        CircleShape cs = new CircleShape();
        cs.m_radius = 20*0.1f;
       
        FixtureDef fd = new FixtureDef();
        fd.shape = cs;
        fd.density = 0.9f;
        fd.friction = 0.3f;      
        fd.restitution = 0.6f;
       
        Body body = Utils.world.createBody(bd);

        body.createFixture(fd);
        ball.setUserData(body);
        return ball;

}
Bounce Sound

public void onContact(){

     AudioClip audio=new AudioClip("file:tennis_bounce.mp3");
 
      Utils.world.setContactListener(new ContactListener(){

          @Override
          public void beginContact(Contact cntct) {

           //produce sound if in contact with the walls

            if(cntct.m_fixtureA.m_shape.m_type==ShapeType.POLYGON){
         
                 audio.play();
             
             }
           
          }

          @Override
          public void endContact(Contact cntct) {
             
          }

          @Override
          public void preSolve(Contact cntct, Manifold mnfld) {
       
          }

          @Override
          public void postSolve(Contact cntct, ContactImpulse ci) {
   
          }
         
      });
    }
Timeline
      ImageView c []=new ImageView[BALL_COUNT];
   
       for(int i=0;i<BALL_COUNT;i++){
            c[i]=ball(r.nextInt(90)+5,r.nextInt(400)+100);
           

       }
        Timeline timeline = new Timeline();
        timeline.setCycleCount(Timeline.INDEFINITE);
       

        Duration duration = Duration.seconds(1.0/60.0);
     
        EventHandler<ActionEvent> ae = new EventHandler<ActionEvent>() {
            public void handle(ActionEvent t) {
           
                    Utils.world.step(1.0f/60.0f, 3, 8);

                    for(int i=0;i<BALL_COUNT;i++) {
                       
                            Body body = (Body)c[i].getUserData();
                            float xpos = Utils.toPixelPosX(body.getPosition().x);
                            float ypos = Utils.toPixelPosY(body.getPosition().y);
                           
                            c[i].setLayoutX(xpos);
                            c[i].setLayoutY(ypos);
                           
                            onContact();
                 
                       }
                     
           }
        };

        KeyFrame frame = new KeyFrame(duration, ae, null,null);

        timeline.getKeyFrames().add(frame);


        timeline.playFromStart();

ScreenShot

javafx_jbox2d image
Video Demo




Comments

  1. The balls don't bounce that well off the floor or the right hand wall. For the floor they sink in a little and for the right hand wall they clearly bounce before making contact. Have you found a way to fix that? They do seem to bounce realistically of the left hand side wall though. I've noticed this from watching the video.

    ReplyDelete

Post a Comment

Popular Posts