3

私はRabbytライブラリを調べ始めましたが、これまでのところ、pygletと組み合わせて使用​​することを本当に楽しんでいます。

ライブラリに実装されていないように見えることの1つは、スプライト間のピクセル完全衝突検出です。それを実装するには2つの問題があります。

まず、スプライトのテクスチャをロードするためにpygletを使用していますが、テクスチャからビットマスクを取得する方法がわかりません(私の非常に限られたOpenGLの知識が主な問題です)。BufferImageMaskはAbstractImageインスタンスから取得されているようですが、テクスチャ自体からは取得されていないようです。それを行う正しい方法は何ですか?

第二に、実際の衝突検出アルゴリズムを実装するためのさまざまな方法は何ですか?私がこれまで読んだことはすべて次のようになっているので、私は主に方法/バリエーションがあるかどうかに興味があります:

衝突検出アルゴリズム@gamedev.net

重要な情報を見逃さないようにしています。アルゴリズム自体はしっかりしています。

前もって感謝します!

PS私はPython2.7でコーディングしていますが、実際のピクセル完全衝突検出アルゴリズムをCで実装し、それを拡張機能として使用したいと思います。

アップデート

回転していないスプライトでピクセルパーフェクトな衝突検出を機能させることができました。

    r1 = collision[entity1].aabb
    r2 = collision[entity2].aabb
    sprite1 = renderable[entity1].sprite
    sprite2 = renderable[entity2].sprite
    ri = r1.intersect(r2)


    offx1, offy1 = int(ri.left - r1.left), int(ri.top - r1.top)
    offx2, offy2 = int(ri.left - r2.left), int(ri.top - r2.top)

    d1 = sprite1.texture.get_image_data().get_data('A', sprite1.texture.width)
    d2 = sprite2.texture.get_image_data().get_data('A', sprite2.texture.width)

    p1 = cast(d1, POINTER(c_ubyte))
    p2 = cast(d2, POINTER(c_ubyte))

    for i in range(0, int(ri.width)):
        for j in range(0, int(ri.height)):
            c1, c2 = 0, 0
            x1 = offx1+i
            y1 = (j+offy1)*sprite1.texture.width
            x2 = offx2+i
            y2 = (offy2+j)*sprite2.texture.width

            if x1 >= 0 and y1 >= 0:
                c1 = p1[x1 + y1]

            if x2 >= 0 and y2 >= 0:
                c2 = p2[x2 + y2]

            if c1>0 and c2 >0:
                pairs.add(pair)
                break

衝突とレンダリング可能は、特定のエンティティに関連付けられているオブジェクトの単なる辞書です。アルゴリズムはこれの修正バージョンです:Pygletピクセルの完全な衝突

それはかなり良いですが(そして、そのようなコードを一緒にハッキングした場合でも)、回転したスプライトには役に立ちません(異なる角度で同じスプライトの約100の異なるバージョンをキャッシュすることが実行可能なオプションでない限り、これは必要です)、私はまだその問題の解決策を探しています。

4

2 に答える 2

1

ピグレット、テクスチャ、画像に関する最初の質問には答えられませんが(オンラインAPIのTextureで「get_image_data」というメソッドを見つけました。おそらくそれを使用できますか?)、2番目の質問には答えることができます。

リンクで提供した方法とは別に、少なくとも2つの方法を知っています。1つはOpenGLを使用し、画像をバッファに描画し、それらが重複していないかどうかを確認する方法です。これがどれだけ速いかはわかりませんが、遅いと想像できます。ただし、回転とスケーリングはサポートされています。

2つ目は、あなたが与えたものとやや似ています。ただし、2つの軸に位置合わせされた境界ボックスの交点を見つけて、交点の内側だけをチェックする代わりに、2つの凸包の交点を見つけてチェックします。これの利点の1つは、凸包が一般により適切にフィットすることです。もう1つは、凸包を回転できるのに対し、軸に位置合わせされた境界ボックスは回転できないことです。主な欠点は、凸包の交差が軸に沿ったバウンディングボックスの交差よりもはるかに複雑であるため、実装が難しい場合があることです。

2番目の方法を利用するライブラリを作成しました。あなたはPoxelCollでそれを見つけることができます。特に回転とスケーリングの場合、他のピクセルパーフェクトな衝突検出ライブラリよりも高速である必要があります。Pythonから使用できるかどうかはわかりません。Jythonを使用する場合はScalaバージョンがあり、Pythonでバインディングを作成できるC ++バージョンがありますが、それはかなりの余分な作業になる可能性があります。したがって、スケーリングや回転が必要ない場合は、すでに見つけたバージョンを実装して、十分に高速かどうかをテストすることをお勧めします。

于 2012-05-14T17:21:48.637 に答える
1

アップデートへの答え

次の疑似コードでうまくいくかもしれません:

...

middleX1 = sprite1.texture.width/2
middleY1 = sprite1.texture.height/2

middleX2 = sprite2.texture.width/2
middleY2 = sprite2.texture.height/2

angle1 = ?   #Radians.
vX11 = -cos(angle1)
vY11 = -sin(angle1)
vX12 = -cos(angle1 + math.pi/2)
vY12 = -sin(angle1 + math.pi/2)

angle2 = ?   #Radians.
vX21 = -cos(angle2)
vY21 = -sin(angle2)
vX22 = -cos(angle2 + math.pi/2)
vY22 = -sin(angle2 + math.pi/2)

for ...
    for ...

        ...

        aX1 = x1 - middleX1
        aY1 = j+offy1 - middleY1
        aX2 = x2 - middleX2
        aY2 = j+offy2 - middleY2

        tX1 = vX11*aX1 + vY11*aY1 + middleX1
        tY1 = vX12*aX1 + vY12*aX1 + middleY1

        tX2 = vX21*aX2 + vY21*aY2 + middleX2
        tY2 = vX22*aX2 + vY22*aX2 + middleY2

        #Use tX* and tY* for indexing. Remember to multiply tY* with width.

        ...

これは、角度が時計回りでラジアンであり、回転が各スプライトの中央付近で発生する必要があると仮定して、機能する必要があります。基本的に、これはハンドコーディングされたベクトルと行列の計算のビットです。よりきちんとした、より保守しやすいソリューションは行列を使用することですが、私は Python についてあまり知らないので、それを避けることにしました。

計算は、各画像の各ポイントについて、中央に対する相対位置を見つけ、回転の新しい軸に沿って座標に単位ベクトルを掛けて回転させ、最後に中央を元に戻して非相対を取得することによって機能します座標。

于 2012-05-18T18:06:37.637 に答える