I have a scene on top of the main ViewController. While that scene will have objects in it, I'd like the background to be clear.
However
myView.backgroundColor = .clear
myView.allowsTransparency = true
produces a black box.
Am I missing some step?
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
This was something I needed so much help with in this post
https://developer.apple.com/forums/thread/666997
I want to add a user defined setting. As I did (from the answer in the previous post, I made sure I was adding in SWIFTACTIVECOMPILATION_CONDITIONS
I added MYDEBUG01, which does not work. This is in Xcode 12.4
I put up both projects in a picture, the one where it does work is the bottom one, MYSCENES. This was in Xcode 11.x
The screens do look a little different, but can't figure out where my error is.
Here is the screenshot
http:// 98.7.37.117/index.html
I just upgraded to Xcode 12.4, created a project using the "app" template, without SwiftUI, I chose Storyboard instead.
I placed a small image on the LaunchScreen.storyboard, and an NSLog output in my ViewController.
When I run the app on the simulator, the LaunchScreen does not, show, and I do get my NSLog output. So I know the app is running. When run this bare app on my physical iPhone X...I do get the launch screen.
So I opened a game app I started under Xcode 11.x. It will show the LaunchScreen on both simulator and my device.
I've checked that Launch screen interface file base name is set to LaunchScreen in Info.plist. It's also set under App Icons and Launch Images.
Is this some bug?
Haven't touched Xcode since it upgraded to 12.4. Just started a new app, which I planned to create without storyboards. But the default files I am used to deleting or manipulating aren't there anymore. I don't even see AppDelegate.swift.
So did Xcode 12.4 get rid of "storyboards" by default? And if so, where do I go to relearn how to start?
Thanks.
When I'm dealing with touchesBegan, moved, etc. I am able to loop through every item at the CGPoint where the action occurred. So obviously I am dealing with everything through my GameScene.
Now when working with UITapGestureRecognizer, I can't seem to come up with the code that would tell me if there are multiple items at the point of tapping (single tap only). It's not that I want that to happen, but I fear my code may crash if it does occur.
Should UITapGestureRecognizer be handled by each SKNode that uses it? Or is there a code solution where I can handle it all through GameScene?
Here is how I deal with touches_:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?){
				guard let touch = touches.first else { return }
				let location = touch.location(in: self)
				let touchedNodes = self.nodes(at: location)
				for theNode in	touchedNodes{
						if let node = theNode as? MyBall {
.......my code,......
								}
						}
				}
			}
And here's how I handle UITapGestureRecognizer, yet unable to figure out code to see if there's more than one SKNode:
@objc func tappedView(_ sender:UITapGestureRecognizer) {
		if sender.state == .ended{
				let point : CGPoint = sender.location(in: self.view)
var post = sender.location(in: sender.view)
				post = self.convertPoint(fromView: post)
				if let touchNode = self.atPoint(post) as? Ball{
......my code.......
				}
		}
}
My app is very simple. Using all the touchesFunctions, I can drag a ball around the screen
I'd also, like the user to be able to tape the ball, then tap where to place it, hence no dragging. Just tap to select the ball, then tap where to send it.
I added UITapGestureRecognizer to my code.
My problem is that with a tap, touchesBegan and touchesMoved are also triggered. The heavier the user taps, the more touchesMoved are registered. In one test I was able to do an intended tap, and still got 15 touchesMoved before the Tap.
Is there an iOS property that can somehow help me? Because the only other choice I see is writing ugly code that has to compare time so a selection
My problem is that I don't get the tap trigger till the end.
So I can write code to detect time differences, or something else horrendous, or maybe there's a property that can help?
If I have the following SKActions I want done:
let spinAction = SKAction.rotate(byAngle: 360, duration: 003)
let moveAction = SKAction.move(to: CGPoint(x: origNP.x, y: origNP.y), duration: 0.3)
let setFlags = SKAction.run { moveThis.inSlot = true;
		moveThis.isMoving = false; moveThis.inSlot = true}
I know I can either run them in sequence:
let sequence = SKAction.sequence([spinAction, moveAction, setFlags])
or all at once as a group
let group = SKAction.group([spinAction, moveAction, setFlags])
But what if I need to call other sequences, or just reset flags after the sequence or group method is done?
Do they have some sort of notifiers after completion?
I'm currently have an app with 6 balls. I use. the following method to move a Ball. Once it's touched I set its .isMoving property to true, and save the node that was touched into a global variable.
Of course the moment I get a touchesEnded or touchesCanceled, the first thing I do is set the moving property to false, clear the global variable and call a function that animates the ball back to its starting my point.
While this all works, I'm too new to Swift to know if this method has any flaws, or is not the proper/efficient way to do this.
If it makes any difference am catching all touches, and movements in the GameScene.
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?){
		guard let touch = touches.first else { return }
		let location = touch.location(in: self)
		let touchedNodes = self.nodes(at: location)
		for node in	touchedNodes{
				if let theNode = node as? SKSpriteNode {
						if theNode.name == "ball" {
								theNode.zPosition += 1
								node.isMoving = true
								}
						}
				}
		}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?){
		guard touches.first != nil else { return }
		 if let touch = touches.first, let node = myGlobalVars.currentBall, node.isMoving == true{
					let touchLocation = touch.location(in: self)
					node.position = touchLocation
					//redraw node to emulate motion
				}
		}
I am trying to place a border on top of a white block.
When I set the border's Y positioning only based on the height of the block, I get what I expected: The border is half into the block. Screenshot, top half
The next logical step:
I adjust the border's Y position to include half of its own height. What I expect is the bar resting on top of the block. But for some reason, the border is way above the block. Screenshot, bottom half
Am I somehow confusing pixels for points?
When I do take the border's height into account, I use this line:
self.position = CGPoint(x: myGV.safeSceneRect.width/2, y: myGV.gemBaseSize.height + (self.size.height/2)) Below in order:
My code for the border,
Print out of sizes and positions
a link to the two screen shots
import Foundation
import SpriteKit
class MyBorder : SKSpriteNode{
		var nodeType = NodeType.border
		init(){
				 //create SKSpriteNode, size it based on screen size
				super.init(texture: SKTexture(imageNamed: "border"), color: .clear, size: CGSize(width: myGV.safeSceneRect.width, height: myGV.safeSceneRect.height * 0.07))
				self.anchorPoint = CGPoint(x: 0.5, y: 0.5)
				self.isHidden = true
				self.isUserInteractionEnabled = false
				self.zPosition = theZ.border
				self.alpha = 0.5
				// position border on top of block
				self.position = CGPoint(x: myGV.safeSceneRect.width/2, y: myGV.blockBaseSize.height)
				print("Screen Size \(myGV.safeSceneRect)")
				print(“Block Size \(myGV.blockBaseSize)")
				print("Border Size \(self.size)")
				print("Border Pos \(self.position)")
				myGV.gameScene!.addChild(self)
				self.isHidden = false
		}
		required init?(coder aDecoder: NSCoder) {
				fatalError("init(coder:) has not been implemented")
		}
}
Here is the output for both runs, same order as the image
> Screen Size (0.0, 44.0, 375.0, 734.0)
Block Size (300.0, 146.8)
Border Size (375.0, 51.380001068115234)
Border Pos (187.5, 146.8000030517578)
Screen Size (0.0, 44.0, 375.0, 734.0)
Block Size (300.0, 146.8)
Block Size (375.0, 51.380001068115234)
Border Pos (187.5, 172.49000549316406) www .warptv.com/links/screens.png
I wanted to have more than just
#if DEBUG
	 ...
#endif
So in the project editor I added a user-defined setting
Wasn't sure exactly how to label and value, so I've tried
So I've tried it as (under user-defined)
MYSCENE MYSCENE
MYSCENE 1
MYSCENE DEBUG
And yet I can't get #if MYSCENE to work.
Any thoughts?
Rather than do this:
let skTexture = SKTexture(imageNamed: "slot")
let mySlot = SKSpriteNode(texture: skTexture, color: .clear, size: slotSize)
I would like to grab the texture in the call to create the SKSprite. I know I'm supposed to use closures, yet I am unable to figure out the proper syntax.
Am looking for something like:
let mSlot = SKSpriteNode( {texture: SKTexture(imageNamed: "slot") -> (SKTexture)} color: SKColor.clear, size: mySlotSize)
Have tried as many variants as I can think of but never get to the point where I can compile.
If the closure is something that I must predefine, then there's no point in trying this.
My entire project is here www. warptv.com/DropSlot.zip
It's very sloppy and kludgy because I made it while I started to learn Swift.
In the code I make a pegHolder positioned at 10, 10
The pegHolder contains 6 slots,
and each slot holds a different color ball
The pegHolder is a child of GameScene
The slots are children of the pegHolder
and each ball is a child of itsslot
Then I create a barrier on the left side of the screen that runs up and down on an X axis of 5 (although in the end I want it at -1.
For some reason at setup, the red ball is thrown on the other side of the barrier. I can grab it and pull it back, but it shouldn't start being thrown off the screen.
Oddly enough I never register a collision, so it must be something else throwing the ball over. When I tried it with the barrier at the bottom of the screen, the same thing happened.
Any thoughts would be appreciated.
Two days ago I was able to receive touchesBegan (moved, canceled) and now I've lost them. So I shortened the code below, created an SKSpriteNode called redSprite within GameScene...and still I don't receive touches.
While I know my redSprite doesn't fulfill all the if's in the touch functions, I'm placing a breakpoint at the start of the touch functions, and it still won't stop at the breakpoint.
However...if I set GameScene's isUserInteractionEnabled to true, then I do get the touches and the debugger breaks.
import UIKit
import SpriteKit
var redSprite : SKSpriteNode?
class GameScene: SKScene, SKPhysicsContactDelegate {
		override func sceneDidLoad(){
				super.sceneDidLoad()
				#if DEBUG
						print ("GC sceneDidLoad")
				#endif
		}
		
		override func didMove(to view: SKView){
				super.didMove(to: view)
				#if DEBUG
						print ("GC didMove START")
				#endif
				self.isHidden = true
				self.backgroundColor = mySafeColor
				myGlobalVars.backGround = SKSpriteNode(imageNamed: "background")
				myGlobalVars.backGround!.zPosition = theZ.backGround
				myGlobalVars.safeSceneRect = view.frame
				myGlobalVars.gameScene = self
				self.isHidden = false
				self.isUserInteractionEnabled = false
				self.addChild(myGlobalVars.backGround!)
				physicsWorld.contactDelegate = self
				
				
				redSprite = SKSpriteNode(color: .red, size: CGSize(width: 100, height: 100))
				redSprite?.anchorPoint = CGPoint(x: 0.5, y:0.5)
				redSprite?.isHidden = false
				redSprite?.isUserInteractionEnabled = true
				redSprite?.color = .orange
				 redSprite!.name = "test"
				 redSprite?.zPosition = 10
				redSprite?.position = CGPoint(x: (myGlobalVars.safeSceneRect.width/2)-(50), y: myGlobalVars.safeSceneRect.height/2 - 50)
				
				redSprite?.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 100, height: 100), center: CGPoint(x: 0.5, y: 0.5))
				 redSprite?.physicsBody!.affectedByGravity = false
				 redSprite?.physicsBody!.restitution = 0.2
				 redSprite?.physicsBody?.categoryBitMask		= bodyMasks.blankMask.rawValue
				 redSprite?.physicsBody?.contactTestBitMask = bodyMasks.blankMask.rawValue
				 redSprite?.physicsBody?.collisionBitMask	 = bodyMasks.blankMask.rawValue
				
				 self.addChild(redSprite!)
				
				gameTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(runTimedCode), userInfo: nil, repeats: true)
				gameTimer?.tolerance = 0.2
				RunLoop.current.add(gameTimer!, forMode: .common)
				#if DEBUG
						print ("GC didMove END")
				#endif
		}
		override func touchesBegan(_ touches: Set<UITouch>,
															 with event: UIEvent?){
				guard let touch = touches.first else { return }
				let location = touch.location(in: self)
				let touchedNodes = self.nodes(at: location)
				for node in	touchedNodes{
						if let theNode = node as? MyGem {
								if theNode.nodeType == NodeType.gem, theNode.isMoving == false {
										theNode.isMoving = true
										theNode.zPosition += 1
										myGlobalVars.currentGem = theNode
								}
						}
				}
		}
		override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?){
				guard touches.first != nil else { return }
				if let touch = touches.first, let node = myGlobalVars.currentGem, node.isMoving == true {
						let touchLocation = touch.location(in: self)
						node.position = touchLocation
						node.isMoving = true
						node.inSlot = false
						//addTrailToTwinkle(theNode: node)
				}
		}
		
		override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
				 guard touches.first != nil else { return }
				if let _ = touches.first, let node = myGlobalVars.currentGem, node.isMoving == true {
						returnHome(moveThis : node, origNP: node.origPoint)
				}
		}
		
		override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
						guard touches.first != nil else { return }
						if let _ = touches.first, let node = myGlobalVars.currentGem, node.isMoving == true {
						returnHome(moveThis : node, origNP: node.origPoint)
						}
				}
		
		@objc func runTimedCode() {
			timeLeft -= 1
		}
}
Below is my abbreviated code, the full code does work.
It starts at GameViewController, create GameScene, and GameScene creates an SKSpriteNode.
What's confusing me is the debug output which just tracks where I am in my app (shown in the abbreviated code).
The debug output is at the very bottom of this post.
I wonder about the order of execution, the last debug msg is the end of GameViewController...I would have thought I'd be done with that already.
i.e. How do I know that everything I'm setting in GVC is setup before it's needed in GC?
On a side note, I've tried Googling "SKScene lifecycle" and can't seem to find the proper documentation.
GameViewController
class GameViewController: UIViewController {
		override func viewDidLoad() {
				super.viewDidLoad()
				#if DEBUG
						print ("GVC viewDidLoad")
				#endif
				
				... create myView (as an SKView)
				... add it as a subview of GameViewController
				... use myView to get constraints
... and set other properties
				myView.isHidden						 = false
				myView.ignoresSiblingOrder		= true
				myView.showsFPS							 = true
				myView.showsNodeCount				 = true
				myView.showsPhysics					 = true
		}
		override func viewWillLayoutSubviews() {
				super.viewWillLayoutSubviews()
				#if DEBUG
						print ("GVC viewWillLayoutSubviews")
				#endif
		}
		 func viewDidAppear() {
				super.viewDidAppear(true)
				#if DEBUG
						print ("GVC viewDidAppear")
				#endif
		}
		override func viewDidLayoutSubviews() {
				super.viewDidLayoutSubviews()
				#if DEBUG
						print ("GVC viewDidLayoutSubviews START")
				#endif
				... get the view.frame
				... record some properties in my global variables				
				
... launch GameScene here
				if myGlobalVars.gameScene == nil {
						let scene = GameScene(size: myView.frame.size )
						scene.anchorPoint = CGPoint(x: 0.0, y: 0.0)
						scene.backgroundColor	 = .clear
						scene.scaleMode				 = .aspectFit
						myGlobalVars.gameScene = scene
						myView.presentScene(scene)
				}
				#if DEBUG
						print ("GVC viewDidLayoutSubviews END")
				#endif				
		}
		
		override var shouldAutorotate: Bool {
				return false
		}
		override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
				if UIDevice.current.userInterfaceIdiom == .phone {
						return .portraitUpsideDown
				} else {
						return .all
				}
		}
		override var prefersStatusBarHidden: Bool {
				return false
		}
}
GameScene
class GameScene: SKScene, SKPhysicsContactDelegate {
		override func sceneDidLoad(){
				super.sceneDidLoad()
				#if DEBUG
						print ("GC sceneDidLoad")
				#endif
		}
		
		override func didMove(to view: SKView){
				super.didMove(to: view)
				#if DEBUG
						print ("GC didMove START")
				#endif
				... load background image
				physicsWorld.contactDelegate = self
				
				... create just one SKSpriteNode
				createGems(myGemRef: &myGems)
				#if DEBUG
						print ("GC didMove END")
				#endif
		}
}
GVC viewDidLoad
GVC viewWillLayoutSubviews
GVC viewDidLayoutSubviews START
GC sceneDidLoad
GC didMove START
SKNode create SKSPriteNode start
SKNode create SKSPriteNode end
GC didMove END
GVC viewDidLayoutSubviews END
I am trying to create four walls, that would surround the screen.
From GameScene I call
let leftWall = MyEdge(side: Walls.left)
The code below works. But then I cannot add it as a child to GameScene, also I would like to give it an SKPhysicsBody.
My problem is figuring out the super.init. I've tried
super.init(texture: nil, color: .clear, size: CGPath(w: 0, h: 0))
super.init()
But I always get
Type of expression is ambiguous without more context
class MyEdge {
		let yourline = SKShapeNode()
		let pathToDraw = CGMutablePath()
		var color : SKColor
		var startAt : CGPoint
		var endAt : CGPoint
		var colMask : UInt32
		var conMask : UInt32
		var catMask : UInt32
		var name : String
		init(side: Walls){
				let whichWall = side
				switch whichWall
				{
						case .left:
myGlobalVars.backGround!.size.height+1)
								startAt = CGPoint(x: 5, y: 5)
								endAt = CGPoint(x: 5, y: myGlobalVars.safeSceneRect.size.height-5)
								color = .white
								colMask = bodyMasks.gemMask.rawValue
								conMask = bodyMasks.blankMask.rawValue
								catMask = bodyMasks.edgeMask.rawValue
								name = "left"
				}
				pathToDraw.move(to: startAt)
				pathToDraw.addLine(to: endAt)
				yourline.lineWidth = 2
				yourline.path = pathToDraw
				yourline.strokeColor = color
		}
}