【问题标题】:SpriteKit: How can I determine when methods like applyImpulse on a physicsbody are done?SpriteKit:如何确定物理体上的 applyImpulse 等方法何时完成?
【发布时间】:2014-08-19 16:19:01
【问题描述】:

我可以看到 here 如何使用 update() 函数来监视 SKNode 上的“位置”等属性,但我不知道如何知道像 [node.physicsBody applyImpulse:vector] 这样的方法是如何完成的。

-(void)someMethod {
    _monitorOn = YES;
    [_node.physicsBody applyImpulse:CGVectorMake(10,10)];
}
-(void)update:(CFTimeInterval)currentTime {
   if( _monitorOn == YES ) {
       NSLog(@"node position: %f,%f", _node.position.x, _node.position.y);
   }
   // When will this be turned off?
 }

【问题讨论】:

    标签: ios sprite-kit ios8


    【解决方案1】:

    这里有两种方法可以检查applyImpulse的效果是否完成:

    if (_node.physicsBody.resting) {
       // Node is at rest, do something
    }
    

    您经常会发现 resting 属性从未设置过,因为您的精灵移动非常缓慢(尤其是圆形节点)。因此,最好检查一下速度是否接近于零。

    static inline CGFloat speed(const CGVector v)
    {
        return sqrtf(v.dx*v.dx+v.dy*v.dy);
    }
    
    if (speed(_node.physicsBody.velocity) < kSmallValue) {
       // Node is moving very slowly, do something
    }
    

    【讨论】:

    • 是的,速度检查非常有用(!),因为节点到达目的地并在设置 .resting 位之前很久就停止移动。谢谢!
    【解决方案2】:

    applyImpulse 只是为您的_node 增加一些速度;它仅在您调用它并在一帧后“完成”时才会这样做。我认为您真正要寻找的是_node 停止移动的时间(物理引擎会确定_node 的速度为零)。要检查这一点,您可以查看SKPhysicsBodyresting 属性。只需在 update: 循环中检查它;当它是true 时,您的_node 已停止。

    -(void)update:(CFTimeInterval)currentTime {
         if( _monitorOn == YES ) {
             NSLog(@"node position: %f,%f", _node.position.x, _node.position.y);
         }
    
         if( _node.physicsBody.resting ) {
             NSLog(@"node is stopped");
         }
     }
    

    注意: 您可能希望在某处设置一个附加标志,以查看是否应该检查 _node 是否为 resting,否则您将会收到大量“节点已停止”消息。

    -(void)someMethod {
        _monitorOn = YES;
        _appliedImpulse = YES;
        [_node.physicsBody applyImpulse:CGVectorMake(10,10)];
    }
    
    -(void)update:(CFTimeInterval)currentTime {
         if( _monitorOn == YES ) {
             NSLog(@"node position: %f,%f", _node.position.x, _node.position.y);
         }
    
         if( _appliedImpulse && _node.physicsBody.resting ) {
             _appliedImpulse = NO;
             NSLog(@"node is stopped");
         }
     }
    

    【讨论】:

    • 实际上,我可以将 .resting 检查放在 _monitorOn 检查下,但问题是在节点实际停止移动后我得到了相当多的更新——比如 80 个更新,其中 50 个是在实际的最后位置。谢谢!
    • _node.physicsBody.resting == YES 时,您将_monitorOn 设置为NO
    • 是的。伪:如果(_monitor){如果(_node.resting){_monitor = NO; } 其他 { ...} }
    • 好的,正在检查。可能只是物理引擎仍将_node 视为移动,即使它移动的量太小而无法在屏幕上或什至在您的NSLog 条目中注册。如果检查resting 花费的时间太长,您不喜欢,@Aidan 的速度检查将起作用。
    • 是的 - 我现在可以看到节点仍在根据速度数学“移动”,这解释了“静止”(没有速度)的真正定义,但微小的速度不足以改变它的位置。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-18
    • 1970-01-01
    相关资源
    最近更新 更多