具有两个物理机构的节点

时间:2016-02-08 19:45:23

标签: ios sprite-kit skspritenode skphysicsbody

我知道这个问题已被问及" here但它没有帮助,也没有涵盖我的要求。

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

  • 我需要一个node,它有2个物理体:1)一个较小的体(200x200)代表节点的框架,2)一个较大的体(500x500)代表一个外围的周边一个将作为"检测"边界。外部物体不会物理地撞击碰撞物体,它只需要记录物体遇到该边界线。以下是我所描述的简单概念:

enter image description here

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

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

我的问题是,在注册该交互时,我似乎无法获得外部边界以允许另一个对象通过。我最接近的是让一个可移动的节点到达边界,然后只要我试图通过边界,就会不断地沿着500x500边界的线来回推动。我已经能够使移动节点UNABLE通过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在标题中设置了<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和内存方面似乎很昂贵,但我相信它仍会有效。如果移动的玩家节点在500x500区域内,我会有BOOL isDetected来表示,然后在update我将监视到500x500节点中心的较小200x200矩形边界的距离。但我更愿意使用2 SKPhysicsBody,因为我相信它可以完成并且更容易实现。

更新 这是我的移动角色(一个名为 Character.m 的单独的SKNode类)

- (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;

}

这是我的模拟器的图像(根据我的描述,它在大小方面略有不同。我的描述是为了便于理解而不是节点的精确缩放) enter image description here

1 个答案:

答案 0 :(得分:2)

这对我有用。抱歉,我没有在obj c上写。对我来说快速的快速

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")
    }
}