How to properly remove node when out of screen bounds?

后端 未结 2 403
广开言路
广开言路 2020-12-06 06:15

I\'m working on a sprite-kit game where nodes spawn below the lowest point on the screen and gravity is set to have them float to the top of the screen. Everything works per

相关标签:
2条回答
  • 2020-12-06 06:51

    With Swift 1.1 / iOS 8, you can use the following pattern in order to solve your problem.


    1. Init your scene's physicsBody property with the following code:

    physicsBody = SKPhysicsBody(edgeLoopFromRect: frame) // or CGRectInset(frame, -10, -10) if you need insets 
    

    2. Create category masks for your scene and your sprite nodes:

    let boundaryCategoryMask: UInt32 =  0x1 << 1
    let someNodeCategoryMask: UInt32 =  0x1 << 2
    

    3. Set the proper categoryBitMask, collisionBitMask and contactTestBitMask for your scene and sprite nodes physicsBody properties:

    // Scene
    physicsBody!.categoryBitMask = boundaryCategoryMask
    
    // Sprite node
    /* ... */
    someNode.physicsBody!.categoryBitMask = someNodeCategoryMask
    someNode.physicsBody!.contactTestBitMask = boundaryCategoryMask 
    

    As an example, the following Swift SKScene implementation shows you how to remove all sprite nodes that go beyond your scene's frame:

    class GameScene: SKScene, SKPhysicsContactDelegate {
    
        let boundaryCategoryMask: UInt32 =  0x1 << 1
        let squareCategoryMask: UInt32 =  0x1 << 2
    
    
        override func didMoveToView(view: SKView) {
            // Scene
            backgroundColor = SKColor.whiteColor()
            physicsWorld.contactDelegate = self
            physicsBody = SKPhysicsBody(edgeLoopFromRect: frame)
            physicsBody!.categoryBitMask = boundaryCategoryMask
    
            // Square
            let square = SKSpriteNode(color: SKColor.redColor(), size: CGSize(width: 80, height: 80))
            square.zPosition = 0.1
            square.position = CGPoint(x: size.width / 2.0 - square.size.width / 2, y: size.height - square.size.height)
            square.physicsBody = SKPhysicsBody(rectangleOfSize: square.frame.size)
            square.physicsBody!.dynamic = true
            square.physicsBody!.affectedByGravity = true
            square.physicsBody!.categoryBitMask = squareCategoryMask
            // square.physicsBody!.collisionBitMask = 0 // don't set collisions (you don't want any collision)
            square.physicsBody!.contactTestBitMask = boundaryCategoryMask // this will trigger -didBeginContact: and -didEndContact: 
            addChild(square)
        }
    
        override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
            // Check if the array containing the scene’s children is empty
            println("children: \(children)")
        }
    
        func didBeginContact(contact: SKPhysicsContact) {
            if contact.bodyA.categoryBitMask == squareCategoryMask {
                contact.bodyA.node?.removeFromParent()
                println("square removed")
            }
    
            if contact.bodyB.categoryBitMask == squareCategoryMask {
                contact.bodyB.node?.removeFromParent()
                println("square removed")
            }
        }
    
        func didEndContact(contact: SKPhysicsContact) {
            /* ... */
        }
    
        override func update(currentTime: CFTimeInterval) {
            /* Called before each frame is rendered */
        }
    
    }
    
    0 讨论(0)
  • 2020-12-06 06:55

    I would recommend using the built in contact detection in spritekit. Create a skspritenode mimicking a roof that has a physics body set to detect contact with bubbles. Create an event on contact between the roof node and bubble node that will simply remove the bubbles. This will ensure that bubbles are removed and you maintain a constant FPS.

    Example of event called on contact:

    - (void)bubble:(SKSpritenode*)bubble didCollideWithRoof:(SKSpriteNode*)roof{
    [bubble removeFromParent];}
    

    Contact detection example:

    - (void)didBeginContact:(SKPhysicsContact *)contact
    {
    SKPhysicsBody *firstBody, *secondBody;
    if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask)
    {
        firstBody = contact.bodyA;
        secondBody = contact.bodyB;
    }
    else
    {
        firstBody = contact.bodyB;
        secondBody = contact.bodyA;
    }
    
    if (firstBody.categoryBitMask==bubbleCategory && secondBody.categoryBitMask == roofCategory)
    {
        [self bubble:(SKSpriteNode*)firstBody.node didCollideWithRoof:(SKSpriteNode*)secondBody.node];
    }}
    

    Bubble needs:

     _bubble.physicsBody.contactTestBitMask = roofCategory;
    

    Roof:

    SKSpriteNode *roof = [SKSpriteNode spriteNodeWithColor:[SKColor blackColor] size:CGSizeMake(self.scene.size.width, 1)];   
    roof.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(self.scene.size.width, 1)];
    
        roof.position = CGPointMake(self.scene.size.width/2,self.scene.size.height)
        roof.physicsBody.dynamic = NO;
        roof.physicsBody.categoryBitMask = floorCategory;
        roof.physicsBody.contactTestBitMask = bubbleCategory;
        [self addChild:roof];
    
    0 讨论(0)
提交回复
热议问题