Stopping and then re-starting a SKSpriteNode
not behaving when moving along the bottom half of an oval UIBezierPath
Works great when moving along top half; just the bottom half that produces a problem.
Code works with the train moving along the top half of the oval; i.e., the train stops and restarts where it previously stopped and the train images remain in-tact.
But, along bottom half, multiple cars all squeezed together and train cars don’t restart where I stopped them.
Here are hopefully the required code snippets = (using @DonMag’s brilliant Ellipse code)
Path creation:
func createTrainPath() {
trainRect = CGRect(x: tracksPosX - tracksWidth/2,
y: tracksPosY - tracksHeight/2,
width: tracksWidth,
height: tracksHeight)
trainPoints = generatePoints(inRect: trainRect,
withNumberOfPoints: nbrPathPoints)
trainPath = generatePathFromPoints(trainPoints!,
startingAtIDX: savedTrainIndex)
} // createTrainPath
Start and Resume movement code:
func resumeFollowTrackPaths() {
// Resets each Path based on each saved,,Index
// when previously stopped.
gameScene.setGameNodePaths()
// Now, resume where we left off at saved..Index.
startFollowTrackPaths()
} // resumeFollowTrackPaths
func setGameNodePaths() {
// delete any old Paths before creating new ones:
itsGameViewController.deleteBezierPaths()
itsGameViewController.createTrainPath() // + the cars
} // setGameNodePaths
func startFollowTrainPath() {
var trainAction = SKAction.follow(trainPath.cgPath,
asOffset: false,
orientToPath: true,
speed: thisSpeed)
trainAction = SKAction.repeatForever(trainAction)
myTrain.run(trainAction, withKey: runTrainKey)
} // startFollowTrainPath
Stop movement code:
func stopFollowTrainPath() {
guard (myTrain != nil) else { return }
myTrain.removeAction(forKey: runTrainKey)
savedTrainPosition = myTrain.position
savedTrainIndex = closestIndexInPath(
trainPath,
toPoint: savedTrainPosition) ?? 0
} // stopFollowTrainPath
GameScene’s update(..) code (from John at Apple DTS + @DonMag):
override func update(_ currentTime: TimeInterval) {
super.update(currentTime)
let t = myTrain.position
if t.y < trainPath.bounds.midY && trainIsOnTopOfOval
{
trainIsOnTopOfOval = false
itsGameViewController.stopAnimatedTrain()
// Thanks, John - DTS
itsGameViewController.initAnimatedTrainHere("bottom")
itsGameViewController.startAnimatedTrain()
// set orientation of each car = that of myTrain
myCoalcar.texture = coalcarBottom
myFreightcar.texture = freightcarBottom
myBaggagecar.texture = baggagecarBottom
}
else if t.y > trainPath.bounds.midY && !trainIsOnTopOfOval
{
trainIsOnTopOfOval = true
itsGameViewController.stopAnimatedTrain()
itsGameViewController.initAnimatedTrainHere("top")
itsGameViewController.startAnimatedTrain()
// set orientation of each car = that of myTrain
myCoalcar.texture = coalcarTop
myFreightcar.texture = freightcarTop
myBaggagecar.texture = baggagecarTop
}
} // update
As stated above, code works with the train moving along the top half of the oval; i.e., the train stops and restarts where it previously stopped and the train images remain in-tact.
Code goes south when train moving along bottom half of the oval. Not 100% certain, but I think the problem surfaces when I re-create the BezierPath starting at the stopped Index. Just a wild guess at this point.