title: Box2D can't understand the way it works - libgdx
body: <p>I'm trying to play around with Box2D in libgdx but unfortunately I can't seem to understand the way it works.</p>
  
  <p>Here are a few examples that drive me crazy:</p>
  
  <p>.1. It is known that Box2D works with meters. Everybody knows that. Then, why I getting results by Pixels? For instance, if I define some body definition and I set the position to 0,1, It draws the related fixture/sprite at the bottom-left corner of the screen! I thought the 0,0 point in Box2D is at the center of the screen.</p>
  
  <p>.2. Another problem that I have been struggling to understand and solve is the values of the Shapes, Joints and other stuff. Let's start with the shapes: I defined a Polygon shape like this:</p>
  
  <pre><code>shape.setAsBox(1, 2);
  </code></pre>
  
  <p>Now the shape was supposed to be 2 <strong>meters</strong> wide and 4 <strong>meters</strong> height, but it's not the case. What I got is a super small shape.</p>
  
  <p>And lastly, the values of the joints. I defined a body with a polygon shape and a ground body. Now I "pinned" those two to the center of the ground body using the Revolute Joint, with the goal to create some sort of a catapult that rotates nicely within a certain range.</p>
  
  <p>Now I defined also a Mouse Joint so I could drag the catapult(the polygon shape) back and forth nicely, but it seems that I need to set the maxForce of the joint to an enormous value so I can actually see movement/rotation of the catapult! I don't understand. All this matter should be operated by small values, with regard to the values I had to set up.</p>
  
  <p>Here is my very basic code that contains all of the above. Please tell me what I'm doing wrong, I'm freaking out here:</p>
  
  <p>GameScreen.java</p>
  
  <pre><code>package com.david.box2dpractice;
  
  import com.badlogic.gdx.Gdx;
  import com.badlogic.gdx.Screen;
  import com.badlogic.gdx.graphics.GL20;
  import com.badlogic.gdx.graphics.OrthographicCamera;
  import com.badlogic.gdx.graphics.Texture;
  import com.badlogic.gdx.graphics.g2d.Sprite;
  import com.badlogic.gdx.graphics.g2d.SpriteBatch;
  import com.badlogic.gdx.math.Vector2;
  import com.badlogic.gdx.physics.box2d.Body;
  import com.badlogic.gdx.physics.box2d.BodyDef;
  import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer;
  import com.badlogic.gdx.physics.box2d.ChainShape;
  import com.badlogic.gdx.physics.box2d.FixtureDef;
  import com.badlogic.gdx.physics.box2d.PolygonShape;
  import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
  import com.badlogic.gdx.physics.box2d.World;
  import com.badlogic.gdx.physics.box2d.joints.RevoluteJointDef;
  import com.badlogic.gdx.utils.Array;
  
  public class GameScreen implements Screen{
  
      private Box2DDebugRenderer debugRenderer;
      private Texture texture;
      private Sprite sprite;
      private Sprite tempSprite;
      private SpriteBatch batch;
      private Body arm , ground;
      private World world;
      public OrthographicCamera camera;
      private RevoluteJointDef jointDef;
      private Array&lt;Body&gt; tempBodies;
  
      public GameScreen() {
          debugRenderer = new Box2DDebugRenderer();
          batch = new SpriteBatch();
          texture = new Texture(Gdx.files.internal("catapult_arm.png"));
          camera = new OrthographicCamera();
          camera.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
          tempBodies = new Array&lt;Body&gt;();
      }
      @Override
      public void render(float delta) {
          // TODO Auto-generated method stub
          Gdx.gl.glClearColor(0, 0, 0, 0);
          Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
          batch.setProjectionMatrix(camera.combined);
          world.getBodies(tempBodies);
          batch.begin();
          for(Body body : tempBodies) {
              if(body.getUserData() != null &amp;&amp; body.getUserData() instanceof Sprite) {
                  tempSprite = (Sprite) body.getUserData();
                  tempSprite.setPosition(body.getPosition().x-tempSprite.getWidth()/2, body.getPosition().y-tempSprite.getHeight()/2);
                  tempSprite.setRotation((float) Math.toDegrees(body.getAngle()));
                  tempSprite.draw(batch);
              }
          }
          batch.end();
          debugRenderer.render(world, camera.combined);
          world.step(1/60f, 6, 2);
      }
  
      @Override
      public void resize(int width, int height) {
          // TODO Auto-generated method stub
          Gdx.app.log("System", "resize() was invoked");
      }
  
      @Override
      public void show() {
          // TODO Auto-generated method stub
          Gdx.app.log("System", "show() was invoked");
          world = new World(new Vector2(0,0), true);
          sprite = new Sprite(texture);
          BodyDef bodyDef = new BodyDef();
          bodyDef.position.set(Gdx.graphics.getWidth()/2,Gdx.graphics.getHeight()/2+sprite.getHeight()/2);
          bodyDef.type = BodyType.DynamicBody;
  
          // The shape
          PolygonShape shape = new PolygonShape();
          shape.setAsBox(11, 91);
  
          // The fixture
          FixtureDef fixtureDef = new FixtureDef();
          fixtureDef.shape = shape;
          fixtureDef.density = .10f;
          arm = world.createBody(bodyDef);
          arm.createFixture(fixtureDef);
          sprite.setOrigin(sprite.getWidth()/2, sprite.getHeight()/2);
          arm.setUserData(sprite);
          shape.dispose();
  
          bodyDef = new BodyDef();
          bodyDef.position.set(Gdx.graphics.getWidth()/2,Gdx.graphics.getHeight()/2);
          bodyDef.type = BodyType.StaticBody;
  
          ChainShape shape2 = new ChainShape();
          shape2.createChain(new Vector2[] {new Vector2(-20*Pixels_To_Meters,0),new Vector2(20*Pixels_To_Meters,0)});
  
          // The fixture
          fixtureDef.shape = shape2;
          fixtureDef.restitution = .65f;
          fixtureDef.friction = .75f;
          ground = world.createBody(bodyDef);
          ground.createFixture(fixtureDef);
          shape2.dispose();
          // joint
          jointDef = new RevoluteJointDef();
          jointDef.bodyA = arm;
          jointDef.bodyB = ground;
          jointDef.localAnchorB.set(ground.getLocalCenter());
          jointDef.localAnchorA.set(arm.getLocalCenter().x,arm.getLocalCenter().y-sprite.getHeight()/2);
          jointDef.enableLimit = true;
          jointDef.enableMotor = true;
          jointDef.motorSpeed = 15;
          jointDef.lowerAngle = (float) -Math.toRadians(75);
          jointDef.upperAngle = (float) -Math.toRadians(9);
          jointDef.maxMotorTorque = 4800;
          world.createJoint(jointDef);
          Gdx.input.setInputProcessor(new InputHandler(arm,ground,world,camera));
      }
  
      @Override
      public void hide() {
          // TODO Auto-generated method stub
          Gdx.app.log("System", "hide() was invoked");
          dispose();
      }
  
      @Override
      public void pause() {
          // TODO Auto-generated method stub
          Gdx.app.log("System", "pause() was invoked");
      }
  
      @Override
      public void resume() {
          // TODO Auto-generated method stub
          Gdx.app.log("System", "resume() was invoked");
      }
  
      @Override
      public void dispose() {
          // TODO Auto-generated method stub
          Gdx.app.log("System", "dispose() was invoked");
          texture.dispose();
          batch.dispose();
          world.dispose();
      }
  }
  </code></pre>
  
  <p>InputHandler.java</p>
  
  <pre><code>package com.david.box2dpractice;
  
  import com.badlogic.gdx.InputProcessor;
  import com.badlogic.gdx.graphics.OrthographicCamera;
  import com.badlogic.gdx.math.Vector2;
  import com.badlogic.gdx.math.Vector3;
  import com.badlogic.gdx.physics.box2d.Body;
  import com.badlogic.gdx.physics.box2d.Fixture;
  import com.badlogic.gdx.physics.box2d.QueryCallback;
  import com.badlogic.gdx.physics.box2d.World;
  import com.badlogic.gdx.physics.box2d.joints.MouseJoint;
  import com.badlogic.gdx.physics.box2d.joints.MouseJointDef;
  
  public class InputHandler implements InputProcessor{
  
      Body ground;
      MouseJoint mouseJoint;
      MouseJointDef mouseJointDef;
      World world;
      Vector2 target,initialPos;
      Vector3 temp;
      QueryCallback query;
      OrthographicCamera camera;
      boolean firstTime = true;
      public InputHandler(Body arm, Body ground, final World world, OrthographicCamera camera) {
          this.camera = camera;
          this.ground = ground;
          this.world =  world;
          mouseJointDef = new MouseJointDef();
          target = new Vector2();
          temp = new Vector3();
          mouseJointDef.bodyA = ground;
          mouseJointDef.collideConnected = true;
          mouseJointDef.maxForce = 9000;
          query = new QueryCallback() {
  
              @Override
              public boolean reportFixture(Fixture fixture) {
                  // TODO Auto-generated method stub
                  if(!fixture.testPoint(temp.x, temp.y))
                      return true;
                  if(firstTime) {
                      initialPos = new Vector2(fixture.getBody().getPosition().x,fixture.getBody().getPosition().y);
                      firstTime = false;
                  }
                  mouseJointDef.bodyB = fixture.getBody();
                  mouseJointDef.target.set(temp.x,temp.y);
                  mouseJoint = (MouseJoint) world.createJoint(mouseJointDef);
                  return false;
              }
          };
      }
      @Override
      public boolean keyDown(int keycode) {
          // TODO Auto-generated method stub
          return false;
      }
  
      @Override
      public boolean keyUp(int keycode) {
          // TODO Auto-generated method stub
          return false;
      }
  
      @Override
      public boolean keyTyped(char character) {
          // TODO Auto-generated method stub
          return false;
      }
  
      @Override
      public boolean touchDown(int screenX, int screenY, int pointer, int button) {
          // TODO Auto-generated method stub
          camera.unproject(temp.set(screenX, screenY, 0));
          world.QueryAABB(query, temp.x, temp.y, temp.x, temp.y);
          return true;
      }
  
      @Override
      public boolean touchUp(int screenX, int screenY, int pointer, int button) {
          // TODO Auto-generated method stub
          if(mouseJoint == null) 
              return false;
          mouseJoint.setTarget(initialPos);
          world.destroyJoint(mouseJoint);
          mouseJoint = null;
          firstTime = true;
          return true;
      }
  
      @Override
      public boolean touchDragged(int screenX, int screenY, int pointer) {
          // TODO Auto-generated method stub
          if(mouseJoint == null)
              return false;
          camera.unproject(temp.set(screenX, screenY, 0));
          mouseJoint.setTarget(target.set(temp.x, temp.y));
          return true;
      }
  
      @Override
      public boolean mouseMoved(int screenX, int screenY) {
          // TODO Auto-generated method stub
          return false;
      }
  
      @Override
      public boolean scrolled(int amount) {
          // TODO Auto-generated method stub
          return false;
      }
  
  }
  </code></pre>
  
  <p>If you could help me out here I would really really appreaciate that. Thanks!!</p>