问题
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