0

ユーザーがソケットを介してオブジェクトを制御するサーバー側の物理実験に取り組んでいます。ユーザーがオブジェクトを世界の境界の外に移動すると、私が直面している問題が発生します。

経由でインストールされた Box2Djs を使用していnpmます。

ワールド 500x500 を作成し、次のリスナーをアタッチします。

var boundaryListener = new b2d.b2BoundaryListener();
boundaryListener.Violation = function (body) {
    //we will move this body to the opposite side
    var position = body.GetWorldCenter();
    //snap to opposite side
    if (position.x < 0) {
        position.x = worldAABB.upperBound.x + position.x;
    }
    if (position.y < 0) {
        position.y = worldAABB.upperBound.y + position.y;
    }
    if (position.x > worldAABB.upperBound.x) {
        position.x -= worldAABB.upperBound.x;
    }
    if (position.y > worldAABB.upperBound.y) {
        position.y -= worldAABB.upperBound.y;
    }

    body.m_flags = body.m_flags & (~b2d.b2Body.e_frozenFlag); //does nothing :(
}
this.world.SetBoundaryListener(boundaryListener);

worldAABB世界が境界として使用するb2AABBです。

問題は、境界リスナーが起動されると、フラグが allowSleep、frozen、および island フラグである 22 に設定されることに気付いたことです。b2Body がワールド境界の外を通過すると、凍結されているように見えます。最後の行は、内部フラグをいじって体の凍結を解除しようとする試みですが、私はそれを行う方法が間違っているとはっきりと感じています。

どうすれば体を解凍できますか?私が見ることができる凍結フラグをクリアする関数はありません (javascript は 10,000 行を超えているため、正直なところすべてを読んでいません)。いくつかのボディを壁として配置しても効果がないようです (ユーザーのオブジェクトがすぐに通過します)。彼ら)。

私の壁は次のように作成されます:

//create walls
var wallShape = new b2d.b2PolygonDef();
wallShape.SetAsBox(500, 10);
wallShape.density = 0.0;
wallShape.friction = 0.3;

var bodyDef = new b2d.b2BodyDef();
bodyDef.position.Set(250, 20);
var north = this.world.CreateBody(bodyDef);
north.CreateShape(wallShape);

bodyDef = new b2d.b2BodyDef();
bodyDef.position.Set(250, 499);
var south = this.world.CreateBody(bodyDef);
south.CreateShape(wallShape);

bodyDef = new b2d.b2BodyDef();
bodyDef.position.Set(499,250);
bodyDef.angle = Math.PI / 2;
var east = this.world.CreateBody(bodyDef);
east.CreateShape(wallShape);

bodyDef = new b2d.b2BodyDef();
bodyDef.position.Set(1, 250);
bodyDef.angle = Math.PI / 2;
var west = this.world.CreateBody(bodyDef);
west.CreateShape(wallShape);

これを修正する方法についての洞察はありますか? ウェブサイトが指しているフラッシュのドキュメント(半分の時間は一致しません)とフリーズについてさえ話していないC ++のドキュメントを除いて、javascriptでBox2Dを使用することについて私が見つけることができるドキュメントはほとんどありません。

世界には重力がなく、すべてのオブジェクトに線形および角度の減衰があることを言及することはおそらく役立つでしょう (疑似空間の感覚であるはずです)。

4

1 に答える 1

0

Box2Djs のソースを調査したところ、次のことがわかりました。ステップごとに、Box2Djs はボディがワールド境界内にあるかどうかをチェックします。ボディが範囲外にある場合、「フリーズ」します。つまり、衝突検出から除外されます。このコードがあります (Body.js 行 414):

Freeze: function(){
    this.m_flags |= b2Body.e_frozenFlag;
    this.m_linearVelocity.SetZero();
    this.m_angularVelocity = 0.0;

    for (var s = this.m_shapeList; s != null; s = s.m_next)
    {
        s.DestroyProxy();
    }
}

注意してください、このチェックはすべての時間ステップ(b2Island.js 244) で実行されます。したがって、境界リスナーで e_frozenFlag を設定すると、何も実行されず、次のタイム ステップでフラグが設定されます。さらに、体が凍結した後、その速度が失われ、その形状は広い段階でプロキシを失います (上記のコードからわかるように)。プロキシが自動的に復元されないように見えるため、フラグをリセットするだけでは不十分です。

また、Box2Djs インターフェイスまたはボディを解凍するためのロジックのどこにも見つかりませんでした。Box2Djs の内部である BroadPhase にアクセスする必要があるため、これを手動で行うのは一種の汚いトリックです。さらに、体が凍ると速度が低下するため、役に立ちません。しかし、私が見るように、体を動かし続ける必要があります。

解決策は次です。ワールド境界の外に移動した後もボディをシミュレーションに保持するには、ボディのフリーズをまったく防止する必要があります。次のトリックでできるかもしれません。まず、大きな値でワールド境界を設定します。次に、接触リスナーを設定し、体が壁に触れたときに境界違反ロジックを実行します。

C++ で連絡先リスナーを設定する方法については、 https : //www.iforce2d.net/b2dtut/collision-callbacks を参照してください。

于 2013-02-05T09:39:19.200 に答える