I know you didn't come here to see this, but some things are more important than computer games.
Don't show me this anymore!



Box2D JSON loader - b2dJson

Last edited: March 05 2012

Intro


It is often useful to be able to save the state of the Box2D world and reproduce it later, whether for loading a game level, a saved game, tuning the parameters of your simulation, or just simply for debugging. A common method for doing this is to loop through all the bodies, fixtures and joints in the world and write them to a text file.

XML is often the first choice of file format since it's easily loadable in many different languages. Likewise, JSON (javascript object notation) which is in many ways the successor to XML is also handy choice. On this page you will find details on 'b2dJson', a text file dump/load utility for Box2D worlds written in C++ and using JSON for formatting.


Features


The b2djson utility has two main functions. Firstly, it can take a b2World* pointer and convert it to a textual representation. This is essentially just one big string which you can pass around in your program as a string, or write to a file. The second function is the reverse of this - to take one of these strings and create a Box2D b2World from it. Along the way, there are other handy features which are also possible:
  • attach names to objects of interest in the world (joint, body, fixture)
  • replicate individual parts of the world (body, fixture)
Attaching a name to something in the world when you create the textual representation lets you get a reference to that object when you load the world again. Replicating parts of the world could be thought of as a rudimentary copy+paste feature.

b2dJson uses the lightweight jsoncpp to handle the actual JSON reading and writing in a very stress-free way - many thanks to the jsoncpp devs!


Basic usage


The b2djson utility is just one C++ class, which is typically used by declaring an instance in local scope and calling functions on this instance. To write a Box2D world to a file, you would do this:
1
2
  b2dJson json;
  json.writeToFile(myWorld, "myfile.json");
And to load the file you created, you would do this:
1
2
  b2dJson json;
  b2World* myWorld = json.readFromFile("myfile.json");
If you want to create a string with the same information that would have been written to the file, you can do this instead:
1
2
3
4
5
6
7
  b2dJson json;
  string mystring = json.writeToString(myWorld);
  
  //later...
  
  b2dJson json;
  b2World* myWorld = json.readFromString(mystring);
If the recreation of the world from the JSON data fails, each of the 'readFrom' functions will return null.


Retrieving objects of interest


If you want to attach names to certain objects of interest in the world, you will need to do that before you create the textual representation. You can attach names to joints, bodies and fixtures. Each object can have only one name. Multiple objects can have the same name. Here is an example:
1
2
3
4
5
6
7
8
9
10
11
12
13
  b2Joint* axleJoint;
  b2Body* carBody;
  b2Fixture* rearBumperFixture;
  b2Fixture* frontBumperFixture;
  
  b2dJson json;
  
  json.setJointName(axleJoint, "drive axle");
  json.setBodyName(carBody, "chassis");
  json.setFixtureName(rearBumperFixture, "bumper");
  json.setFixtureName(frontBumperFixture, "bumper");
  
  json.writeToFile(myWorld, "myfile.json");
Notice that we have given the same name to both bumpers. For this example, after you load the world from the JSON data you can retrieve the named objects like this:
1
2
3
4
5
6
7
8
9
10
  vector<b2Joint*> axleJoints;
  vector<b2Body*> carBodies;
  vector<b2Fixture*> bumperFixtures;
    
  b2dJson json;
  b2World* myWorld = json.readFromFile("myfile.json");
  
  json.getJointsByName("drive axle", axleJoints);
  json.getBodiesByName("chassis", carBodies);
  json.getFixturesByName("bumper", bumperFixtures);
In this example, this would result in a vector of two fixtures for the bumpers, because they had the same name.


Replicating objects using JSON


As well as saving and loading an entire world you can also make use of the 'piecewise' functions that b2dJson itself uses, to copy and replicate individual parts of the world. Specifically, you can copy bodies and fixtures. Here is an example of copying a body:
1
2
3
4
5
6
7
8
9
  b2Body* carBody;
  b2dJson json;
  Json::Value bodyValue = json.b2j( carBody );
  
  //later...
  
  b2World* myWorld;
  b2dJson json;
  b2Body* body = json.j2b2Body(myWorld, bodyValue);
You don't need to know what a Json::Value is, suffice to say it contains the same information that would be dumped to the text file, so when you recreate a body like this all the body's attributes, and all its fixtures with their attributes will be replicated. Replicating a fixture is similar, except the last step requires a body to attach the fixture to:
1
2
3
4
5
6
7
8
9
  b2Fixture* bumperFixture;
  b2dJson json;
  Json::Value fixtureValue = json.b2j( bumperFixture );
  
  //later...
  
  b2Body* carBody;
  b2dJson json;
  b2Fixture* myFixture = json.j2b2Fixture(carBody, fixtureValue);
This will 'paste' the fixture onto another body.


Other details


Although the files produced by this utility are text files and are somewhat human-readable and occasionally it can be handy to delve in there and cut bits out, the intention is not to edit these files manually.

By default, floating point values are written to JSON as their hex string representation to perfectly preserve the floating point value, as opposed to writing an ascii representation which can be rounded off and must be parsed back into a float when loading. If you do want to edit the files manually, you can set the b2dJson to use human readable values by passing true to the constructor like this:
1
2
  b2dJson json(true); //enable human-readable floats
  json.writeToFile(myWorld, "myfile.json");
Currently no consideration has been made for 64 bit... anythings.


Source code


The source code will work for v2.2.0 of Box2D.
You can download the b2dJson files individually here: b2dJson.h , b2dJson.cpp and get the supporting jsoncpp source from sourceforge separately.

You can download b2dJson and jsoncpp together here. This also includes the source code and .json files for the tests in the screenshots below.


Binary download


You can download a windows binary of the testbed including the b2dJson utility. This includes some neat test scenes using b2dJson to load JSON data, and you can use Ctrl+S and Ctrl+L to save and load a 'snapshot' of the current world in any of the regular tests, including your own. Just bear in mind that the filename 'snapshot.json' is hardcoded so if you want to save different scenes, you'll have to rename the file.

Each of the demos loads JSON data, and some of them do a little more, for example retrieving named objects or replicating existing bodies. See the source code of each test for comments on these methods.

View YouTube video
box2d b2djson demo raycast box2d b2djson demo raycast box2d b2djson demo raycast
box2d b2djson demo raycast