具有内部边缘的SpriteKit SKPhysicsBody [英] SpriteKit SKPhysicsBody with Inner Edges

查看:67
本文介绍了具有内部边缘的SpriteKit SKPhysicsBody的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have created an SKSpriteNode called let's say Map that has an edge path that I have defined (some simple polygon shape).

我要弄清楚的是如何添加几个 other 边缘路径,这些路径将用作 Map 的内部边缘.好像整个地图"实际上确实有.某些内部边界形状可以与地图一起使用:一个边缘路径(如下所示)

What I am trying to figure out is how to add several other edge paths that would act as interior edges of the Map. As if the "map" as a whole did in fact have holes. Some sort of inner boundary shapes that could act with Map as a whole: one edge path (as shown below)

©

我了解有一种方法可以创建带有主体(例如NSArray)的SKPhysicsBody,例如

I understand that there is a method that allows for creating an SKPhysicsBody with bodies (some NSArray), like such

Map.physicsBody = [SKPhysicsBody bodyWithBodies:bodiesArray];

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

Does this method in fact generate what I have shown in the image? Assuming that the bodiesArray contains 3 SKSpriteNode's each with a defined path from using such method:

+ (SKPhysicsBody *)bodyWithEdgeChainFromPath:(CGPathRef)path

,并创建类似这样的路径

, with creating the path like such

        SKSpriteNode *innerNode1 = [SKSpriteNode spriteNodeWithImageNamed:@"map"];

        CGMutablePathRef innerNode1Path = CGPathCreateMutable();

        CGPathMoveToPoint(mapPath, NULL, 1110, 1110);
        CGPathAddLineToPoint(mapPath, NULL, <some x1>, <some y1>);
        CGPathAddLineToPoint(mapPath, NULL, <some x2>, <some y2>);
        CGPathAddLineToPoint(mapPath, NULL, <some x3>, <some y3>);
        . 
        .
        .
        CGPathCloseSubpath(mapPath);

        innerNode1.physicsBody = [SKPhysicsBody bodyWithPolygonFromPath:innerNode1Path];
        [bodiesArray addObject:innerNode1];

        // Repeat for other 2 nodes

我知道一种替代方法是使用预期的孔"的位置和形状创建3个单独的节点,但我想避免创建超出所需数量的节点.如果有人可以确认我正在尝试做的事是正确的,或者提出我不知道的替代方法.

I understand that an alternative would be to create 3 separate nodes with the location and shape of the intended "holes", but I am tying to avoid creating more nodes than I need. If anyone can confirm what I am trying to do is correct, or perhaps suggest an alternative that I am unaware of.

注意:如果我做的是正确的,但是我缺少一些东西,那么如果有人可以向我展示正确的方法来做我想做的事情,我将不胜感激(即使是一个简单的例子)内部较小的正方形的正方形将是一个很好的选择).谢谢!

NOTE: IF what I am doing is correct but I am missing something, I would appreciate it if someone can show me the correct way to do what I am trying to do (even a simple example of a square with an inner smaller square would be great). Thanks!

编辑1 : 下面是我用来创建内部边界"的代码片段.这里的问题是,在绘制和显示外部和内部rect的同时,当我将内部rect添加到Map bodyWithBodies时,它将完全控制碰撞检测,并从外部rect shell中删除所有接触控制.当我移除bodyWithBodies时,它恢复正常并显示两个矩形,外部具有碰撞检测功能(不允许我通过),而内部则没有碰撞...如此接近

EDIT 1: Below is the code snippet that I am using as an attempt to create the "inner boundaries". This issue here, is that while both the outer and inner rect's are drawn and shown, when I add the inner rect to the Map bodyWithBodies, it takes full control of the collision detection, removing all contact control from the outer rect shell. When I remove the bodyWithBodies it goes back to normal with showing both rects, the outer has collision detection (does not allow me to pass through), while the inner one has nothing... so close

// 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 这种方法通过仅添加一个与外部rect具有相同属性的新节点来起作用.

EDIT 2 This approach works..by just adding a new node with the same properties as the outer rect:

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

...但是我非常希望有一个更清洁的解决方案,不需要其他节点.

...but I would very much like a cleaner solution that does not require additional nodes..thoughts?

推荐答案

在这里您没有做错什么,我举了一个例子,其中我创建了带有两个物理物体的两个边缘矩形物体

you are doing nothing wrong here i come with an example where i created two edge rect bodies with two physics bodies

//一段时间后使用gcd添加正文

//adding bodies after some time using 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开销,因此不要担心性能,除非您的多边形没有那么多边缘.

remember edge bodies comes with low cpu overhead so don't worry about performance untill your polygon don't have so many edges.

这篇关于具有内部边缘的SpriteKit SKPhysicsBody的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆