I’ve just started playing around with box2dweb and have now run into a problem that is leaving me stumped.
I have a basic simulation with a “ground” static fixture and some code that allows me to add shapes (just circles for now) to the canvas at the point where I click on it.
My code is working in as far as I can add as many circles to the canvas as I want and have them drawn on the canvas.
I then have a button that begins the simulation by entering the step loop. I would expect that when I click the button, the circles would fall to the “ground” and eventually come to rest, thereby ending the simulation.
The problem is that as soon as I begin the simulation, the very next frame completely removes all the fixtures in the scene. However, if I start out with a circle in the scene (not added by click, but by the initialization function that creates the world and the ground), and I begin the simulation, it runs as expected: the circle drops at some rate and stops on the “ground”.
I’m using the same function addCircle() to add the circle at either the initialization of the scene or when I click on the canvas, so it seems like that code is fine.
// this function is called by the canvas onclick
function addShape(e) {
var shape = $('input:radio[name=shape]:checked').val();
var offset = $("#c").offset();
if (shape == "circle") {
addCircle((e.pageX - offset.left) / SCALE,
(e.pageY - offset.top) / SCALE,
$("#dimen").val());
}
gWorld.DrawDebugData();
}
// same function is used by the above handler and also to set up a circle
// in the initial scene, however when added via click, the simulation
// breaks (all objects disappear in the next frame)
function addCircle(x, y, r) {
var fixDef = new b2FixtureDef;
fixDef.density = 1.0;
fixDef.friction = 0.5;
fixDef.restitution = 0.2;
var bodyDef = new b2BodyDef;
bodyDef.type = b2Body.b2_dynamicBody;
bodyDef.position.x = x;
bodyDef.position.y = y;
fixDef.shape = new b2CircleShape(r);
gWorld.CreateBody(bodyDef).CreateFixture(fixDef);
}
// called when a button to start the simulation is clicked
function startSimulation() {
gWorld.SetGravity(new b2Vec2(0, parseInt($("#gravity").val())));
gStopped = false;
requestAnimFrame(update);
}
// this is the main step loop
function update() {
if (!gStopped) {
gWorld.Step(
1 / 60 //frame-rate
, 10 //velocity iterations
, 10 //position iterations
);
gWorld.DrawDebugData();
gWorld.ClearForces();
var keepGoing = true;
for (var b = gWorld.GetBodyList(); keepGoing && b; b = b.m_next) {
if (! b.IsAwake()) {
keepGoing = false;
}
}
if (keepGoing) {
requestAnimFrame(update);
}
}
function init() {
gWorld = new b2World(
new b2Vec2(0, parseInt($("#gravity").val())),
true);
var fixDef = new b2FixtureDef;
fixDef.density = 1.0;
fixDef.friction = 0.5;
fixDef.restitution = 0.2;
//create ground
var bodyDef = new b2BodyDef;
bodyDef.type = b2Body.b2_staticBody;
bodyDef.position.x = $("#c").width() / 2 / SCALE;
bodyDef.position.y = $("#c").height() / SCALE;
fixDef.shape = new b2PolygonShape;
fixDef.shape.SetAsBox((600 / SCALE) / 2, (10/SCALE) / 2);
gWorld.CreateBody(bodyDef).CreateFixture(fixDef);
//setup debug draw
var debugDraw = new b2DebugDraw();
debugDraw.SetSprite(document.getElementById("c").getContext("2d"));
debugDraw.SetDrawScale(SCALE);
debugDraw.SetFillAlpha(0.3);
debugDraw.SetLineThickness(1.0);
debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
gWorld.SetDebugDraw(debugDraw);
// this circle is simulated correctly
addCircle(1,1,1);
gWorld.DrawDebugData();
}
I’ve found that the problem was in lines like these:
When I changed this to the following, the simulation began to run as normal: