如何关联SKSpriteNode位置与UIBezierPath的currentPoint并实现路径续走?
实现方案
要满足你的需求,核心是保存火车的运动状态和停止位置,并在返回场景时根据状态精准恢复。以下是具体实现步骤和代码调整:
1. 修正现有代码的逻辑错误
你的stopFollowTrainPath()里的guard条件写反了,应该确保myTrain存在时才执行移除动作和保存位置:
func stopFollowTrainPath() { guard let train = myTrain else { return } train.removeAction(forKey: runTrainKey) savedTrainPosition = train.position // 直接保存节点当前位置,无需冗余判断 isTrainMoving = false // 标记为停止状态 }
2. 添加必要的状态变量
在GameViewController或对应的SKScene中添加三个状态变量,用于记录火车的关键状态:
// 标记火车是否处于移动状态 var isTrainMoving: Bool = false // 保存火车停止时的位置 var savedTrainPosition: CGPoint = .zero // 保存动作已执行的时间,用于恢复时精准回到断点 var savedElapsedTime: TimeInterval = 0
3. 优化启动动作的逻辑
在startFollowTrainPath()中添加状态标记,避免重复启动动作:
func startFollowTrainPath() { guard let train = myTrain else { return } // 如果已经在移动,先移除旧动作 if train.action(forKey: runTrainKey) != nil { train.removeAction(forKey: runTrainKey) } let followAction = SKAction.follow( trainPath.cgPath, asOffset: false, orientToPath: true, speed: theSpeed ) let repeatAction = SKAction.repeatForever(followAction) train.run(repeatAction, withKey: runTrainKey) isTrainMoving = true // 标记为移动状态 }
4. 完善停止时的状态记录
更新stopFollowTrainPath(),保存动作已执行的时间,确保恢复时能从断点继续:
func stopFollowTrainPath() { guard let train = myTrain else { return } if let runningAction = train.action(forKey: runTrainKey) { savedElapsedTime = runningAction.elapsedTime train.removeAction(forKey: runTrainKey) } savedTrainPosition = train.position isTrainMoving = false }
5. 返回场景时的恢复逻辑
在场景的didMove(to view:)方法(或GameViewController中切换回场景的回调)中添加恢复逻辑:
func restoreTrainState() { guard let train = myTrain else { return } // 先恢复火车位置 train.position = savedTrainPosition // 如果之前处于移动状态,从断点继续沿路径循环 if isTrainMoving { let pathLength = trainPath.cgPath.length() let totalDuration = pathLength / theSpeed let followAction = SKAction.follow( trainPath.cgPath, asOffset: false, orientToPath: true, speed: theSpeed ) let repeatAction = SKAction.repeatForever(followAction) // 设置时间偏移,让动作从停止的位置继续执行 repeatAction.timeOffset = savedElapsedTime.truncatingRemainder(dividingBy: totalDuration) train.run(repeatAction, withKey: runTrainKey) isTrainMoving = true } }
6. 调用时机
- 切换到其他场景前:调用
stopFollowTrainPath()记录状态 - 回到当前场景后:调用
restoreTrainState()恢复状态
这样就能完全满足需求:
- 之前在移动的火车,从停止位置继续沿路径循环移动
- 之前未移动的火车,保持停止时的位置不动
内容的提问来源于stack exchange,提问作者user22530416
相关产品推荐
相关产品推荐

