【问题标题】:SpriteKit: how to smoothly animate SKCameraNode while tracking node but only after node moves Y pixels?SpriteKit:如何在跟踪节点但仅在节点移动 Y 像素之后平滑地为 SKCameraNode 设置动画?
【发布时间】:2016-12-05 07:53:49
【问题描述】:

This question 和其他人讨论如何使用 SKCameraNode 在 SpriteKit 中跟踪节点。

但是,我们的需求各不相同。

其他解决方案,例如更新相机在 SKScene 的update(_ currentTime: CFTimeInterval) 中的位置不起作用,因为我们只想在节点向下移动 Y 像素后调整相机位置。

换句话说,如果节点向上移动 10 个像素,相机应该保持静止。如果节点向左或向右移动,相机应该保持静止。

我们尝试随着时间的推移而不是立即为相机的位置设置动画,但是对 update(_ currentTime: CFTimeInterval) 内部的相机运行 SKAction 无法执行任何操作。

【问题讨论】:

  • 只跟踪精灵位置并根据该位置限制相机节点的移动。
  • @GeneCode 是的,但是在哪里? update(_ currentTime: CFTimeInterval) 在我们尝试为 SKCameraNode 的运动设置动画时不起作用?
  • 是的,将 SKAction 放在更新方法中并不是一个好的做法,因为每秒会调用多次更新。
  • @GeneCode 对,那么您建议在哪里设置 SKCameraNode 动画?
  • 更新 SKCameraNode 定位。但不要动画。只需立即申请职位。

标签: ios sprite-kit sknode skcameranode


【解决方案1】:

我很快就做了这个。我相信这就是你要找的? (实际动画很流畅,只是我要压缩GIF)

这是更新代码:

-(void)update:(CFTimeInterval)currentTime {
    /* Called before each frame is rendered */

    SKShapeNode *ball = (SKShapeNode*)[self childNodeWithName:@"ball"];
    if (ball.position.y>100) camera.position = ball.position;

    if (fabs(ball.position.x-newLoc.x)>10) {
        // move x
        ball.position = CGPointMake(ball.position.x+stepX, ball.position.y);
    }

    if (fabs(ball.position.y-newLoc.y)>10) {
        // move y
        ball.position = CGPointMake(ball.position.x, ball.position.y+stepY);
    }
}

【讨论】:

  • 感谢您的努力,但这实际上是我们之前所做的。由于节点移动很快(重力下降),因此导致移动非常不稳定。
  • 如果你的动作不顺畅,很可能不是因为这个,而是因为你移动精灵的方式。你是否实现了 timeElapsed*speed 来移动精灵?
  • 或者,也许,由于您使用的是物理,最好将与运动相关的所有内容都放在 didsimulatephysics 委托中?
  • 感谢您的快速响应。如果我们不移动相机,精灵的移动是平滑的,所以看起来这不是与移动精灵有关的问题。抖动仅在移动相机以匹配精灵的新位置时发生,仅在精灵下降 50 像素左右时才会发生。
  • 我不知道了。最后的建议是尝试在 didsimulatephysics 中进行相机移动。祝你好运。
【解决方案2】:

我不会把它放在更新代码中,尽量让你的更新部分保持整洁,记住你只有 16 毫秒可以使用。

而是为您的角色节点创建一个子类,并覆盖位置属性。我们基本上要说的是,如果您的相机距离您的角色 10 像素,请向您的角色移动。我们在动作上使用一个键,这样我们就不会叠加多个动作,并使用一个计时模式来让相机平稳地移动到您的位置,而不是瞬间完成。

class MyCharacter : SKSpriteNode
{
    override var position : CGPoint
    {
        didSet
        {

            if let scene = self.scene, let camera = scene.camera,(abs(position.y - camera.position.y) > 10)
            {
                let move = SKAction.move(to: position, duration:0.1)
                move.timingMode = .easeInEaseOut
                camera.run(move,withKey:"moving")
            }
        }
    }
}

编辑:@Epsilon 提醒我 SKActions 和 SKPhysics 直接访问变量而不是通过存储的属性,所以这不起作用。在这种情况下,在 didFinishUpdate 方法中执行:

override func didFinishUpdate()
{
    //character should be a known property to the class,  calling find everytime is too slow
    if let character = self.character, let camera = self.camera,(abs(character.position.y - camera.position.y) > 10)
    {
        let move = SKAction.move(to: character.position, duration:0.1)
        move.timingMode = .easeInEaseOut
        camera.run(move,withKey:"moving")
    }
}

【讨论】:

  • 如果相机只是向下移动,那么取出腹肌使其
  • 这仅在您直接设置角色位置时才有效。如果您通过动作或通过对其physicsBody 施加力/脉冲来移动角色,则不会调用didSet,因为没有直接设置位置属性。
  • 这是真的,你可以通过在 didFinishUpdate 上执行 character.position = character.position 来解决这个问题,这让我们回到 GeneCodes 答案,只是使用不同的函数,或者使用 customActions 来移动而不是使用内置的移动精灵
  • 感谢骑士的详细回答。 @Epsilon 你还有其他建议吗?
  • SKAction 内部运行didFinishUpdate 似乎没有效果。它对你有用吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多