21

javascript のように Tiny Wings を実行しようとしています。

Box2D を使用した手法を最初に見ました。クロージャ Web バージョンを使用しています (メモリ リークの修正のため)。
要するに、曲線をポリゴンに分解して、次のようにします。

ここに画像の説明を入力

私も Chipmunk-js を試してみましたが、セグメント形状を使用して地面を次のようにシミュレートしています。

ここに画像の説明を入力

どちらの場合も、円が転がっているときに、ポリゴンまたはセグメント間の共通点で「クラッシュ」または「バンプ」が発生しています。

Chipmunk にそれについて尋ねたところ、著者は、この動作を減らすためにセグメントに radius プロパティを実装したと述べました。私は試してみましたが、確かにうまくいきましたが、完璧ではありません。まだいくつかの隆起があります (プラスの効果を得るには、半径を 30px に設定する必要がありました)。

「バンプ」は、2 つのポリゴン間の共有ポイントに追加されます。

バンプバグ

illandrilがに提案したように、円がエッジでクラッシュするのを避けるために、エッジング手法 (彼はポリゴン-ポリゴンの接触でのみテストしました) を使用します。

スロープエッジングテクニック

また、Lucが提案したように弾丸オプションを追加しようとしましたが、何も変わらないようです.

ここに問題のデモがあります。
チェックする値を変更してみることができます:

  • 弾丸オプション
  • エッジサイズ
  • 反復回数
  • 物理学

(最新の開発 Chrome でのみテスト済み) しばらく
お待ちください (または水平方向の重力を変更してください)。
ここに興味のあるレポがあります。

4

3 に答える 3

2

最良の解決策は、ゴースト頂点を持つエッジ形状ですが、使用しているバージョン/ポートでそれが利用できない場合、次善の策は、「エッジング」と呼ばれる質問の図のようですが、ポリゴンをさらに地下に非常に拡張しますこのスレッドのような浅い斜面: http://www.box2d.org/forum/viewtopic.php?f=8&t=7917

于 2013-02-25T15:25:06.763 に答える
1

最初は、隣接する 2 つのセグメント間の勾配の変化から問題が発生する可能性があると考えていましたが、ポリゴンの平らな表面にはまだ隆起があるため、問題はむしろポリゴンの角にぶつかっていると思います。

互いに重なり合う 2 つのポリゴン セットを設定できるかどうかわかりません。同じ補間計算を使用して、以下の図のようにポリゴンの 2 番目のセットを生成するだけです。赤のポリゴン セットを構築し、緑のポリゴンの左側の頂点を赤いポリゴンの中央に設定して緑のセットを追加します。次の赤いポリゴンの真ん中にある右の頂点。

![図][1]

これは凹状の曲線で機能するはずです...まあ、とにかく凸状のものの上を飛んでいるはずです。

これがうまくいかない場合は、多数のポリゴンを設定して斜面を構築してみてください。多角形の幅には、円の半径の 10 分の 1 を使用します。これにより、勾配の不連続が減少するはずです。

- 編集

Box2D.js の 5082 行目 (少なくともこのレポ内) には、マニホールド (ポリゴンが衝突したときに雪玉が衝撃を受ける方向) が正しいかどうかを確認するためにオーバーライドできる PreSolve(contact, manifest) 関数があります。

そのためには、マニホールド ベクトルを復元し、それをカーブの法線と比較する必要があります。そのように見えるはずです(正確ではないかもしれません):

Box2D.Dynamics.b2ContactListener.prototype.PreSolve = function (contact, oldManifold) {
    // contact instanceof Box2D.Dynamics.Contacts.b2Contact == true
    var localManifold, worldManifold, xA, xB, man_vect, curve_vect, normal_vect, angle;
    localManifold = contact.GetManifold();

    if(localManifold.m_pointCount == 0)
        return; // or raise an exception

    worldManifold = new Box2D.Collision.b2WorldManifold();
    contact.GetWorldManifold( worldManifold );

    // deduce the impulse direction from the manifold points
    man_vect = worldManifold.m_normal.Copy();

    // we need two points close to & surrounding the collision to compute the normal vector
    // not sure this is the right order of magnitude
    xA = worldManifold.m_points[0].x - 0.1;
    xB = worldManifold.m_points[0].x + 0.1;

    man_vect.Normalize();

    // now we have the abscissas let's get the ordinate of these points on the curve
    // the subtraction of these two points will give us a vector parallel to the curve

    var SmoothConfig;

    SmoothConfig = {
        params: {
            method: 'cubic',
            clip: 'mirror',
            cubicTension: 0,
            deepValidation: false
        },
        options: {
            averageLineLength: .5
        }
    }
    // get the points, smooth and smooth config stuff here
    smooth = Smooth(global_points,SmoothConfig);

    curve_vect = new Box2D.Common.Math.b2Vec2(xB, smooth(xB)[1]);
    curve_vect.Subtract(new Box2D.Common.Math.b2Vec2(xA, smooth(xA)[1]));

    // now turn it to have a normal vector, turned upwards
    normal_vect = new Box2D.Common.Math.b2Vec2(-curve_vect.y, curve_vect.x);
    if(normal_vect.y > 0)
        normal_vect.NegativeSelf();
    normal_vect.Normalize();
    worldManifold.m_normal = normal_vect.Copy();

    // and finally compute the angle between the two vectors
    angle = Box2D.Common.Math.b2Math.Dot(man_vect, normal_vect);

    $('#angle').text("" + Math.round(Math.acos(angle)*36000/Math.PI)/100 + "°");
    // here try to  raise an exception if the angle is too big (maybe after a few ms)
    // with different thresholds on the angle value to see if the bumps correspond
    // to a manifold that's not normal enough to your curve 
};
于 2012-05-20T15:36:30.897 に答える
0

この問題は Box2D 2.2.0 で解決されたと思います。マニュアルのセクション 4.5「エッジ形状」を参照してください。

問題は、これが 2.2.0 バージョンの機能であり、chainshape とともに、box2dweb が実際には 2.2.1a から移植されたものであることです。box2dweb-closure についてはわかりません。

Box2D.Collision.b2Collision.CollidePolygonAndCircle を変更して試したことはすべて、不安定な動作になりました。少なくとも一部の時間 (例: ボールがランダムな方向にぶつかるが、ボールがゆっくり転がる場合のみ)。

于 2012-06-24T18:31:44.730 に答える