如何在屏幕边界外正确删除节点?

时间:2014-06-11 18:19:47

标签: ios objective-c xcode sprite-kit

我正在开发一个sprite-kit游戏,其中节点在屏幕的最低点以下产生,并且重力被设置为让它们浮动到屏幕的顶部。一切都很完美,但它很快就开始减慢FPS,最终滞后和故障变得非常缓慢。我认为解决这个问题的方法是在父节点超过一个点之后从父节点中删除节点,这是我在更新中使用的代码:

-(void)update:(CFTimeInterval)currentTime {

    if (_bubble1.position.y > CGRectGetMaxX(self.frame)+40) {
        [self removeFromParent];
    }

}

如果需要,这就是我在initWithSize方法下产生气泡的方法:

-(void)didMoveToView:(SKView *)view {

    [self performSelector:@selector(spawnBubbles) withObject:nil afterDelay:1.0];
    [self performSelector:@selector(spawnBubbles1) withObject:nil afterDelay:1.5];

}

-(void)spawnBubbles {
    randomPosition = arc4random() %260*DoubleIfIpad;
    randomPosition = randomPosition + 20*DoubleIfIpad;

    randomNumber = arc4random() %7;
    randomNumber = randomNumber + 1;

    myColorArray = [[NSArray alloc] initWithObjects:colorCombo1, colorCombo2, colorCombo3, colorCombo4, colorCombo5, colorCombo6, colorCombo7, colorCombo8, nil];
    myRandomColor = [myColorArray objectAtIndex:randomNumber];

    _bubble1 = [SKShapeNode node];
    [_bubble1 setPath:CGPathCreateWithEllipseInRect(CGRectMake(-25*DoubleIfIpad, -25*DoubleIfIpad, 50*DoubleIfIpad, 50*DoubleIfIpad), nil)];
    _bubble1.strokeColor = _bubble1.fillColor = myRandomColor;
    _bubble1.position = CGPointMake(randomPosition, CGRectGetMinY(self.frame)-60);
    _bubble1.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:20];
    _bubble1.physicsBody.categoryBitMask = CollisionBubble;

    [self addChild:_bubble1];

    [self runAction:[SKAction sequence:@[
                                         [SKAction waitForDuration:1.0],
                                         [SKAction performSelector:@selector(spawnBubbles) onTarget:self],
                                         ]]];

}

如何才能使节点在离开屏幕时妥善处理掉?如何将FPS保持在60 FPS的恒定速率?

提前致谢!!

2 个答案:

答案 0 :(得分:12)

我建议在spritekit中使用内置的接触检测。创建一个模仿屋顶的skspritenode,其中物理主体设置为检测与气泡的接触。在屋顶节点和气泡节点之间的接触上创建一个简单地去除气泡的事件。这将确保消除气泡并保持恒定的FPS。

联系人呼吁的事件示例:

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

联系检测示例:

- (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.physicsBody.contactTestBitMask = roofCategory;

车顶:

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

答案 1 :(得分:4)

1 /使用以下代码启动您的场景physicsBody属性:

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

2 /为场景和精灵节点创建类别蒙版:

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

3 /为场景和精灵节点categoryBitMask属性设置正确的collisionBitMaskcontactTestBitMaskphysicsBody

// Scene
physicsBody!.categoryBitMask = boundaryCategoryMask

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

作为示例,以下Swift SKScene实现向您展示了如何删除超出场景框架的所有精灵节点:

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 */
    }

}