7 minutes
Dart Box2D Fundamentals: Bodies
Bodies
Bodies are basically the properties of an object, they are not what you see or interact with but they define what kind of body your object has.
A body can exist out of the following basic properties:
- Mass, how heavy your object is.
- Velocity, how fast and in which direction your object is moving.
- Rotational inertia, how much resistance your object has while spinning, aka how much effort it takes to start or stop spinning.
- Angular velocity, how fast your object is rotating, and in which direction.
- Location, the position of your object.
- Angle, which way your object is facing.
But these properties do not describe what the object looks like or how it will interact when colliding with other objects. For that we need to use fixtures, but that is a subject for the next article. For now we are going to create a body and set some basic properties and see how they work.
Body creation
Bodies are created by setting up a definition(BodyDef
), and by using this definition we can create the body itself. The definition can be reused, this is useful if you have many bodies that you want to create.
Add a body definition to our Box2DAndFlame
constructor:
...
var bodyDef = Box2D.BodyDef();
bodyDef.type = Box2D.BodyType.DYNAMIC; // The body type.
bodyDef.position = Box2D.Vector2(100, 100); // The position of the body.
bodyDef.angle = 0; // The angle of the body.
...
Source: /examples/bodies/lib/main.dart
This is a basic body definition. All of the properties you see here are optional but these are the ones you will use the most. We haven’t provided a mass because we do that by adding fixtures to the body. More on this in the next step.
As you might have noticed we are also setting the body type to dynamic
, this means that the body is movable and can be interacted with. More on this and other body types later.
Now we can use this definition to create the actual body instance:
...
var dynamicBody =
_world.createBody(bodyDef); // Add the bodyDef to the world.
...
Source: /examples/bodies/lib/main.dart
As mentioned in the previous article the _world
is a Box2D.World
instance, and controls our objects. Like creation and deletion of physics objects. We now have a body thanks to the createBody
method, but the body is just a physics object so if you would run the game you wont see anything yet.
So lets give the body a size and shape. We do that by adding fixtures to the body, adding fixtures will affect the mass of the body. In the next article we will talk more about the fixture but for now we wil just add one simple square fixture to the body:
...
var boxShape = Box2D.PolygonShape();
boxShape.setAsBox(10, 10, Box2D.Vector2(10, 20), 0);
var boxFixtureDef = Box2D.FixtureDef();
boxFixtureDef.shape = boxShape;
boxFixtureDef.density = 1;
dynamicBody.createFixtureFromFixtureDef(boxFixtureDef);
...
Source: /examples/bodies/lib/main.dart
Most of the this code can be ignored but notice the density
and the setAsBox
, the density
is multiplied by the area of the fixture to calculate its mass, and it then becomes the mass of the body. And the setAsBox
defines our shape, the first two parameters are the half width and half height of the box. So our objet becomes a 20x20 sized box. The third parameter is the center position, where to position it in our world. And the last parameter is the angle of rotation.
When you run the program now you will see a small box falling downwards, and since it is a dynamic body it will be affected by gravity and will move out of the way or rotate when it hits another object.
Playing around with body properties
Now that we have a little box we can try some of those properties mentioned at the beginning of the article, lets try and change the position and angle using setTransform
:
...
dynamicBody.setTransform(Box2D.Vector2(130, 80), 1);
...
Source: /examples/bodies/lib/main.dart
This will transform the body to the left by 130 units, and from the top 130 units. And rotate it by 1 radian counter-clockwise. Box2D uses radians for all angle related methods and properties, so if you prefer using degrees instead of angles you use the following: degrees * (pi / 180)
.
Lets also set the angular and linear velocity of our body like so:
...
dynamicBody.linearVelocity = Box2D.Vector2(-5, 5);
dynamicBody.angularVelocity = -2;
...
Source: /examples/bodies/lib/main.dart
This will move our body up and left by 5 units per cycle, and rotate it 2 radian per cycle clockwise.
Static bodies
Now we have a moving body, lets add a static one and see what it does. And since we already have both the definition for a body and a fixture, we can reuse them and just change a few properties:
...
bodyDef.type = Box2D.BodyType.STATIC; // Change the body type to STATIC.
bodyDef.position =
Box2D.Vector2(100, 200); // Change the position to be sllightly lower.
var staticBody =
_world.createBody(bodyDef); // Once again add the bodyDef to the world.
staticBody
.createFixtureFromFixtureDef(boxFixtureDef); // And add our fixture.
...
Source: /examples/bodies/lib/main.dart
We didn’t change the square fixture at all, we just reused it. If you run the game now you will see another box in the scene, but this one wont move at all. A static body is not affected by physics, setting the velocity properties wont have any effect on it.
Kinematic bodies
And finally we have a kinematic body. We know that dynamic bodies move, we know that static bodies don’t move. And when those two collide the dynamic body will always move out of the way, and the static one will stay in place. A kinematic body follows the same principles as a static body, with the exception that a kinematic body can move.
Setting up a kinematic body:
...
bodyDef.type =
Box2D.BodyType.KINEMATIC; // Now we change the body type to KINEMATIC.
bodyDef.position =
Box2D.Vector2(60, 200); // Change the position once again.
var kinematicBody =
_world.createBody(bodyDef); // Add the bodyDef to the world.
kinematicBody
.createFixtureFromFixtureDef(boxFixtureDef); // And add our fixture.
kinematicBody.angularVelocity = -0.5;
...
Source: /examples/bodies/lib/main.dart
Reading the property values of a body
Reading the values of a property is quite useful when you are in your update or rendering state:
...
Box2D.Vector2 position =
dynamicBody.position; // A simple getter that returns the position.
double angle = dynamicBody.getAngle(); // A method that returns the angle.
Box2D.Vector2 linearVelocity =
dynamicBody.linearVelocity; // Another getter for the linear velocity.
double angularVelocity =
dynamicBody.angularVelocity; // Getter of the angular velocity.
...
Source: /examples/bodies/lib/main.dart
Note: As you might have noticed the API is not consistent, it uses getters/setters and other times there are explicit set/get methods. This is because it was ported over from java version, but the v1.0.0 release will make the API more inline with the Dart philosophy, when that happens I will update the articles and their respective examples.
If you wish to transform your object by changing only the angle and not the position, you can do that like so:
body.setTransform(body.position, newAngle);
Looping over the bodies in the world
If you want to do something with all your bodies, for instance for rendering as we are doing in the example, you can do that. Just use the forEachBody
method:
...
_world.forEachBody((body) {
// Do something with 'body'.
});
...
Source: /examples/bodies/lib/main.dart
And finally, destruction!
When you are done with your body, you can destroy it. Destroying it will remove it from the world and it wont be able to influence the rest of your physics objects:
_world.destroyBody(dynamicBody);
Destroying a body will also remove all the fixtures and joints attached to it.
Previous: Setup • Next up: Fixtures
See Dart Box2D Fundamentals series for all the articles.
Author: The explanations and code examples are based on https://www.iforce2d.net/b2dtut, I highly suggests to read those articles as well.