SpriteKit SKPhysicsBody with Inner Edges

我创建了一个SKSpriteNode名为let,例如Map ,它具有我定义的边缘路径(一些简单的多边形形状)。

我想弄清楚的是如何添加几个其他边缘路径作为Map的内部边缘。 好像整个“地图”确实有漏洞 。 某种内部边界形状可以与Map一起作为一个整体:一条边缘路径(如下所示)

在此处输入图像描述 ©

我知道有一种方法允许用body(一些NSArray)创建一个SKPhysicsBody ,就像这样

 Map.physicsBody = [SKPhysicsBody bodyWithBodies:bodiesArray]; 

这种方法实际上是否产生了我在图像中显示的内容? 假设bodiesArray包含3个SKSpriteNode ,每个SKSpriteNode都有一个使用这种方法定义的路径:

 + (SKPhysicsBody *)bodyWithEdgeChainFromPath:(CGPathRef)path 

,创造这样的道路

  SKSpriteNode *innerNode1 = [SKSpriteNode spriteNodeWithImageNamed:@"map"]; CGMutablePathRef innerNode1Path = CGPathCreateMutable(); CGPathMoveToPoint(mapPath, NULL, 1110, 1110); CGPathAddLineToPoint(mapPath, NULL, , ); CGPathAddLineToPoint(mapPath, NULL, , ); CGPathAddLineToPoint(mapPath, NULL, , ); . . . CGPathCloseSubpath(mapPath); innerNode1.physicsBody = [SKPhysicsBody bodyWithPolygonFromPath:innerNode1Path]; [bodiesArray addObject:innerNode1]; // Repeat for other 2 nodes 

我知道另一种方法是创建3个单独的节点,其中包含预期“洞”的位置和形状,但我想要避免创建比我需要的节点更多的节点。 如果有人能够确认我想要做的是正确的,或者可能建议我不知道的替代方案。

注意 :如果我正在做的事情是正确的,但我错过了一些东西,如果有人能告诉我正确的方法来做我想做的事情,我将不胜感激(即使是一个内部较小正方形的正方形的简单例子也是如此)大)。 谢谢!

编辑1 :下面是我用来创建“内部边界”的代码片段。 这里的问题是,虽然绘制并显示了外部和内部矩形,但是当我将内部矩形添加到Map bodyWithBodies ,它完全控制了碰撞检测,从外部rect shell中删除了所有接触控制。 当我移除bodyWithBodies它恢复正常显示两个rects,外部有碰撞检测(不允许我通过),而内部没有任何东西……如此接近

 // 1 Create large outer shell Map CGRect mapWithRect = CGRectMake(map.frame.origin.x + offsetX, map.frame.origin.y + offsetY, map.frame.size.width * shrinkage, map.frame.size.height * shrinkage); self.physicsWorld.gravity = CGVectorMake(0.0, 0.0); self.physicsWorld.contactDelegate = self; // 2 Create smaller inner boundary CGRect innerRect = CGRectMake(100, 100, 300, 300); SKPhysicsBody *body = [SKPhysicsBody bodyWithEdgeLoopFromRect:innerRect]; body.categoryBitMask = wallCategory; NSArray *bodyArray = [NSArray arrayWithObject:body]; // 3 Add bodies to main Map body myWorld.physicsBody = [SKPhysicsBody bodyWithBodies:bodyArray]; myWorld.physicsBody.categoryBitMask = wallCategory; if ( [[levelDict objectForKey:@"DebugBorder"] boolValue] == YES) { // This will draw the boundaries for visual reference during testing [self debugPath:mapWithRect]; [self debugPath:innerRect]; } 

编辑2这种方法有效..只需添加一个与外部矩形具有相同属性的新节点:

 SKPhysicsBody *innerRectBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:innerRect]; innerRectBody.collisionBitMask = playerCategory; innerRectBody.categoryBitMask = wallCategory; SKNode *innerBoundary = [SKNode node]; innerBoundary.physicsBody = innerRectBody; [myWorld addChild: innerBoundary]; 

…但我非常希望一个更清洁的解决方案,不需要额外的节点…虽然?

你在这里做错了我带来一个例子,我用两个物理体创建了两个边缘矩形体

//使用gcd在一段时间后添加实体

 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self addBodyA]; }); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self addBodyB]; }); -(void)addBodyB { SKSpriteNode *node=[SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(20, 20)]; node.physicsBody=[SKPhysicsBody bodyWithRectangleOfSize:node.frame.size]; node.position=CGPointMake(550, 420); node.physicsBody.restitution=1; [self addChild:node]; } -(void)addBodyA { SKSpriteNode *node=[SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(20, 20)]; node.physicsBody=[SKPhysicsBody bodyWithRectangleOfSize:node.frame.size]; node.position=CGPointMake(400, 420); node.physicsBody.restitution=1; [self addChild:node]; } -(void)addEdgesBodies { SKAction *r=[SKAction rotateByAngle:1.0/60 duration:1.0/60]; SKSpriteNode *rect=[SKSpriteNode spriteNodeWithColor:[SKColor clearColor] size:CGSizeMake(300,300)]; rect.physicsBody=[SKPhysicsBody bodyWithEdgeLoopFromRect:rect.frame]; rect.position=CGPointMake(500, 400); [self addChild:rect]; // SKSpriteNode *rect1=[SKSpriteNode spriteNodeWithColor:[SKColor clearColor] size:CGSizeMake(100,100)]; rect1.physicsBody=[SKPhysicsBody bodyWithEdgeLoopFromRect:rect1.frame]; rect1.position=CGPointMake(550, 450); [self addChild:rect1]; [rect1 runAction:[SKAction repeatActionForever:r]]; } [self addEdgesBodies]; 

记住边缘体具有低CPU开销,所以不要担心性能,直到你的多边形没有这么多边缘。

你制作一个路径然后在物理体中使用它的代码看起来会起作用。 以及身体的物理身体。 不幸的是我不知道SKPhysicsBody可以真正支撑孔,因为你无法翻转身体的法线。 我阅读苹果文档的方式是,它意味着做一些事情,比如采用两个圆形形状并将它们组合成一个体,而不是像这样创建一个复杂的形状。 问题是在你的更大的形状内有一个洞将意味着忽略该区域的碰撞。

以下是一些备选方案

一种选择是你可以从多种形状构建你的舞台。 例如,如果您将地图分成两部分(每条线都有一条线)并为这些部分制作物理实体。 然后将它们重叠并将它们组合成一个体,然后它就可以解决了。 我做了一个图表显示这个(原谅它的可怕质量你应该仍然能够理解它正在做什么(希望))。 在此处输入图像描述

另一种选择是使用纹理来制作它,这可能会损害性能,但如果你可以管理它,那么它可能会很好地工作。

 Map.physicsBody = SKPhysicsBody(texture: Map.texture, size: Map.size)