2

iPhone 用の基本的なプラットフォーム ゲームを作成していますが、衝突検出で問題が発生しました。

if (CGRectIntersectsRect(player.frame, platform.frame))
    pos2 = CGPointMake(0.0, +0.0);
else
    pos2 = CGPointMake(0.0, +10.0);

衝突検出は、プレイヤーがプラットフォームにいるときに存在するゲーム内の重力を止めることです。問題は、衝突検出がプレイヤーの周りの長方形であるという事実にあります。とにかく、実際の形状の衝突検出を行うことはありますか?周囲の長方形ではなく、画像(透明度あり)?

4

1 に答える 1

3

これは自分でプログラムする必要があります。ピクセルごとの衝突はおそらくiPhoneには高すぎることに注意してください。Collidableプロトコル(他のすべてのプログラミング言語ではインターフェイスと呼ばれます)を作成し、collidedWith:(Collidable *)c関数を指定して、衝突を許可するオブジェクトに実装することをお勧めします。次に、ケースバイケースの衝突ロジックを記述できます。同様に、衝突に必要なすべての情報(X、Y、幅、高さ、またはX、Y、ピクセルデータ配列のいずれか)とcollidesWithメソッドを含む大きなスーパークラスを作成できます。 。どちらの方法でも、さまざまなコリジョンメソッドを作成できます。ピクセルコリジョンをいくつかの目的で実行している場合は、パフォーマンスに大きな影響はありません。通常、しかし、それは大幅に高速化。

metanetsoftwareにいる人々は、衝突テクニックに関するいくつかの素晴らしいチュートリアルを作成しました。その中には、軸分離衝突とグリッドベースの衝突があります。後者は、ゲームにとってより実行可能であるように聞こえます。ただし、ブルートフォース衝突検出に固執したい場合(すべてのオブジェクトを他のすべてのオブジェクトに対してチェックする)、画像よりも単純に小さいバウンディングボックスを作成するのが通常は適切な方法です。これは、スーパーマリオブラザーズを含め、成功したプラットフォーマーの数です。加重バウンディングボックスを検討することもできます。つまり、あるタイプのオブジェクト用に1つのバウンディングボックスがあり、他のタイプのオブジェクト用に異なるサイズのバウンディングボックスがあります。たとえば、マリオでは、敵よりもコインを打つための大きな箱があります。

さて、私はあなたに他のことをするように警告しましたが、私はあなたに義務を負わせ、ピクセルベースの衝突を行う方法を説明します。CGImageのピクセルデータにアクセスし、すべてのピクセルを反復処理して、この画像が他の画像と場所を共有しているかどうかを確認します。これがそのためのコードです。

for (int i = 0; i < [objects count]; i++)
{
    MyObject *obj1 = [objects objectAtIndex:i];

    //Compare every object against every other object.
    for (int j = i+1; j < [objects count]; j++)
    {
        MyObject *obj2 = [objects objectAtIndex:j];

        //Store whether or not we've collided.
        BOOL collided = NO;

        //First, do bounding box collision. We don't want to bother checking
        //Pixels unless we are within each others' bounds.
        if (obj1.x + obj1.imageWidth >= obj2.x &&
            obj2.x + obj2.imageWidth >= obj1.x &&
            obj1.y + obj1.imageHeight >= obj2.y &&
            obj2.y + obj2.imageGeight >= obj1.y)
        {
            //We want to iterate only along the object with the smallest image.
            //This way, the collision checking will take the least time possible.
            MyObject *check = (obj1.imageWidth * obj1.imageHeight < obj2.imageWidth * obj2.imageHeight) ? obj1 : obj2;

            //Go through the pixel data of the two objects.
            for (int x = check.x; x < check.x + check.imageWidth && !collided; x++)
            {
                for (int y = check.y; y < check.y + check.imageHeight && !collided; y++)
                {
                    if ([obj1 pixelIsOpaqueAtX:x andY:y] && [obj2 pixelIsOpaqueAtX:x andY:y])
                    {
                        collided = YES;
                    }
                }
            }
        }
    }
}

pixelIsOpaqueがローカル座標ではなくグローバル座標を使用するように作成したので、その部分をプログラムするときは、その部分からxとyを再度減算するように注意する必要があります。そうしないと、画像の境界をチェックアウトすることになります。 。

于 2009-08-31T18:09:46.580 に答える