"By definition, there is no such button for os(tvOS)"
Post
Replies
Boosts
Views
Activity
"By definition, there is no such button for os(tvOS)"
The Apple Docs state:
If **orientToPath** = true, the node’s **zRotation** property animates so that the node turns to follow the path. If false, the **zRotation** property of the node is unchanged.
I have initialized zRotation = 0.0 (no rotation) and to both +1.0 and -1.0 which initializes the train's zRotation accurately. But as soon as motion begins, the train immediately rotates 90 degrees on its own ??
I have been at this for a good 3-ish weeks, with total failure.
After 3+ months, I talked with Tim from Apple Support
Solution = disconnect your soundbar‘s HDMI cable going to the TV’s ARC port and connect it to non-ARC port.
RESTART ATV
My soundbar‘s Stereo components = sub woofer + surround sound wall speakers emit sound no matter how many different movies I switch between.
Reason = ATV has problems with the ARC port connected to anything in the ATV chain (which obviously includes the soundbar).
HERE is the THE answer ...
Make touchesBegan an extension of GameScene, not GameViewController with:
extension GameScene {
// "if we set isUserInteractionEnabled = false, the Scene will receive touch events"
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
// not needed because addCreditsButton() isn't called
// unless we're staring at "GameScene"
// if let ourScene = GameScene(fileNamed: "GameScene") {
if let touch:UITouch = touches.first {
let location = touch.location(in: self)
let ourNode:SKNode = atPoint(location) // not ourScene.atPoint(location)
// print("location = \(location)")
print("ourNode.name = \(ourNode.name!)")
if (ourNode.name == "creditsInfo") {
showCredits()
}
} // if let touch:UITouch
// } // if let ourScene
} // touchesBegan
Strictly speaking this is not the answer, but I present here what the last comment above talks about - but in a much more readable format. Hopefully this will generate some much needed help:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let ourScene = GameScene(fileNamed: "GameScene") {
if let touch:UITouch = touches.first {
var position = CGPoint()
let location = touch.location(in: ourScene)
position.x = -roomWidth/2 + location.x
position.y = roomHeight/2 - location.y
let node:SKNode = ourScene.atPoint(position)
if (node.name == "creditsInfo") {
showCredits()
}
}
} // if let ourScene
} // touchesBegan
Please note that with the above touchesBegan, the node.name is not "creditsInfo", but "room" which is the SKSpriteNode immediately below my itsCreditsNode. "room" has zPosition = 0 versus 5 for itsCreditsNode. So, my itsCreditsNode is not seen.
Finally, note that my addCrreditsButton(...) presented at the top of this Post will not change
ALMOST THERE (1) change "let" to "var" + (2) add location.x = -roomWidth/2 + location.x & location.y = roomHeight/2 - location.y which together changes the view coordinates of the original location to match the node.location. I know I am on the right track because besides the "horse", I have several buildings and 2 people added directly to the .sks file. An appropriate print("\(node.name)") prints the names of the buildings + people. BUT, this does not work for my itsCreditsNode since this node is programmatically added, versus added to the .sks file. ??
I did check my .zPosition numbers and they were okay. I even set its .zPosition to a crazy 20 - no change. I also checked that node.isHidden = false and it is. So, it appears your statement that location is the culprit. As a matter of interest, physically this "info" SKSpriteNode is physically very close to the top-left corner .. so I clicked very close to this location and got, for example (1.0, 30.0). No matter how precise I tried to get (0.0, 0.0) I could never get that close vertically. So, that truly mystifies me. One last thing: .anchorPoint = (0.5, 0.5) AHAH = it's a circle with radius = 40.0, a left-edge offset from left scene border = 50.0 and a top-edge offset from top scene border = 15.0 That number = 30.0 mentioned above still bugs me greatly.
(1) an iOS App
(2) Someone else nailed it when he effectively stated that I called an iOS App with a macOS func mouseDown(with event: NSEvent). Actually, func mouseDown(with event: UIEvent) doesn't exist. iOS Apps deal with touches, not mouse clicks, obviously
(3) I've got touches covered with override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {...}
(4) BUT, I am hung up with how do I see if my code works with touches within Xcode?
(5) Folk have their mouse linked to their iPad via Bluetooth ?
I think I need to re-group and start from scratch ... I am so, so sorry:
FWIW, your corrections are "spot on" if I were dealing with a macOS App, but I have a iOS App:
How to detect the location of a mouseDown event using Swift?
With the following code snippet, I get the error "Value of type 'UIEvent' has no member 'location' in scope"?
import SpriteKit
extension GameViewController {
func mouseDown(with event: UIEvent) {
if let ourScene = GameScene(fileNamed: "GameScene") {
// error here:
let location = event.location(in: view)
let node:SKNode = ourScene.atPoint(location)
if (node.name == "creditsInfo") {
showCredits()
}
} // if let ourScene
} // mouseDown
}
Anybody have a floodlight to shine on this very basic error?
In view of the fact that "something is better than nothing", I have decided (with rotation and the Train is moving) to:
(1) stop the movement
(2) delete the trackPath via
func deletePath(_ thePath:UIBezierPath) {
var thePoints = thePath.cgPath.getPoints()
thePoints.removeAll()
} // deletePath
FWIW, getPoints() is an extension CGPath that I found elsewhere.
(3) call createTrainPath() which starts the new UIBezierPath from the original starting point
(4) finally call resumeGame() which calls startFollowTrainPath()
It is 100% absolutely certain that this is much less than I desire which is to replace (3) with a new UIBezierPath which starts where the Train was before I rotated the UIDevice
So, that challenge is still on the table ...
In the meantime, I need to attack the very, very last challenge which is summarized here:
https://stackoverflow.com/questions/77903234/why-does-orient-path-true-cause-the-sprite-node-to-rotate-cw-when-the-path-is
I reference stack overflow.com because they allow presenting .pngs in an effort to show what the problem is all about.
John Love
TO: Albert from DTS .. You have acknowledged receipt of my complete bare bones Project.
You keep asking for a simple Project, but I can honestly say that the Project you've received is bare bones and simple.
I have led you step-by-step through (1) loading of my SKSpriteNodes, (2) running the Train with a Game Controller and (3) while the Train is moving, using Xcode to rotate the SKScene. Following this 3 step process, I see how, for example, If I am looking at Portrait mode, I see the moving Train following the old Landscape path.
Like, while staring at Portrait mode, the Train disappears off the left edge and right edge of the UIDevice.
= the OLD path
In conclusion, I must very, very regretfully conclude that I must seek help elsewhere.
Bye.
Whoops ... you have to use a Game Controller to run the App
FWIW - this eventual App actually will never be finished. I will always be expanding it, for example:
(1) a track winding thru all sorts of hills
(2) an animated waterfall
(3) a hero galloping on a horse to rescue a damsel in distress
There'll be a version 1.1, 1.2, 1.3 etc.
I'm retired military and with the short term assignments (2 years between moving to somewhere else), I couldn't afford the time to set up an HO Train Set in my basement. So, this is the next best thing.
Reference my comment above:
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
Next:
if let ourScene = GameScene(fileNamed: thisSceneName) {
// Force SKScene to fill up its parent SKView:
if (thisSceneName == "GameScene") { ourScene.scaleMode = .aspectFill }
else { ourScene.scaleMode = .resizeFill }
}
My rotation code is within:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if (thisSceneName == "GameScene") {
setGamePieceParms() // for GamePieces, e.g., trainWidth + dogWidth
setTrackPaths() // for trainPath + dogPath, etc.
reSizeAndPositionNodes()
} // if (thisSceneName == "GameScene")
} // viewDidLayoutSubviews
I chose it over:
#if os(iOS) && !targetEnvironment(macCatalyst)
NotificationCenter.default.addObserver(self,
selector: #selector(rotated),
name: UIDevice.orientationDidChangeNotification,
object: nil)
#endif
@objc func rotated() {
if (thisSceneName == "GameScene") {
setGamePieceParms() // for GamePieces, e.g., trainWidth + dogWidth
setTrackPaths() // for trainPath + dogPath, etc.
reSizeAndPositionNodes()
} // if (thisSceneName == "GameScene")
} // rotated
Anyway, I've got a complete focused Project as .zip, so how do I get it to you since you've chosen to reply within this Forum?
I have investigated altering the pivot point of the SKSpriteNode .. I have even changed its anchorPoint .. no change. I am definitely ready to cry "Uncle" here.