iPhone SDK:碰撞检测,是否必须是矩形?

时间:2009-08-30 20:11:02

标签: iphone collision-detection

我正在为iPhone制作基本平台游戏,我遇到了碰撞检测问题。

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

碰撞检测是当玩家在平台上时停止游戏中的重力,问题在于碰撞检测是玩家周围的矩形,无论如何都要对实际进行碰撞检测图像的形状(有透明度)而不是围绕它的矩形?

1 个答案:

答案 0 :(得分:3)

你必须自己编程,并注意逐像素的碰撞可能对iPhone来说太贵了。我的建议是编写一个Collidable协议(在所有其他编程语言中称为接口),给它一个collidedWith :( Collidable *)c函数,然后只为你想允许碰撞的任何对象实现它。然后你可以编写逐个案例的碰撞逻辑。类似地,你可以创建一个包含碰撞所需信息的大型超类(在你的情况下是X,Y,宽度和高度,或X,Y和像素数据数组)和collidesWith方法。无论哪种方式,你都可以编写一堆不同的碰撞方法 - 如果你只是为了一些事情而进行像素碰撞,那么它就不会受到很大影响。但通常情况下,最好根据几何进行边界框碰撞或其他碰撞,因为它显着更快。

metanetsoftware上的人们提供了一些关于碰撞技术的精彩教程,其中包括axis separation collsiongrid based collision,后者听起来对你的游戏来说更可行。但是,如果您想坚持使用强力碰撞检测(检查每个对象与其他所有对象),那么创建一个比图像更小的边界框通常是正确的方法。这就是有多少成功的平台游戏,包括超级马里奥兄弟。你也可以考虑加权边界框 - 也就是说,你有一种类型的对象的边界框和其他的不同尺寸的边界框。例如,在马里奥,你有一个更大的盒子来击中硬币而不是敌人。

现在,即使我已经警告过你,否则我会责备你,并介绍如何进行基于像素的碰撞。您将要获得CGImage的access the pixel data,然后遍历所有像素以查看此图像是否与任何其他图像共享位置。这是一些代码。

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,否则你将检查出界限你的形象。