如何在节点围绕 UIBezierPath 移动时停止节点,然后从停止的位置重新开始移动?

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

请参阅本文底部的 Apple DTS 解决方案...

我有一个椭圆形

UIBezierPath
和一个移动的
SKSpriteNode
,

我停止它的运动并记录停止的位置。然后我重新启动这个动作并希望它在最初停止的地方重新启动。

如果运动“没有”停止,

效果很好。整个椭圆形路径的运动非常好。 只要这个停止-重新启动顺序发生在椭圆形的上半部分

UIBezierPath

,效果也很好。然而,我在这条路径的下半部分遇到了问题——它停止得很好,但重新启动位置

不是
之前停止的位置。 我创建这个椭圆形

UIBezierePath

的方法如下:

func createTrainPath() {
    
    trainRect = CGRect(x: tracksPosX - tracksWidth/2,
                       y: tracksPosY - tracksHeight/2,
                       width: tracksWidth,
                       height: tracksHeight)

    // these methods come from @DonMag
    trainPoints = generatePoints(inRect: trainRect,
                                 withNumberOfPoints: nbrPathPoints)
    trainPath = generatePathFromPoints(trainPoints!,
                                       startingAtIDX: savedTrainIndex)
            
}   // createTrainPath

我停止这个动作的方法如下:

func stopFollowTrainPath() { guard (myTrain != nil) else { return } myTrain.isPaused = true savedTrainPosition = myTrain.position // also from @DonMag savedTrainIndex = closestIndexInPath( trainPath, toPoint: savedTrainPosition) ?? 0 } // stopFollowTrainPath

最后,我再次呼吁这个动议:

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

再次强调,如果运动“没有”停止,那就太好了。整个椭圆形路径的运动非常好。

再次,沿着椭圆形的上半部分停止然后重新启动没有问题..哦哦发生在下半部分。 我在 GameScene 的更新方法中是否缺少一些需要做的事情?例如,我需要重建我的

UIBezierPath

吗?每当我的节点在上半部和下半部之间移动时,就说明该节点从上半部向相反的方向移动?

=====已解决=====

我在暂停游戏后放置了print("pause index =", savedTrainIndex)

并得到了160,例如我还放置了

print("resume index =", savedTrainIndex)
before 恢复并得到了 160,因为节点沿着椭圆形的上半部分移动。
然后,当节点沿着椭圆形的下半部分移动时,我得到了 90。
这是我从 Apple Deve;loper 技术支持处收到的回复 - 效果完美:

当您在节点上运行跟随操作时,SpriteKit 会将节点的位置设置为所提供路径的起始位置。

您观察到的问题(当火车在位置上发生大幅跳跃时)是由于节点的当前位置与跟随路径的起始位置相比存在较大差异而引起的。

这种巨大的差异是由于代码中的错误造成的,特别是在closestPointInPath函数中,该函数似乎是一种算法,试图确定路径上最接近节点当前位置的点,然后您可以使用该点计算新跟随路径的起点。

如果用这个函数替换该函数(其中包含一个简单的实现来查找距目标点最近的点),您将看到不再发生大的位置跳跃:

public func closestPointInPath(_ path:UIBezierPath, toPoint:CGPoint) -> CGPoint? { let targetPoint = toPoint let thePoints = getPointsForPath(path) var closestPoint = CGPoint.zero var minDistance = CGFloat.infinity for point in thePoints { let distance = distanceBetween(point, targetPoint) if distance < minDistance { minDistance = distance closestPoint = point } } return closestPoint }

先生。 Apple DTS 的 Chistie 非常棒。

再一次,我劳动了3周,DTS在3天内解决了问题。

这是暂停/取消暂停的简单示例

SKAction
swift sprite-kit uibezierpath skspritenode
1个回答
© www.soinside.com 2019 - 2024. All rights reserved.