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

标签 swift sprite-kit collision tile tiled

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

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

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

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

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

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

所以问题是,我如何单独使用 SpriteKit 处理这些类型的碰撞(没有额外的框架,如 Cocos2D、Kobold Kit 等)?还是这种方法完全错误,平台游戏中与 SpriteKit 的碰撞应该从根本上不同?

非常感谢任何帮助!

最佳答案

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

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

例如:

enter image description here

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

下一步是解析您的 map 对象。对于 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];
    }

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

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

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

关于swift - SpriteKit tilemaps 与弯曲或倾斜的地砖碰撞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30211503/

相关文章:

ios - 如何在 xcode 和 swift 中使用不受支持的类(新功能)构建项目

arrays - Swift:使用备用键的合并排序算法

swift - 在 SpriteKit swift4 Xcode 中停止运动并设置计时器来切换玩家

ios7 - SpriteKit碰撞检测不起作用

xcode - 理解 SpriteKit 节点的概念

快速碰撞不起作用。我认为 didBeginContact 中的代码有问题

ios - 从 iOS 模拟器上的应用程序崩溃中退出

math - 到交叉路口的最短路线

javascript - 二维 map 数组上的简单 Javascript 碰撞检测

swift - 强制二进制数显示有符号整数?