有什么算法可以将 SKSpriteNode 的位置与 UIBezierPath 的 currentPoint 关联起来?

问题描述 投票:0回答:1

有什么算法可以将 SKSpriteNode 的位置与 UIBezierPath 的 currentPoint 关联起来?

我有这段代码(

GameViewController
),它沿着
SKSpriteNode
实现了以下
UIBezierPath

func createTrainPath() {
    
    trackRect = CGRect(x: tracksPosX - tracksWidth/2,
                       y: tracksPosY,
                       width: tracksWidth,
                       height: tracksHeight)
    trainPath = UIBezierPath(ovalIn: trackRect)
                  
}   // createTrainPath


func startFollowTrainPath() {
                       
    var trainAction = SKAction.follow(
                                  trainPath.cgPath,
                                  asOffset: false,
                                  orientToPath: true,
                                  speed: theSpeed)
    trainAction = SKAction.repeatForever(trainAction)
    myTrain.run(trainAction, withKey: runTrainKey)

}   // startFollowTrainPath


func stopFollowTrainPath() {
    
    guard myTrain == nil else {
        myTrain.removeAction(forKey: runTrainKey)
        savedTrainPosition = getPositionFor(myTrain, orPath: trainPath)
        return
    }
    
}   // stopFollowTrainPath

该分段的用户可以调出另一个

SKScene
.. 在该操作中,我调用
stopFollowTrainPath()
并将
position
SKSpriteNode
保存到全局
savedTrainPosition
,通过:

func getPositionFor(_ node: SKSpriteNode, orPath: UIBezierPath) -> CGPoint {
    
    if (useNode) {
        return node.position
    }
    else {
        return orPath.currentPoint
    }
    
}   // getPositionFor

(1) 当用户从查看另一个

SKScene
返回时,我希望移动(后续)
SKSpriteNode
继续围绕
UIBezierPath
移动,从我在呈现另一个
 之前停止 
Node
 的位置开始SKScene

(2) 如果在另一个

SKSpriteNode
出现之前 SKScene
移动,我需要
position
SKSpriteNode
保持在新
SKScene
出现之前的位置.

执行这些操作的最佳方法是什么?

uibezierpath
1个回答
0
投票

因为您将在设备旋转时重新调整椭圆形的大小,并且,当您显示不同的场景然后“返回”时,您想要:

  • “保存”当前列车位置
  • 展现新场景
  • 显示火车场景(可能在观看其他场景时旋转设备后)
  • 在保存的位置重新开始动画

您可能需要生成定义椭圆路径的点数组(而不是使用

ovalIn:
)。

让我们看一下仅使用 10 个点的椭圆形路径,其中

array[0]
位于 3 点钟方向:

动画始终从路径的第一个点开始:

现在火车有了一点动画:

用户点击即可进入“方向”场景。

我们找到数组中最近点的索引,保存它,然后返回时使用该索引作为起点重新创建路径:

我们让动画运行,用户点击即可看到“Credits”场景:

我们再次找到数组中最近点的索引,保存它,然后返回时使用该索引作为起点重新创建路径:

为了获得更平滑的椭圆形路径,我们将使用更多点:

我们仍然可以使用当前火车位置来找到最近的点,并使用该点作为起点重新创建路径:

我们使用的点越多,椭圆就越平滑。这是 180 分(标签会很乱):

为了让火车位于椭圆形的内部,并且“正面朝上”,我们可以在节点位于椭圆形中心线下方时水平翻转文本:

从新索引重新创建路径非常快:

    var ptsCopy = Array(thePoints[startIDX...])
    ptsCopy.append(contentsOf: thePoints[0..<startIDX])
    
    let pth = UIBezierPath()
    pth.move(to: ptsCopy.removeFirst())
    while !ptsCopy.isEmpty {
        pth.addLine(to: ptsCopy.removeFirst())
    }
    pth.close()

而且,除非您正在做一些在本文和其他相关帖子中未讨论过的事情,否则我们不必重复生成“椭圆形点数组”......您只有两种尺寸 - 一种一个用于纵向,一个用于横向。

我更新了之前为您提供的 GitHub 存储库:https://github.com/DonMag/SpriteKitRotation

这是运行时的样子:https://www.youtube.com/watch?v=ziDqt-ApuSU

© www.soinside.com 2019 - 2024. All rights reserved.