box2dwebをいじり始めたばかりですが、問題が発生して困惑しています。
「地面」の静的フィクスチャと、クリックしたポイントでキャンバスに形状(今のところは円だけ)を追加できるコードを使用した基本的なシミュレーションがあります。
私のコードは、必要な数の円をキャンバスに追加して、それらをキャンバスに描画できる範囲で機能しています。
次に、ステップループに入ってシミュレーションを開始するボタンがあります。ボタンをクリックすると、円が「地面」に落ちて、やがて静止し、シミュレーションが終了すると思います。
問題は、シミュレーションを開始するとすぐに、次のフレームでシーン内のすべてのフィクスチャが完全に削除されることです。ただし、シーン内の円から始めて(クリックではなく、世界と地面を作成する初期化関数によって追加)、シミュレーションを開始すると、期待どおりに実行されます。円は一定の速度で低下し、 「地面」で止まります。
同じ関数addCircle()
を使用して、シーンの初期化時またはキャンバスをクリックしたときに円を追加しているので、そのコードは問題ないようです。
// 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();
}