Box2D JSON loader - b2dJson
Last edited: March 05 2012Intro
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)
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"); |
1 2 | b2dJson json; b2World* myWorld = json.readFromFile("myfile.json"); |
1 2 3 4 5 6 7 | b2dJson json; string mystring = json.writeToString(myWorld); //later... b2dJson json; b2World* myWorld = json.readFromString(mystring); |
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"); |
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); |
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); |
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); |
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"); |
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
|
|
|
| ||