SpriteKit瓷砖地图与弯曲或倾斜的地砖碰撞

时间:2015-05-13 10:00:19

标签: swift sprite-kit collision tile tiled

我正在计划使用SpriteKit和Swift的iOS平台游戏。我做了一些关于如何处理玩家精灵碰撞的研究,并偶然发现了这篇文章。

http://www.learn-cocos2d.com/2013/08/physics-engine-platformer-terrible-idea/

那篇文章建议你不要使用SpriteKit的内置物理引擎,而是要自己实现移动,跳跃和碰撞处理等功能。 Ray Wenderlichs网站上的平台教程提出了类似的方法。

到目前为止一直很好,但让我们谈谈玩家可以站立的地砖。只要瓷砖是矩形并且具有平坦表面(如Ray Wenderlich的教程中),定制物理实现就很容易,因为您将使用CGRectIntersectsRect来检测碰撞。但是,如何在弯曲或倾斜的瓷砖上检查玩家碰撞?根据我的阅读,CGRectIntersectsRect不考虑精灵矩形内的透明像素。

http://i.stack.imgur.com/lRP2Q.png

以上面的图块为例。白色区域(左上角)是透明的。现在,如果玩家精灵会在此图块上掉落,则会在图块矩形的上边界处检测到碰撞,尽管那里没有地面像素(蓝色区域,右下角)。所以最终玩家将在这片瓷砖上方的半空中盘旋。我可以将玩家精灵推向几个像素,但这有点黑客,如果弯曲的地砖具有不同的倾斜角度会变得更难。

所以问题是,如何单独使用SpriteKit来处理这些类型的碰撞(没有像Cocos2D,Kobold Kit这样的额外框架......)?或者这种方法是完全错误的,平台游戏与SpriteKit的碰撞应该根本不同吗?

非常感谢任何帮助!

2 个答案:

答案 0 :(得分:3)

我不同意不使用物理来处理碰撞和接触。你真的只是试图通过不使用物理和实现自己的自定义代码来重新发明轮子。

如果您正在使用Tiled应用程序,那么分配物理主体是一项简单的任务。使用Tiled中的Objects指定各种体型。在您的代码中,您可以为每种对象类型创建特定的主体。

例如:

enter image description here

在上图中,我创造了一个45度右侧倾斜地板。我添加的对象叫做floor45R。

下一步是解析地图对象。如果是45floorR,你可以创建一个这样的物理体:

NSArray *arrayObjects = [group objectsNamed:@"floor45R"];
    for (NSDictionary *dicObj in arrayObjects) {
        CGFloat x = [dicObj[@"x"] floatValue];
        CGFloat y = [dicObj[@"y"] floatValue];
        CGFloat w = [dicObj[@"width"] floatValue];
        CGFloat h = [dicObj[@"height"] floatValue];

        SKSpriteNode *myNode = [SKSpriteNode spriteNodeWithColor:[SKColor clearColor] size:CGSizeMake(w, h)];
        myNode.position = CGPointMake(x, y);
        myNode.zPosition = 100;
        CGMutablePathRef trianglePath = CGPathCreateMutable();
        CGPathMoveToPoint(trianglePath, nil, -myNode.size.width/2, myNode.size.height/2);
        CGPathAddLineToPoint(trianglePath, nil, myNode.size.width/2, -myNode.size.height/2);
        CGPathAddLineToPoint(trianglePath, nil, -myNode.size.width/2, -myNode.size.height/2);
        CGPathAddLineToPoint(trianglePath, nil, -myNode.size.width/2, myNode.size.height/2);
        myNode.physicsBody = [SKPhysicsBody bodyWithPolygonFromPath:trianglePath];
        myNode.physicsBody.dynamic = NO;
        myNode.physicsBody.restitution = 0;
        myNode.physicsBody.friction = 0.0;
        myNode.physicsBody.categoryBitMask = CategoryFloor45;
        myNode.physicsBody.collisionBitMask = 0x00000000;
        CGPathRelease(trianglePath);

        [worldNode addChild:myNode];
    }

这适用于任何度数的楼坡。请记住将播放器和任何其他节点的冲突位掩码设置为与地板发生碰撞。

为了让你的玩家在倾斜的地板上顺利移动,我建议将玩家的物理身体分为两部分。底部有一个圆圈,顶部有一个矩形。这个圆圈可以防止卡在由2个物理团体组成的任何潜在裂缝中。

SKPhysicsBody *firstBody = [SKPhysicsBody bodyWithCircleOfRadius:10 center:CGPointMake(0, 0)];
SKPhysicsBody *secondBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(5, 50) center:CGPointMake(0, 10)];
self.physicsBody = [SKPhysicsBody bodyWithBodies:@[firstBody, secondBody]];

您必须调整位置和中心坐标以匹配精灵的图像。

答案 1 :(得分:1)

您可以使用关卡编辑器Tiled来处理弯曲和倾斜的地砖以及处理TMX地图的JSTileMap。

它能够处理与弯曲和倾斜的地砖的接触,但是为了调整站在这些地砖顶部的物体的角度,你必须利用一些数学函数,这是一个很好的例子{{3 }}

您仍然可以使用SpriteKit的碰撞检测功能,它可以为您简化操作,但可以创建自己的跳跃或移动引擎。