跟随玩家时SpriteKit相机口吃

时间:2017-10-25 01:24:24

标签: ios swift sprite-kit skaction skcameranode

我在游戏中经历了这种滞后或口吃,我认为这可能是因为我让相机跟随我的播放器。

以下是代码:

func update(_ hp: CGPoint) {
    let camMove = SKAction.move(to: CGPoint(x: hp.x, y: hp.y), duration: 0.2)
    self.run(camMove)
}

上面的函数是SKCameraNode的扩展,我基本上是从场景更新函数调用它。

它功能相当不错,虽然有人提到口吃可能是由于重叠动作,因为它被称为每帧。我使用这种方法是因为持续时间允许相机比刚性更自然地跟随。

我正在寻找替代方法来消除这种SKAction重叠。

我尝试在运行新动作之前添加一个removeallActions()调用,但它必须快速发生,因为相机根本无法移动。此外,我尝试在操作中添加一个键,然后在下一个开始之前按键删除,但与removeallActions()相同,相机不会移动。

我也尝试了以下内容:

func moveCam(_ point: CGPoint) {
    let camMove = SKAction.move(to: CGPoint(x: point.x, y: point.y), duration: 0.2)
    self.run(camMove) {
        self.moveCam(player.position)
    }
}

这会停止重叠,但是在一个动作结束和另一个结尾之间会有轻微的延迟,这会导致一个丑陋的口吃。

我有一个想法尝试使用具有跟随行为的SKAgent,但我不完全确定如何做到这一点或者它是否会好。任何建议或解决方案将不胜感激。

1 个答案:

答案 0 :(得分:1)

你想在精灵位置发生变化时这样做,所以我建议你做KVO来监控它,并相应地更新你的动作:

override func didMove(to view:SKView) {
  super.didMove(to:view)
  sprite.addObserver(self, forKeyPath: #keyPath(SKNode.position),
              options: [.old, .new, .initial],
              context: nil)
}

override func observeValue(forKeyPath keyPath: String?,
                           of object: Any?, change: [NSKeyValueChangeKey : Any]?,
                           context: UnsafeMutableRawPointer?) {

  if keyPath == #keyPath(SKNode.position) {

    guard let camera = self.camera, let sprite = object as? SKNode else { fatalError() }

    let wait = SKAction.wait(forDuration: 0.2)
    let loop = SKAction.customAction(withDuration: TimeInterval(CGFloat.infinity)) {_,_ in
      let move = SKAction.move(to: CGPoint(x: self.sprite.position.x, y: self.sprite.position.y), duration: 0.2)
      camera.run(SKAction.sequence([move,SKAction.run({
        camera.removeAction(forKey:"cameraWaitKey")})]), withKey:"cameraMoveKey")
    }

    if camera.action(forKey:"cameraWaitKey") == nil {
      camera.run(SKAction.sequence([wait,loop]), withKey:"cameraWaitKey")
    }
  }
}


deinit { sprite.removeObserver(self, forKeyPath: #keyPath(SKNode.position)) }

这将做的是应用一个小等待,然后每次位置改变时开始移动相机。一旦相机到达播放器,它将重置,当您再次移动时,将发生延迟。

您可以在操作中添加timingMode,以便在相机移动时创建easeIn和easeOut效果。