iOS SKSpriteNode - Leave screen

纵然是瞬间 提交于 2019-12-20 03:32:23

问题


Is there any way to remove from Parent a SKSpriteNode that has left area bounds?

for instance:

-(void)didBeginContact:(SKPhysicsContact *)contact
{
    firstNode = (SKSpriteNode *)contact.bodyA.node;
    if (firstNode.position.y<0) {
        [firstNode removeFromParent];
    }
}

Just point me in the right direction. Is it the update method enumerate through checking their rects or is their an action you can apply. I have gone through the documentation can't seem to find it but I would have thought it would be an easy implement since it saves memory


回答1:


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!!




回答2:


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



回答3:


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
}



回答4:


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




回答5:


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



回答6:


Swift version

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

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

}


来源:https://stackoverflow.com/questions/20173850/ios-skspritenode-leave-screen

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