Sample Example of generating rotation for Box2d Bodies created from Tiled Map Editor in LibGDX [SOLVED]

By | December 26, 2015

Tiled is a map/level editor tool used for developing levels for games. In previous articles( Introduction, Terrain Tutorial) we have already learnt how to use this tool.

Box2d is a 2D physics engine. You can learn more about box2d here.

In this article we will look at a very common problem faced when a Box2d Body created using Tiled Map Editor. This is a problem specific to the rotation of the objects. When a simple rectangle is drawn in Object Layer of Tiled Editor. If this rectangle is used to create a Box2d body, it will draw the object positioned at the expected position. But if we provide non-zero rotation to the object in Tiled Editor, we will see that there is no rotation applied by Box2d itself.

So we will have to manually provide a rotation to the object in our code. Lets look at the differences between coordinate systems of Tiled & Box2d before we go further.

 

Differences in Box2d and Tiled:

  • The origin  is located at the top left corner of the map in Tiled while its located at the bottom left corner in Box2d world.
  •  Centre of rotation is different in Tiled when compared to Box2d. In Box2d, a body is always rotated with respect to its local centre i.e centre position of the body. While in Tiled, when we rotate an object, it will rotate around the top left corner of the object.

If we use TmxMapLoader().load() method provided by LibGDX to load our Tiled map, then the difference in origin is handled automatically by LibGDX, but the rotation has to be provided manually.

We will use the inbuilt method named setTransformation() of Box2d Body to set the rotation and position of the object.

Algorithm for the Fix:

  • Get the position and angle of rotation from the Tiled Object and convert rotation in radians.
  • Rotate the box2d body at its local centre.
  • Find the position of the object if it is rotated with respect to its top-left corner.
  • Move the body to that newly calculated position.

Hence by using above algorithm we can achieve the desired rotation provided by us in Tiled Map Editor.

Lets see the coding part for our algorithm :

public static void rotateObject(Body body, float x1, float y1, float width1,
			float height1, float rotation,float PPM) {

                float DEGTORAD = 0.0174532925199432957f;
		// Top left corner of object
		Vector2 pos = new Vector2((x1) / PPM, (y1 + height1) / PPM);
		// angle of rotation in radians
		float angle = DEGTORAD * (rotation);
		// half of diagonal for rectangular object
		float radius = (float) ((Math
				.sqrt((width1 * width1 + height1 * height1))) / 2f) / PPM;
		// Angle at diagonal of rectangular object
		double theta = (Math.tanh(height1 / width1) * DEGTORAD);

                 // Finding new position if rotation was with respect to top-left corner of object.  
		// X=x+ radius*cos(theta-angle)+(h/2)cos(90+angle)
		// Y= y+radius*sin(theta-angle)-(h/2)sin(90+angle)
		pos = pos.add((float) (radius * Math.cos(-angle + theta)),
				(float) (radius * Math.sin(-angle + theta))).add(
				(float) ((height1 / PPM / 2) * Math.cos(90 * DEGTORAD
						+ angle)),
				(float) (-(height1 / PPM / 2) * Math.sin(90
						* DEGTORAD + angle)));
		// transform the body
		body.setTransform(pos, -angle);

	}
/* NOTE ------------
PPM = Pixel per meter (Example: PPM=100)
x1 = x position of object fetched from Tiled.
y1 = y position of object fetched from Tiled.
width1 = width of object fetched from Tiled.
height1 = height of object fetched from Tiled.
rotation = angle (in degrees) of rotation of object fetched from Tiled.
*/

The above method can simply be used to rotate any Box2d body. The parameters for the method are already explained in the comments below the function definition. Now Lets look at the sample usage of the above method.

Sample Example:


float x1 = (Float) map_object.getProperties().get("x");
float y1 = (Float) map_object.getProperties().get("y");
float width1 = (Float) map_object.getProperties().get("width");
float height1 = (Float) map_object.getProperties().get("height");
float rotation = map_object.getProperties().get("rotation", 0.0f, Float.class);

//----------Rotating the Box2d body---------
rotateObject(body, x1, y1, width1, height1, rotation,100); 

 

Thanks. I hope this article was useful.

1,528 total views, 3 views today

(Visited 523 times, 1 visits today)