Hello Everyone,
Over the course of the next few weeks we would be covering the topic of using Box2d for physics in your libgdx app/game. In our recently released Android Game – Balloon Shooter we used Box2d for all the physics. Box2d is awesome in handling all the physics and gives realistic results. Integrating is not that difficult also. For more information regarding Box2d you can check their site Box2D where they also have a documentation which covers mostly everything you would require to make an awesome physics game.
There are many ways to use box2d in your game and the following method is one of the many methods you can use.
World:
In box2d all the objects exist in a world which has to be created before the objects.
The syntax for world requires to give two arguments -> Vector2 Gravity and Boolean allowSleep. Gravity as the name suggests is to give a gravitational force to all the objects in the world. You can also give a horizontal force (like a wind) if need arises. AllowSleep is usually set to true as it saves computations when objects in the game are stationary and not having any collisions, so usually we set it to true.
World world=new World(new Vector2(0,-20),true)
Here we used negative y value for gravity because in libgdx the y coordinate value decreases as we go down the screen.
Body & Fixture:
In box2d there are two parts of a physics objects -> a body and a fixture. Body is an invisible part which has information like position,velocity,angle etc. Fixture is the physical shape which is attached to the body to give it properties like mass, friction, restitution etc.
Body:
Firstly box was made with MKS (Metre, Kg, Second) units in mind, so it is not the best practice to have 1pixel equivalent to 1m in box2d. So we create constants to convert all the pixel units to physics one and vice versa.
static final float WORLD_TO_BOX=0.01f; static final float BOX_WORLD_TO=100f; float ConvertToBox(float x){ return x*WORLD_TO_BOX; }
For creating a body we need to have reference to the World object. Also for creating a body we first create a BodyDef object which store properties like position,angle and use it to create a body as shown below.
public void CreateBody(World world,Vector2 pos,float angle){ BodyDef bodyDef = new BodyDef(); bodyDef.type = bodyType; bodyDef.position.set(ConvertToBox(pos.x),ConvertToBox(pos.y)); bodyDef.angle=angle; body = world.createBody(bodyDef); }
Fixture/Shapes:
Now the body is made we have to attach a physical shape to it i.e. a Fixture. We first define a PolygonShape and give it dimenstions of width and height. As it takes half width and half height as arguments we divide both of them by 2. Then we create a FixtureDef object to hold information like density,restitution (the constant which defines collision is elastic or inelastic whose value ranges from 0.0 to 1.0. 1 being elastic and more than 1 will give really odd results),shape etc. Then we attach a fixture to the body by calling body.createFixture(FixtureDef fd).
private void MakeRectFixture(float width,float height,BodyDef.BodyType bodyType, float density,float restitution, Vector2 pos,float angle){ PolygonShape bodyShape = new PolygonShape(); float w=ConvertToBox(width/2f); float h=ConvertToBox(height/2f); bodyShape.setAsBox(w,h); FixtureDef fixtureDef=new FixtureDef(); fixtureDef.density=density; fixtureDef.restitution=restitution; fixtureDef.shape=bodyShape; body.createFixture(fixtureDef); bodyShape.dispose(); }
Adding a circle shape is similar to rectangle just that the shape type would be a CircleShape and not a PolygonShape and we would have to give a radius to it rather than width and height.
void MakeCircleFixture(float radius,BodyDef.BodyType bodyType, float density,float restitution, Vector2 pos,float angle){ FixtureDef fixtureDef=new FixtureDef(); fixtureDef.density=density; fixtureDef.restitution=restitution; fixtureDef.shape=new CircleShape(); fixtureDef.shape.setRadius(BoxObjectManager.ConvertToBox(radius)); body.createFixture(fixtureDef); fixtureDef.shape.dispose(); }
World Update Fixed TimeStep:
In this way a body can be created and fixtures can be attached to it. Finally to update the physics we have to call step function of world object to update it for the delta time passed. Shown below is a function to update the physics which should be called in the game’s main update function.
static final float BOX_STEP=1/120f; static final int BOX_VELOCITY_ITERATIONS=8; static final int BOX_POSITION_ITERATIONS=3; float accumulator; public void Update(float dt){ accumulator+=dt; while(accumulator>BOX_STEP){ world.step(BOX_STEP,BOX_VELOCITY_ITERATIONS,BOX_POSITION_ITERATIONS); accumulator-=BOX_STEP; } }
You can test with different values for the above three constants to see which works best for you. The above values were used in our game – Balloon Shooter. It is good to use a constant value for udpating physics because usually rendering is slower than physics and frames per second can be variable depending on what is being drawn on the screen. So what we do is have a constant udpate time for physics which is usually more than the render udpate time. So every frame we add the time in a variable called accumulator and the loop the phyics the number of times to update with the render timestep. This is not exactly the best method to do it but it worked for us so we kept it as shown above. There is a post which describes in a really detailed manner on how to have a fixed timestep to update physics.
Though bodies are created still you wont see anything on the screen as we haven’t attached any texture to the bodies.
This we will do in the next tutorial.
Thank you for the patience. Please leave any queries/suggestions/feedback in comments section. We look forward to hearing from you.
Oh!!! I really needed this, thank you!!! Can i translate your post to spanish, i have my blog about libgdx Development too
Sure go ahead, but don’t forget to link our blog 🙂
Of Course! Thanks!
hey u are not the this site’s admin! ¬¬