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

SpriteKit tilemaps collision with curved or sloped floor tiles

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

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 的碰撞应该从根本上不同?

非常感谢任何帮助!

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

它将能够处理与弯曲和倾斜的地砖的接触,但至于调整站在这些地砖上的物体的角度,你将不得不利用一些数学函数,找到了一个很好的例子here

您仍然可以使用 SpriteKit 的碰撞检测,这会为您简化事情,但会创建您自己的跳跃或移动引擎。

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

如果您使用的是 Tiled 应用程序,那么分配物理 body 是一项简单的任务。使用 Tiled 中的 Objects 分配各种 body 类型。在您的代码中,您可以着手为每个 object 类型创建一个特定的 body。

例如:

在上图中,我创建了一个 45 度右侧倾斜的地板。我加的object叫floor45R

下一步是解析您的地图 object。在 45floorR 的情况下,您可以像这样创建物理 [​​=31=]:

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];
    }

这适用于任何程度的地板坡度。请记住将您的玩家和任何其他节点的碰撞位掩码设置为与地板碰撞。

为了让您的玩家在倾斜的地板上平稳移动,我建议将玩家的物理系统 body 分 2 部分构建。底部为圆形,顶部为矩形。该圆圈将防止卡在由 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]];

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