4 minutes
Dart Box2D Fundamentals: Worlds
Worlds
The concept of a world in Box2D is something we briefly went through, it is the main parent of all the Box2D bodies. Whenever you create or delete a body, you call a method on a world. A world is quite important in Box2D, and you can do the following things with it:
- Set the gravity of the world.
- Tune the physics simulation to your own liking.
- Finding fixtures in a given area.
- Casting rays and get intersected fixtures.
For now you don’t have to worry about the last two as we will cover them in a later article, we will just go into the first two and the whole life cycle of a world. We have been using the setup from the Setup article and it has been handling everything surrounding the world for us. You might have seen the _world
property that we have been using. So instead of making another example, we will take a look at how our current setup does it.
You can get an instance of a World by either using one of its factory constructors or the main constructor. The following ways exists to construct a world:
- The
World.withGravity
factory, which handles everything a part from the gravity for you. - The
World.withPool
factory, expects you to pass both aVector2
for gravity, and aWorldPool
. - The
World.withPoolAndStrategy
factory, expects the same as theWorld.withPool
but you also have to pass collision strategy. - The
World
constructor, which is expects the same asWorld.withPoolAndStrategy
but instead of a strategy, you pass a strategy buffer.
You are probably wondering what a pool or strategy is, well simply put a pool is the data structure for all the bodies and is used to pull and store bodies efficiently. And the strategy is what Box2D will use for collision detection, the exact details about them are also unknown for me but in most cases you can just skip the last three ways of construction and just use the World.withGravity
:
...
Box2DAndFlame() {
var gravity = Box2D.Vector2(0, 9.81); // Normal earth gravity.
_world = Box2D.World.withGravity(gravity);
...
Source: /examples/worlds/lib/main.dart
The gravity affects all dynamic typed bodies in the world, and we can change it at run-time. Lets say we don’t want any gravity at all:
...
_world.setGravity(Box2D.Vector2(0, 0));
...
Source: /examples/worlds/lib/main.dart
If you applied this to one of the previous examples we went through you will see that the bodies are just staying put.
To allow the world to update and change things we have to call the stepDt
method. This method runs the physics simulations, our current setup does so in the update
method:
...
@override
void update(double delta) {
var velocityIterations = 8; // How strongly to correct velocity.
var positionIterations = 3; // How strongly to correct position.
_world.stepDt(delta, velocityIterations, positionIterations);
}
...
Source: /examples/setup/lib/main.dart
Every time our update
method is called we advance the physics simulation by the given delta value. This effects movements of objects, gravity and collision. You can play with the delta value to see how it affects the speed of the simulation.
The velocity iterations and position iterations are used for body collision, especially in how they react and how Box2D will solve an overlapping problem with two bodies by using these values in its calculations. If you set these values highers your simulation will run more precise but at the cost of performance, so if you want to tweak them keep that in mind.
If you want to know more about what they do internally I suggest reading the last part of https://www.iforce2d.net/b2dtut/worlds, the Update 2013/1/20 section. I think he explains it better than I could ever do without bluntly copying it. The same behavior applies to the dart version.
Previous: 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.