sprite kit:如何根据距离改变 skaction 持续时间?

Posted

技术标签:

【中文标题】sprite kit:如何根据距离改变 skaction 持续时间?【英文标题】:sprite kit: how to vary skaction duration based on distance? 【发布时间】:2017-03-21 12:52:56 【问题描述】:

好的,所以我有一个 Cgpoints 数组,我在遍历数组时将一个精灵节点移动到该数组。精灵与下一个点的距离因每个点而异

func moveGuy() 
    let action = SKAction.move(to: points[i], duration: 2)
    action.timingMode = .easeInEaseOut
    guy.run(action)   


//UPDATE
override func update(_ currentTime: CFTimeInterval) 
    if(mouseIsDown)
    
       moveGuy()
    

我的问题是静态持续时间,这取决于精灵的位置,他以较慢/较快的速度移动。无论精灵必须走多远,我都需要保持恒定的速度。

如何根据精灵与终点的距离来改变 SKAction 的速度?

【问题讨论】:

【参考方案1】:

这需要使用距离公式。现在要保持恒定速度,您需要确定要移动的每秒点数 (pps)。

基本上公式变成了距离/pps

假设我们想要从 (0,0) 到 (0,300)(这是 300 点,所以我们需要 2 秒)

伪代码:

让时长 = sqrt((0 - 0) * (0 - 0) + (0 - 300) * (0 - 300)) / (150) 持续时间 = sqrt(90000) / (150) 持续时间 = 300 / 150 持续时间 = 2

然后您将其弹出到您的移动操作中:

let action = SKAction.move(to: points[i], duration: duration)

您的 Swift 代码应如下所示:

let pps = 150 //define points per second
func moveGuy() 
    var actions = [SKAction]()
    var previousPoint = guy.position // let's make sprite the starting point
    for point in points
    
      //calculate the duration using distance / pps
      //pow seems to be slow and some people have created ** operator in response, but will not show that here
      let duration = sqrt((point.x - previousPoint.x) * (point.x - previousPoint.x) + 
                     (point.y - previousPoint.y) * (point.y - previousPoint.y)) / pps

      //assign the action to the duration
      let action = SKAction.move(to: point, duration: duration)
      action.timingMode = .easeInEaseOut
      actions.append(action)
      previousPoint = point
       
    guy.run(actions)


//Since the entire path is done in moveGuy now, we no longer want to be doing it on update, so instead we do it during the mouse click event
//I do not know OSX, so I do not know how mouse down really works, this may need to be fixed
//Also I am not sure what is suppose to happen if you click mouse twice,
//You will have to handle this because it will run 2 actions at once if not done
override func mouseDown(event:NSEvent)

    moveGuy()

现在您会注意到您的精灵在每次迭代时都会运行并变慢,您可能不希望这样,因此对于您的计时模式,您可能希望这样做

//Use easeInEaseOut on our first move if we are only moving to 1 point
if points.count == 1

    action.timingMode = .easeInEaseOut

//Use easeIn on our first move unless we are only moving to 1 point
else if previousPoint == sprite.position

    action.timingMode = .easeIn

//Use easeOut on our last move unless we are only moving to 1 point
else if point == point.last

    action.timingMode = .easeOut

//Do nothing
else

    action.timingMode = .linear

【讨论】:

每一帧都会有很多SKActions创建和销毁。我想知道你为什么没有警告skyguy?他正在做的事情不是去 IMO 的有效方式,也没有任何意义(即使行动的持续时间很短)。 我认为他还是个新手,我不想在他身上扔太多 SKAction followPath 将是他有兴趣了解路径的真正方法 是的,那行得通。或者直接更新位置属性而不使用操作...我同意这对于新手来说可能太多了,但我不知道,当有人将持续时间为 2 秒的SKAction 放入update: 时,它只是戳我的眼睛方法并在下一帧中覆盖该操作。没有意义。 哦,我忘了在我的回答中提到,谢谢提醒,我删除了更新功能【参考方案2】:

您必须创建一个新的 SKAction,其持续时间根据要移动的距离和要移动的节点的速度(以点/秒为单位)计算得出。

【讨论】:

以上是关于sprite kit:如何根据距离改变 skaction 持续时间?的主要内容,如果未能解决你的问题,请参考以下文章

如何根据平移手势速度向 Sprite Kit 节点应用角脉冲

如何通过 Sprite Kit 中的 CGPoints 数组制作动画 - Swift

在 Sprite-Kit 中更改精灵图像

如何在 sprite kit 中引用多个同名的 sprite?

如何在 Sprite-kit 中画一条线

如何在Sprite-kit中画一条线