iOS SKSpriteNode - Leave screen

为君一笑 提交于 2019-12-01 23:02:30
AndyOS

Update method is where you can do it alright:

- (void)update:(NSTimeInterval)currentTime {
    //remove any nodes named "yourNode" that make it off screen
    [self enumerateChildNodesWithName:@"yourNode" usingBlock:^(SKNode *node, BOOL *stop) {

        if (node.position.x < 0){
            [node removeFromParent];
        }
    }];
}

Though note that removing nodes doesn't guarantee freeing up memory!!

Here's how to test if the node has left any edge of the screen. In your update loop, iterate through all children object of your layer. Test if the object is of a specific type. Then test if the node's frame is outside each edge of the screen. If so call removeFromParent. Note that since the node's position is from its center you want to take that into account.

-(void)update:(CFTimeInterval)currentTime 
{
    [_gameLayer.children enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) 
    {
        if ([obj isKindOfClass:[MyNode class]])
        {
            MyNode *myNode = (MyNode *)obj;

            if (myNode.position.x + myNode.size.width/2 < 0 ||
                myNode.position.x - myNode.size.width/2 > self.size.width ||
                myNode.position.y + myNode.size.height/2 < 0 ||
                myNode.position.y - myNode.size.height/2 > self.size.height)         
            {
                [myNode removeFromParent];
            }
        }
    }];
}

You can also detect contact with the background SKSpriteNode and set a category for it. And then, implement didEndContact: method to remove the object

- (void)didEndContact:(SKPhysicsContact *)contact
{
   //Find out your object (Remember it could be bodyA or bodyB) and remove it here
}

You can use this function. This function will be called every frame.(ps:My English is poor) -(void)didSimulatePhysics

I prefer contact handling. Contact testing is done in each frame just like the processing of update:. But the contact detection by comparing bits (SKPhysicsBody.categoryBitMask) is very fast and leightweight.

I need to detect and remove balls that leave the screen. So I setup an invisible border as the scenes physicsBody that is exactly large enough to detect balls the have left the screen completely.

If physicsBody.contactTestBitMask of node#1 == physicsBody.categoryBitMask of node #2 then didBeginContact: is being called when both of them get in touch.

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

    // bitmasks:
    static uint32_t const categoryBitMaskBall = 0x1<<1;
    static uint32_t const categoryBitMaskBorder = 0x1<<6;

    CGFloat ballDiameter = [BallSprite radius] *2;

    // floorShape is my scenes background
    CGRect largeFloorFrame = floorShape.frame;
    largeFloorFrame.origin.x -= ballDiameter;
    largeFloorFrame.origin.y -= ballDiameter;
    largeFloorFrame.size.width += ballDiameter *2;
    largeFloorFrame.size.height += ballDiameter *2;

    CGPathRef pathMainView = CGPathCreateWithRect(largeFloorFrame, nil);
    self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromPath:pathMainView];
    self.physicsBody.categoryBitMask = categoryBitMaskBorder;
}

- (BallSprite*)addBall {

    // initialize ball with additional configuration...
    BallSprite *ball = [BallSprite ballAtPoint:(CGPoint)p];
    ball.categoryBitMask = categoryBitMaskBall;
    ball.contactTestBitMask = categoryBitMaskBorder;
    [self addChild:ball];
}


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

    /*!
        Check on outside border contact
     */
    if ((firstBody.categoryBitMask & categoryBitMaskBall) != 0 &&
        (secondBody.categoryBitMask & categoryBitMaskBorder) != 0) {

        [firstBody.node removeFromParent];
}
    if ((firstBody.categoryBitMask & categoryBitMaskBorder) != 0 &&
        (secondBody.categoryBitMask & categoryBitMaskBall) != 0) {

        [secondBody.node removeFromParent];
    }
}

Swift version

self.enumerateChildNodesWithName("enemy") {
 node, stop in 

 if (node.position.x < 0) {
   node.removeFromParent()
 }

}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!