具有两个物理体的节点

Node with Two Physics Bodies

我知道这个问题已经 "asked" here 但它没有帮助,也没有涵盖我的问题。

话虽如此,我想知道如何实现以下目标:

我最初的方法是使用 SKPhysicsBody bodyWithBodies:<NSArray>,但这只会创建重叠 body 作为较小的矩形。

所以我想我必须为较小的 body(黑色方块)创建一个 SKSpriteNode,为较大的 body(黑色方块)创建另一个 SKSpriteNode蓝色方块),并将其作为 child 添加到较小的方块(反之亦然)。

我的问题是,在注册该交互时,我似乎无法获得允许另一个 object 通过的外边界。我最接近的是让一个可移动节点撞到边界,然后只要我试图穿过边界,就会沿着 500x500 边界线不断地来回推动。我已经能够使移动节点无法通过 500x500,但这与我需要的完全相反。

这是我正在使用的代码,也许有人能看出我做错了什么:

/// TESTING

// Detection body - 500x500
SKSpriteNode *dbody = [SKSpriteNode spriteNodeWithImageNamed:@"object500"];
dbody.position = CGPointMake(500, 100);
dbody.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:dbody.frame];
dbody.physicsBody.categoryBitMask = detection;
dbody.physicsBody.collisionBitMask = 0;
dbody.physicsBody.contactTestBitMask = player;

// Node body - 200x200
SKSpriteNode *testBoundary = [SKSpriteNode spriteNodeWithImageNamed:@"object"];
testBoundary.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:testBoundary.frame];
testBoundary.physicsBody.categoryBitMask = object;
testBoundary.physicsBody.contactTestBitMask = player;
testBoundary.position = dbody.position;

// Add boundary as child to main node
[testBoundary addChild:dbody];

// Add to scene
[chapterScene addChild:dbody];

所有这些都在 LevelScene.m 中,SKScene 集 header 中的 <SKPhysicsContactDelegate>。另外,我这样定义 chapterScene

// Set up main chapter scene
self.anchorPoint = CGPointMake(0.5, 0.5); //0,0 to 1,1
chapterScene = [SKNode node];
[self addChild:chapterScene];

,在 LevelScene 的顶部定义了 chapterScene

@interface LevelScene () {

#pragma 1 Scene objects
    SKNode *chapterScene;

}

如果有人可以帮助我弄清楚我做错了什么,或者可以提供一种替代方法来满足我的需求,我将不胜感激。

注意: 我的备份解决方案在 CPU 和内存方面似乎很昂贵,但我相信它仍然有效。我将有一个 BOOL isDetected 来表示移动玩家节点是否在 500x500 区域内,然后在 update 中我将监视到 500x500 节点中心的较小 200x200 矩形边界的距离。但我更愿意使用 2 SKPhysicsBody,因为我确信它可以完成并且更容易实现。

更新: 这是我的移动角色(一个单独的 SKNode class 称为 Character.m

- (void)createCharacterWithName:(NSString *)charName {

    character = [SKSpriteNode spriteNodeWithImageNamed:charName];
    [self addChild:character];

    self.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:character.frame.size.width/2.0];
    self.physicsBody.dynamic = YES;
    self.physicsBody.allowsRotation = YES;

    // Define physics body relationships
    self.physicsBody.categoryBitMask = player;
    self.physicsBody.collisionBitMask = player;
    self.physicsBody.contactTestBitMask = detection;

}

这是我的模拟器的图片(就尺寸而言,它与我的描述略有不同。我的描述是为了便于理解,而不是节点的精确缩放)

这对我有用。对不起,我没有把它写在 objc 上。 swift

对我来说快多了
import SpriteKit

let CategoryOuter:UInt32     = 1 << 0
let CategoryInner:UInt32     = 1 << 1
let CategoryTester:UInt32    = 1 << 2

class GameScene: SKScene, SKPhysicsContactDelegate {

    let outerSprite = SKSpriteNode(color: SKColor.redColor(), size: CGSizeMake(100, 100))
    let innerSprite = SKSpriteNode(color: SKColor.blueColor(), size: CGSizeMake(40, 40))
    let tester = SKSpriteNode(color: SKColor.greenColor(), size: CGSizeMake(10, 10))

    override init(size: CGSize) {
        super.init(size: size)
        physicsWorld.contactDelegate = self
        physicsWorld.gravity = CGVectorMake(0, 0)

        outerSprite.position = CGPointMake(size.width/2, size.height/2)
        outerSprite.physicsBody = SKPhysicsBody(rectangleOfSize: outerSprite.size)
        outerSprite.physicsBody!.dynamic = false
        outerSprite.physicsBody!.categoryBitMask = CategoryOuter
        outerSprite.physicsBody!.collisionBitMask = 0
        outerSprite.physicsBody!.contactTestBitMask = CategoryTester

        innerSprite.physicsBody = SKPhysicsBody(rectangleOfSize: innerSprite.size)
        innerSprite.physicsBody!.dynamic = false
        innerSprite.physicsBody!.categoryBitMask = CategoryInner
        innerSprite.physicsBody!.collisionBitMask = CategoryTester
        innerSprite.physicsBody!.contactTestBitMask = CategoryTester

        outerSprite.addChild(innerSprite)
        addChild(outerSprite)

        tester.physicsBody = SKPhysicsBody(rectangleOfSize: tester.size)
        tester.physicsBody!.categoryBitMask = CategoryTester
        tester.physicsBody!.collisionBitMask = CategoryInner
        addChild(tester)
    }

    func didBeginContact(contact: SKPhysicsContact) {
        let collision:UInt32 = (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask)

        if collision == (CategoryOuter | CategoryTester) {
            print("outer collision")
        }
        else if collision == (CategoryInner | CategoryTester) {
            print("inner collision")
        }
    }

    override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
        if let touch = touches.first {
            let location = touch.locationInNode(self)
            tester.position = location
        }
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}