Posts

Post not yet marked as solved
0 Replies
46 Views
Here is a link to a super long conversation with a true genius at StackOverflow https://stackoverflow.com/questions/78343630/what-algorithm-is-available-to-correlate-a-skspritenodes-position-with-the-uibe/78379892#78379892 He has done an extraordinary amount of work to make up for what I consider is the non-working of UIBezierPath’s orientToPath = true. He’s done multiple hours work to make up for orientToPath = true not working. What are we missing?
Posted
by JohnLove.
Last updated
.
Post marked as solved
1 Replies
270 Views
I know that this is not a coding question and I have posted on the regular Apple Forum and have been working with the 800 Tech Support folk for 4 months. I am in a world of hurt. Have ATV + Samsung TV + external soundbar. All software versions are current NO Cable box (direct input). 4 months ago I had Cable box = zero problems. With Samsung on and ATV off, stereo = Dolby 5.1 sounds great. With ATV also on, no stereo. I can use Siri remote to activate stereo until I change to a new movie. ATV then reverts to mono = PCM One Tech Support lady said to just not watch multiple movie. ?$@!*+^? I have spoken with engineers at Samsung and Sonos (soundbar). Both say my cabling is correct = 1 cable from soundbar to HDMI Arc on TV + 1 cable from ATV to another HDMI port on TV. Another Tech Support folk said to connect ATV to soundbar. Soundbars don’t have gobs of HDMI ports, the TV does. ?!$@*^+%# I have spoken with Apple Tech Support with zero help for 3-4 months. I think I have been a good soldier. But it is time for real results. Please help
Posted
by JohnLove.
Last updated
.
Post marked as solved
5 Replies
405 Views
Detecting touching a SKSpriteNode within a touchesBegan event? My experience to date has focused on using GamepadControllers with Apps, not a touch-activated iOS App. Here are some short code snippets: Note: the error I am trying to correct is noted in the very first snippet = touchesBegan within the comment <== shows "horse" Yes, there is a "horse", but it is no where near the "creditsInfo" SKSpriteNode within my .sksfile. Please note that this "creditsInfo" SKSpriteNode is programmatically generated by my addCreditsButton(..) and will be placed very near the top-left of my GameScene. override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { if let ourScene = GameScene(fileNamed: "GameScene") { if let touch:UITouch = touches.first { let location = touch.location(in: view) let node:SKNode = ourScene.atPoint(location) print("node.name = \(node.name!)") // <== shows "horse" if (node.name == "creditsInfo") { showCredits() } } } // if let ourScene } // touchesBegan The above touchesBegan function is an extension GameViewController which according to the docs is okay, namely, touchesBegan is a UIView method besides being a UIViewController method. Within my primary showScene() function, I have: if let ourScene = GameScene(fileNamed: "GameScene") { #if os(iOS) addCreditsButton(toScene: ourScene) #endif } with: func addCreditsButton(toScene: SKScene) { if thisSceneName == "GameScene" { itsCreditsNode.name = "creditsInfo" itsCreditsNode.anchorPoint = CGPoint(x: 0.5, y: 0.5) itsCreditsNode.size = CGSize(width: 2*creditsCircleRadius, height: 2*creditsCircleRadius) itsCreditsNode.zPosition = 3 creditsCirclePosY = roomHeight/2 - creditsCircleRadius - creditsCircleOffsetY creditsCirclePosX = -roomWidth/2 + creditsCircleRadius + creditsCircleOffsetX itsCreditsNode.position = CGPoint(x: creditsCirclePosX, y: creditsCirclePosY) toScene.addChild(itsCreditsNode) } // if thisSceneName } // addCreditsButton To finish, I repeat what I stated at the very top: The error I am trying to correct is noted in the very first snippet = touchesBegan within the comment <== shows "horse"
Posted
by JohnLove.
Last updated
.
Post marked as solved
4 Replies
327 Views
How to detect the location of a mouseDown event using Swift? With the following code snippet, I get the error "Cannot find type 'NSEvent' in scope"? import SpriteKit func mouseDown(with event: NSEvent) { if let ourScene = GameScene(fileNamed: "GameScene") { 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?
Posted
by JohnLove.
Last updated
.
Post not yet marked as solved
6 Replies
562 Views
How to integrate UIDevice rotation and creating a new UIBezierPath after rotation? My challenge here is to successfully integrate UIDevice rotation and creating a new UIBezierPath every time the UIDevice is rotated. (Please accept my apologies for this Post’s length .. but I can’t seem to avoid it) As a preamble, I have bounced back and forth between NotificationCenter.default.addObserver(self, selector: #selector(rotated), name: UIDevice.orientationDidChangeNotification, object: nil) called within my viewDidLoad() together with @objc func rotated() { } and override func viewWillLayoutSubviews() { // please see code below } My success was much better when I implemented viewWillLayoutSubviews(), versus rotated() .. so let me provide detailed code just for viewWillLayoutSubviews(). I have concluded that every time I rotate the UIDevice, a new UIBezierPath needs to be generated because positions and sizes of my various SKSprieNodes change. I am definitely not saying that I have to create a new UIBezierPath with every rotation .. just saying I think I have to. Start of Code // declared at the top of my `GameViewController`: var myTrain: SKSpriteNode! var savedTrainPosition: CGPoint? var trackOffset = 60.0 var trackRect: CGRect! var trainPath: UIBezierPath! My UIBezierPath creation and SKAction.follow code is as follows: // called with my setTrackPaths() – see way below func createTrainPath() { // savedTrainPosition initially set within setTrackPaths() // and later reset when stopping + resuming moving myTrain // via stopFollowTrainPath() trackRect = CGRect(x: savedTrainPosition!.x, y: savedTrainPosition!.y, width: tracksWidth, height: tracksHeight) trainPath = UIBezierPath(ovalIn: trackRect) trainPath = trainPath.reversing() // makes myTrain move CW } // createTrainPath func startFollowTrainPath() { let theSpeed = Double(5*thisSpeed) var trainAction = SKAction.follow( trainPath.cgPath, asOffset: false, orientToPath: true, speed: theSpeed) trainAction = SKAction.repeatForever(trainAction) createPivotNodeFor(myTrain) myTrain.run(trainAction, withKey: runTrainKey) } // startFollowTrainPath func stopFollowTrainPath() { guard myTrain == nil else { myTrain.removeAction(forKey: runTrainKey) savedTrainPosition = myTrain.position return } } // stopFollowTrainPath Here is the detailed viewWillLayoutSubviews I promised earlier: override func viewWillLayoutSubviews() { super.viewWillLayoutSubviews() if (thisSceneName == "GameScene") { // code to pause moving game pieces setGamePieceParms() // for GamePieces, e.g., trainWidth setTrackPaths() // for trainPath reSizeAndPositionNodes() // code to resume moving game pieces } // if (thisSceneName == "GameScene") } // viewWillLayoutSubviews func setGamePieceParms() { if (thisSceneName == "GameScene") { roomScale = 1.0 let roomRect = UIScreen.main.bounds roomWidth = roomRect.width roomHeight = roomRect.height roomPosX = 0.0 roomPosY = 0.0 tracksScale = 1.0 tracksWidth = roomWidth - 4*trackOffset // inset from screen edge #if os(iOS) if UIDevice.current.orientation.isLandscape { tracksHeight = 0.30*roomHeight } else { tracksHeight = 0.38*roomHeight } #endif // center horizontally tracksPosX = roomPosX // flush with bottom of UIScreen let temp = roomPosY - roomHeight/2 tracksPosY = temp + trackOffset + tracksHeight/2 trainScale = 2.8 trainWidth = 96.0*trainScale // original size = 96 x 110 trainHeight = 110.0*trainScale trainPosX = roomPosX #if os(iOS) if UIDevice.current.orientation.isLandscape { trainPosY = temp + trackOffset + tracksHeight + 0.30*trainHeight } else { trainPosY = temp + trackOffset + tracksHeight + 0.20*trainHeight } #endif } // setGamePieceParms // a work in progress func setTrackPaths() { if (thisSceneName == "GameScene") { if (savedTrainPosition == nil) { savedTrainPosition = CGPoint(x: tracksPosX - tracksWidth/2, y: tracksPosY) } else { savedTrainPosition = CGPoint(x: tracksPosX - tracksWidth/2, y: tracksPosY) } createTrainPath() } // if (thisSceneName == "GameScene") } // setTrackPaths func reSizeAndPositionNodes() { myTracks.size = CGSize(width: tracksWidth, height: tracksHeight) myTracks.position = CGPoint(x: tracksPosX, y: tracksPosY) // more Nodes here .. } End of Code My theory says when I call setTrackPaths() with every UIDevice rotation, createTrainPath() is called. Nothing happens of significance visually as far as the UIBezierPath is concerned .. until I call startFollowTrainPath(). Bottom Line It is then that I see for sure that a new UIBezierPath has not been created as it should have been when I called createTrainPath() when I rotated the UIDevice. The new UIBezierPath is not new, but the old one. If you’ve made it this far through my long code, the question is what do I need to do to make a new UIBezierPath that fits the resized and repositioned SKSpriteNode?
Posted
by JohnLove.
Last updated
.
Post not yet marked as solved
0 Replies
236 Views
I submitted a TSI about 3 weeks ago. Got an automated reply giving me my TSI ID. Unfortunately I cannot find that ID anywhere. Can any of you detectives find that ID for me? I guess I am a little curious as to when one of their super smart DTS programmers will contact me. My Bad John Love
Posted
by JohnLove.
Last updated
.
Post not yet marked as solved
0 Replies
273 Views
How do I change a UIBezierPath.currentPoint to a SKSpriteNode.position? Here are the appropriate code snippets: func createTrainPath() { let startX = -tracksWidth/2, startY = tracksPosY savedTrainPosition = CGPoint(x: startX, y: startY!) trackRect = CGRect(x: savedTrainPosition.x, y: savedTrainPosition.y, width: tracksWidth, height: tracksHeight) trainPath = UIBezierPath(ovalIn: trackRect) trainPath = trainPath.reversing() // makes myTrain move CW } // createTrainPath Followed by: func startFollowTrainPath() { let theSpeed = Double(5*thisSpeed) var trainAction = SKAction.follow( trainPath.cgPath, asOffset: false, orientToPath: true, speed: theSpeed) trainAction = SKAction.repeatForever(trainAction) createPivotNodeFor(myTrain) myTrain.run(trainAction, withKey: runTrainKey) } // startFollowTrainPath So far, so good (I think?) ... Within other places in my code, I call: return trainPath.currentPoint I need to convert trainPath.currentPoint to myTrain.position ... When I insert the appropriate print statements, I see for example: myTrain.position = (0.0, -295.05999755859375) trainPath.currentPoint = (392.0, -385.0) which obviously disqualifies a simple = , as in: myTrain.position = trainPath.currentPoint Since this = is not correct, what is ? After more investigation, my guess is that .currentPoint is in SKSpriteNode coordinates and .position is in SKScene coordinates.
Posted
by JohnLove.
Last updated
.
Post not yet marked as solved
0 Replies
237 Views
Why does orient Path = true cause the sprite node to rotate CW when the path is horizontal? Here's just one example: let trainAction = SKAction.follow( trainPath.cgPath, asOffset: false, orientToPath: true, duration: 0.1) myTrain.run(trainAction.reversed()) I have myTrain.zRotation = 0.0 myTrain is a simple locomotive,trainPath = the railroad tracks Docs state with orientToPath: true, that the Node will always orient itself such that it's facing the UIBezierPath. To me, facing means that the wheels of the locomotive are facing the BezierPath (= trainPath) Apparently I am wrong in this interpretation ... if so, what is the correct interpretation? FYI, comparing the snapshot of my initial placement of the locomotive on the tracks using .position with what happens after I start moving the locomotive: These snapshots indicate that facing means that the nose of the locomotive is facing the BezierPath (= trainPath). If true, how do I eliminate that CW rotation?
Posted
by JohnLove.
Last updated
.
Post not yet marked as solved
0 Replies
242 Views
How do I change just the starting point of an existing UIBezierPath? .. and leave all other points the same? I have definitely seen many posts on how to do this .. honestly, I just do not understand many of them My existing path has one .move(to:) and many .addLine(to:) My goal is: (1) replace the .move(to:) with .addLine(to:) and then (2) change one of the .addLine(to:) with .move(to:) All other CGPoints stay the same. In order to get the new starting point, I set: savedPathPoint = myPath.currentPoint when I stop the following motion. At some point, I want to resume this following motion with the new starting point = savedPathPoint via myPath.move(to: savedPathPoint) let myAction = SKAction.follow( myPath.cgPath, asOffset: false, orientToPath: true, duration: 0.1) mySprite.run(myAction) When I look at the above problem description, it really appears simple. Nevertheless, its implementation alludes me. Thanks bunches in advance for any hints whatsoever.
Posted
by JohnLove.
Last updated
.
Post not yet marked as solved
3 Replies
361 Views
Problem = I have a locomotive trying to follow an oval-shaped UIBezierPath. The challenge is that when I use orientToPath:true in my call to SKAction.follow, the locomotive immediately rotates even though the locomotive is initially positioned on the straight portion of the oval before it reaches the rounded portion of the oval. If I could prevent this initial rotation, then the rotation would not happen until it reached the rounded portion of the oval - as it should. So, can you please provide some guidance as to how I could prevent this initial rotation? Here is the code: func createTrainPath() { // this custom method ensures that the locomotive // moves CW, versus CCW trackPath = getBezierPath(theNode: myTrain, offset: 0.0) } // createTrainPath func startFollowTrainPath() { let theSpeed = Double(5*thisSpeed) var trainAction = SKAction.follow( trackPath.cgPath, asOffset: true, orientToPath: true, // <== speed: theSpeed) trainAction = SKAction.repeatForever(trainAction) myTrain.run(trainAction, withKey: runTrainKey) } // startFollowTrainPath
Posted
by JohnLove.
Last updated
.
Post not yet marked as solved
0 Replies
209 Views
How to attach a struct to the main GameViewController? This struct occupies the top half of the main ViewController. The goal is to have this struct be part of the main GameViewController and not in separate UIHostingController. SO, when I rotate the main SKScene for example the struct also rotates OR when I switch SKScenes both the top-half struct and the bottom-half switch together because they are one SKScene. The programmer who invented HStacks and VStacks is a blooming genius … but I need to avoid what I have now which is the HStack VStack combo closing and then its neighbors in the main SKScene closing. Here are the essential code segments - all in my GameViewController: Declared at the top: var useGSO = false var gsoChildVC: UIViewController! // = UIHostingController override func viewDidLoad() { showScene() /* "gso" = "Game Static Objects" */ if useGSO { // create a UIHostingController and extract a rootView for later processing gsoChildVC = UIHostingController(rootView: GameStaticObjects()) } } // viewDidLoad Within my showScene(): func addGamePieces(toScene: SKScene) { if thisSceneName == "GameScene" { // various SKSpriteNodes // // STATIC People, Animals and Buildings // are now added to the top of our SKScene // addGSOChild(toScene: toScene) } // if thisSceneName == "GameScene" else { removeGSOChild() } } // addGamePieces func addGSOChild(toScene: SKScene) { // gsoChildVC = nil *if* useGSO = false guard gsoChildVC == nil else { let gsoParentVC = self // parent = us = GameViewController // default value // gsoChildVC.view.translatesAutoresizingMaskIntoConstraints = true /**/ let sameWidth = gsoParentVC.view.bounds.width let newHeight = 0.5 * gsoParentVC.view.bounds.height let boundsWithNewBottom = CGRectMake(0.0, 0.0, sameWidth, newHeight) gsoChildVC.view.frame = boundsWithNewBottom /**/ // first, add the view of the hild to the view of the parent gsoParentVC.view.addSubview(gsoChildVC.view) // then, add the child to the parent gsoParentVC.addChild(gsoChildVC) // notify the child ViewController that we're finished gsoChildVC.didMove(toParent: gsoParentVC) return } } // addGSOChild func removeGSOChild() { // gsoChildVC = nil *if* useGSO = false guard gsoChildVC == nil else { // First, remove the Child from its Parent gsoChildVC.removeFromParent() // Then, remove the Child's view from the Parent's gsoChildVC.view.removeFromSuperview() return } } // removeGSOChild As stated at the top of this OP, the HStack and Stack code appears great .. but the UIHostingController is distinct from my GameViewController. As a direct result, such operations as switching SKScenes is done in 2 halves - (1) the HStack and Stack top half and (2) whatever non-struct stuff appears below it. If I switch SKScenes, I want both halves to switch as one entity. FWIW, the struct that contains the HStack and Stack code is outside the GameViewController class as suggested by Apple. and as specified above, I call: gsoChildVC = UIHostingController(rootView: GameStaticObjects()) within my viewDidLoad() method. I would love some basic guidance here as to what basic error I am making.
Posted
by JohnLove.
Last updated
.
Post not yet marked as solved
3 Replies
348 Views
I am developing a game in which my Locomotive is following a UIBezierPath that mimics an oval shaped Track. The math of the following is not "adding up" .. if it is, I am obviously not understanding the math of the layout. Bottom line = the following code does not display the UIBezierPath. Here's the code that creates this UIBezierPath .. please note the math in the comments: func createTrainPath() { trackRect = CGRect(x: 0.0, y: 0.0 - roomHeight/2 + tracksHeight, width: tracksWidth, height: tracksHeight) // trackRect = (0.0, -207.0, 940.0, 476.0) // portrait // trackRect = (0.0, -274.0, 470.0, 238.0) // landscape print("trackRect = \(trackRect!)") trackPath = UIBezierPath(ovalIn: trackRect) let theTrackShapeNode = SKShapeNode(path: trackPath.cgPath, centered: true) theTrackShapeNode.zPosition = 100 // for testing theTrackShapeNode.position = myTracks.position theTrackShapeNode.lineWidth = 4.0 theTrackShapeNode.strokeColor = SKColor.blue if let ourScene = GameScene(fileNamed: "GameScene") { print("here") // this shows ourScene.addChild(theTrackShapeNode) // does *not* show? } } // createTrainPath In Portrait mode, the UIScreen measures 1024 x 1366 and the Track measures 940 x 476 with its top edge down 207 from the center of the UIScreen. In Landscape mode, the UIScreen measures 1366 x 1024 and the Track measures 470 x 238 with its top edge down 274 from the center of the UIScreen. In both modes, the bottom edge of the Track is supposed to be flush with the bottom edge of the UIScreen .. and it is. If the math is correct, then I am obviously not understanding the math of the layout .. because the UIBezierPath is not showing. The math appears correct .. but the UIBezierPath just is not showing. So where is my brain off-center?
Posted
by JohnLove.
Last updated
.
Post not yet marked as solved
0 Replies
285 Views
Do I really have to reset position and size of SKSpriteNodes with every rotation between landscape and portrait layout?? I've done that and it works .. but this seems to be overkill that the writers of Xcode internally compensated for .. vs. having the individual programmer having to do it. I have a getGameParms() which resets positions based on: #if os(iOS) && !targetEnvironment(macCatalyst) func getGameParms() { let roomRect = UIScreen.main.bounds roomWidth = roomRect.width * roomScale roomHeight = roomRect.height * roomScale if (thisSceneName == "GameScene") { if UIDevice.current.orientation.isLandscape { // changes here } else { // changes } } // if (thisSceneName == "GameScene") } // getGameParms #elseif os(tvOS) func getGameParms() { let roomRect = UIScreen.main.bounds roomWidth = roomRect.width * roomScale roomHeight = roomRect.height * roomScale if (thisSceneName == "GameScene") { // other changes here } } // getGameParms #endif Again, the burdensome changes are done .. but are they really necessary? As an alternative, I have called getGameParms() just once within my viewDidLoad() and the results are not correct. For example, I place one SKSpriteNode at the very bottom of the UIScreen and it does not stay there with UIDevice rotation. I also size it horizontally such that it expands to the full width of the UIScreen. Rotation destroys that. if getGameParms() is called only once as just described. Some explanation as to why would be appreciated.
Posted
by JohnLove.
Last updated
.
Post not yet marked as solved
1 Replies
267 Views
Can you access the objects in a struct from outside the struct? So far I have a group of HStacks and VStacks whose embedded objects are all Images(“name”). By definition these Images are fixed in terms of their .position and .size for example. Can I dynamically access these embedded objects from outside the struct? In short, move them? .. or include a Node so I could change its color? All changes made from Swift outside the struct?
Posted
by JohnLove.
Last updated
.
Post not yet marked as solved
0 Replies
242 Views
Can you access the objects in a struct from outside the struct? So far I have a group of HStacks and VStacks whose embedded objects are all Images(“name”). By definition these Images are fixed in terms of their .position and .size for example. Can I dynamically access these embedded objects from outside the struct? in short, move them ?
Posted
by JohnLove.
Last updated
.