【问题标题】:iOS SKSpriteNode - Leave screeniOS SKSpriteNode - 离开屏幕
【发布时间】:2013-11-24 11:15:12
【问题描述】:

有什么方法可以从 Parent 中删除具有左区域边界的 SKSpriteNode?

例如:

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

只要给我指出正确的方向。是通过检查其矩形来枚举更新方法,还是您可以应用它们的操作。我浏览了文档似乎找不到它,但我认为这将是一个简单的实现,因为它可以节省内存

【问题讨论】:

    标签: sprite-kit skspritenode


    【解决方案1】:

    更新方法是你可以做到的地方:

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

    请注意,删除节点并不能保证释放内存!!

    【讨论】:

    • 真的吗?我是否将节点设置为 nil 或其他什么?
    • 不,删除它就足够了。但有时其他因素(可能难以识别)会导致记忆被保留,所以我想提一下!
    • 例如,如果您对某个节点有其他强引用。这就像 Cocoa 中的标准内存管理一样。
    【解决方案2】:

    这是测试节点是否离开屏幕边缘的方法。在更新循环中,遍历图层的所有子对象。测试对象是否属于特定类型。然后测试节点的框架是否在屏幕的每个边缘之外。如果是这样,请调用 removeFromParent。请注意,由于节点的位置是从其中心开始的,因此您需要考虑这一点。

    -(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】:

      您还可以检测与背景 SKSpriteNode 的接触并为其设置类别。 然后,实现 didEndContact: 方法来移除对象

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

      【讨论】:

      • 最好的方法,如果接触显示边缘的物体肯定会离开屏幕......迟早。我有一个问题,我的球可以部分离开屏幕并回来 - 由于重力和其他球的接触。 [SKScene didEndContact :] 在这种情况下也会被调用。
      【解决方案4】:

      您可以使用此功能。 每一帧都会调用这个函数。(ps:我的英文很差) -(void)didSimulatePhysics

      【讨论】:

        【解决方案5】:

        我更喜欢联系人处理。接触测试是在每一帧中完成的,就像更新的处理:。但是通过比较位(SKPhysicsBody.categoryBitMask)的接触检测非常快速和轻量级。

        我需要检测并移除离开屏幕的球。 因此,我设置了一个不可见的边框,因为场景物理体刚好足够大,可以检测到完全离开屏幕的球。

        如果physicsBody.contactTestBitMask of node#1 == PhysicsBody.categoryBitMask of node#2 then didBeginContact: 当他们两个取得联系时被调用。

        -(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】:

          斯威夫特版本

          self.enumerateChildNodesWithName("enemy") {
           node, stop in 
          
           if (node.position.x < 0) {
             node.removeFromParent()
           }
          
          }
          

          【讨论】:

            猜你喜欢
            • 2020-12-11
            • 1970-01-01
            • 2011-09-14
            • 2017-12-01
            • 2012-05-15
            • 1970-01-01
            • 1970-01-01
            • 2021-10-23
            相关资源
            最近更新 更多