After rotation, a new one has not been created. This is for certain because the SKSpriteNode follows the old one if it's moving before rotation. However, if I stop the movement before the rotation within viewDidLayoutSubviews() and resume the movement after the rotation, a new UIBezierPath is created. But what I want is to replace the UIBezierPath while moving when rotation happens. If you scroll up my OP, you will see that my viewDidLayoutSubviews() calls createTrainPath() which needs ? to be called during this rotation.
As already noted, I have tried to effectively delete the old UIBezierPath by removing all the .cgPath [CGPoint] before calling setTrackPaths() (instead of stopping the movement and then resuming). Please note that my setTrackPaths() calls createTrainPath(). Unfortunately, the old Path stuck around with its old [CGPoint] and was never replaced by createTrainPath() when the latter called trainPath = UIBezierPath(ovalIn: trackRect).
It just dawned on me that the problem could rest with my call to trackRect = CGRect(x:, y:, width:tracksWidth, height:tracksHeight). I say that because with rotation, the width and height parts change. Never mind ... I just deleted that guess because my call to setGamePieceParms() occurs before setTrackPaths() .. and the former changes tracksWidth and tracksHeight. Back to the drawing board ...
Post
Replies
Boosts
Views
Activity
I have even tried to delete the current UIBezierPath by calling trainPath.cgPath.getPoints().removeAll and then re-create it when the UIDevice is rotated. Once again, visually it shows that the SKSpriteNode follows the old UIBezierPath
Elsewhere, someone properly suggested to change viewWillLayoutSubviews to viewDidLayoutSubviews.
This makes total sense because I wish to generate a new UIBezierPath after rotation when all the SKSpriteNodes have been resized and repositioned. Regrettably this did not work. So, I'm still on the prowl for the correct solution.
From: Apple Developer Support ...
I believe you can achieve what you are aiming for by using a "pivot" node.
Effectively, you would add your "myTrain" node as a child of the "pivot".
Then you would run the "trainAction" on the "pivot" instead of "myTrain".
This allows "myTrain" to maintain its local zRotation relative to the path,
but still follow the path.
==
It’s seemingly funny how things work out .. I was very recently asked who my favorite college prof was and why.
I responded “Dr. Leno Pedrotti who taught Quantum Mechanics in Grad School. The reason I choose him as my favorite is because he was consistently able to reduce the extraordinarily convoluted subject to the simple, using simple and short statements in the process.”
The above writer from Apple Developer Support was made from the same mold as Dr. Pedrotti.
FWIW, we’re talking circa 1963 in case you “youngsters” are curious.
To continue, here is my code wherein I “attempted” to implement the above writer’s concise solution:
func moveTrainForward() {
// trackPath + myTrain = globals
let forwardTrackPath = trackPath
let trainAction = SKAction.follow(
forwardTrackPath!.cgPath,
asOffset: false,
orientToPath: true,
duration: 0.1)
createPivotNode(forSpriteNode: myTrain)
myTrain.run(trainAction)
} // moveTrainForward
And here is the key createPivotNode:
func createPivotNode(forSpriteNode: SKSpriteNode) {
let nodeGeometry = SCNBox(width: forSpriteNode.size.width,
height: 1,
length: forSpriteNode.size.height,
chamferRadius: 0)
let theSCNNode = SCNNode(geometry: nodeGeometry)
// create "pivot" node
theSCNNode.pivot = SCNMatrix4MakeTranslation(0.5, 0.5, 0.5)
if let ourSceneNode = SCNScene(named: "GameScene") {
// effectively add "myTrain" node as a child of the "pivot" ???
ourSceneNode.rootNode.addChildNode(theSCNNode)
}
} // createPivotNode
Unfortunately, the above does not prevent the rotation mentioned in my OP.
I don't know for certain, but I think the core of this not working rests with my comment effectively add "myTrain" node as a child of the "pivot" ???
In conclusion, I need some further elaboration from my college prof.
I don’t know if this is proper to say .. but I have been working on this rotation issue for a very long time and I need some serious help here.
It is totally clear to me that I am in a total fog ...
When I set up my GameScene.sks within Xcode, I produced this:
which I set as 1366 x 1366
The frame: designation below is in line with the anchor setting .. so the fog continues as to why the blue UIBezierPath is not showing
// print("ourScene = \(ourScene)")
// ourScene = <SKScene> name:'GameScene'
// frame:{{-683, -683}, {1366, 1366}}
// anchor:{0.5, 0.5}
Once again, my head got confused between:
tracksPosY = roomPosY - roomHeight/2 + tracksHeight/2
where the .position is negative below the (0, 0) = center of the Scene and positive above (0, 0)
With this UIBezierPath, the top of the CGRect is positive below the (0, 0) as exhibited by these data:
// (l,t,r,b)
// trackRect = (0.0, 207.0, 1024.0, 476.0) // portrait
// trackRect = (0.0, 36.0, 1366.0, 476.0) // landscape
// trackRect = (0.0, 64.0, 1920.0, 476.0) // osTV
The bad news is that I still don't see a blue line anywhere.
Given that, I am still doing something insanely wrong.
I'm beginning to think my problem is with this statement:
theTrackShapeNode.position = myTracks.position
This is seriously suspect only because of the above-mentioned flip-flop of .position. and the CGRect.
What do you think?
Thanks bunches, Claude31.
Unfortunately it didn't work .. and I take full responsibility for that because I feel I did not fully explain all the details necessary to describe my goal ..
I faithfully inserted all the code your doc stated should be placed within my viewDidLoad. It compiled okay.`
My GameViewController consists of 2 vertical halves. The bottom shows several animated SKSpriteNodes that move. This bottom half is not the subject of my quest for help.
It's the top half that contains my GameStaticObjects. As you can see in the above screen shot, this struct comprises 2 rows of static objects using HStack and Vstack. I discovered the latter that docs said would cause them to spread out edge-to-edge as the destination iPad rotated 90 degrees. In short, as the length of the string along which these HStack objects were strung, they would spread out and go edge-to-edge of the parent window frame.
Before GameStaticObjects, these SKSpriteNodes were added in the addGamePieces function of my GameViewController via aSKScene.addChild(aSKSpriteNode). As already noted, however, the just talked about edge-to-edge rendition did not happen .. not to mention the fact there was a lot of hard coding required to set the position of each of these static objects.
So, here I am .. I added all the code specified in your doc reference to my viewDidLoad function and nothing happened.
I'm tempted to think that I need to add a small amount of code to the above addGamePieces function.
I really apologize for being too wordy here .. but I don't know to do it differently so you are fully aware of where I am.
The thought of selecting offsets based on width & height of Simulator is totally repulsive ...
So there's gotta be an optimum solution.
For what it's worth,
Mini size = 744 X 1133,
11" Pro size = 834 X 1194,
Air size = 820 X 1180,
12.9" size = 1024 X 1366
for Portrait orientation.
A very, very interesting observation:
In my iPad Computer Game already uploaded to the App Store, I don't have any code that calls:
targetEnvironment(macCatalyst)
Yet, when in the distant past, this previous iPad Game of mine became available for download from the App Store, just on a whim, I downloaded it to my iMac Desktop to see what would happen. It worked with Ventura and Sonoma. ASAMOF, in its Supported Destinations, I just had iPad with zero mention of Mac (Designed for iPad).
SO, I eliminated any testing for targetEnvironment(macCatalyst) in the above #if and set the Product's Destination to My Mac (Designed for iPad)
AND IT WORKED!
Bottom Line = apparently I don't need to test for targetEnvironment.
Anyway, sorry to bother you folks with what turned out to be a very simple correction.
Once again a big Shout Out to DTS with whom I opened up an offical TSI.
DTS responded that the true culprit is most likely LOG NOISE = Errors or Warnings that do not stop my Code from working. Their effect is superficial, versus substantial.
They specifically mentioned several of the posts here by Quinn the Eskimo which essentially conclude that I ignore this LOG NOISE as long as my Code remains 100% functional.
DTS also re-credited my TSI Count.
CHEERS!! CHEERS!! CHEERS!!
Why can't I edit the OP ...
Anyway,
Here is the CORRECT code which I call within my GameViewController's viewDidLoad().
func setupMovie(theMovieName: String) {
guard let path = Bundle.main.path(forResource: "movies/" + theMovieName,
ofType:"mp4") else {
print("movie not found")
return
}
itsMoviePlayer = AVPlayer(url: URL(fileURLWithPath: path))
itsPlayerController = AVPlayerViewController()
itsPlayerController?.player = itsMoviePlayer
itsMovieIsFinished = true
} // setupMovie
One last statement = if I comment out the call to NotificationCenter => Error stays => my call to present is the most likely suspect.
You’re a Saint for sticking this out
Error happens when
-(a-b)
but not
(b-a)
WHEN /2
NO Error anywhere when /2.0
Go Figure
OK,
This WORKS
if (playerPosY - playerHeight/2) <= -(roomHeight/2.0 - kFudge)
{
}
NOT
if (playerPosY - playerHeight/2) <= -(roomHeight/2 - kFudge)
{
}
BUT, THIS WORKS
if false
{
}
else if (playerPosY - playerHeight/2) <= -(roomHeight/2 - kFudge)
{
}
NOW, I hope you are screaming like I am ... Misery Loves Company