Very Basic Node Removal in Swift - swift

I found some other questions about node removal in swift, but none of them seemed to be quite relevant to my issue.
I just want to do a basic node removal, for example:
override func touchesBegan(touches: NSSet, withEvent event: UIEvent){
let covernode1 = SKSpriteNode(imageNamed: "tester")
covernode1.position = CGPointMake(100.0, 600.0)
for touch: AnyObject in touches {
if self.nodeAtPoint(location) == self.fake {
button1++
button2++
}
if(button1 == 1 && button2 == 1){
addChild(covernode1)
}
if(button1 == 2 && button2 == 2){
//THIS IS WHERE I WANT TO REMOVE THE NODE
}
I have tried
covernode1.removeFromParent()
but to no avail.
The code runs the addChild part fine, but removal seems to be a problem. I even tried just changing the position of the node so it's off screen, with something like
covernode1.position = CGPointMake(-100.0, -600.0)
This did not work either.
Thank you.

Unfortunately I don't have enough reputation to comment on your original question, so this may not be an "answer" per se, but I'll try and diagnose what I think is going on, and hopefully you can clear up some points for me.
The covernode1 that you are trying to remove from the parent view in your if statement may be a different node than the one you added to the view when you called addChild(covernode1)
I think this is the case because when you say you are using covernode1.position = CGPointMake(-100.0, -600.0) and it still does not work, that makes me think that is a completely different SKNode object.
Instead, try declaring covernode1 outside of the function as a class variable. That way, when you actually instantiate it and refer to it in the function, it is grabbing the correct node you are looking for. Let me know if any of this helps. I'll edit the answer when I know a bit more from your response.
Also, are your button1 and button2 vars originally set to 1?
EDIT: Another question: Are you receiving any error when calling .removeFromParent() or is just "not doing anything"?

One simple thing you could do (kind of cheating but it will work) is to hide the node using
covernode1.hidden = true
Note
Also make sure the if statement actually runs because I don't know why the things you tried should not work. To test that, place a println("log") in the if block.
Hope that helps :)

From button1 and button2, I think you are trying to do this: On the first click, you add a SKNode. On the second click, you want to remove the SKNode.
Thus on the second click your let covernode1 = SKSpriteNode(imageNamed: "tester") is a different instance although it has the same variable name ! Thus the instance on the second click is not removable since it was not added to anything.
Try this,
if(button1 == 1 && button2 == 1){
addChild(covernode1)
self.tempChildCount = count(self.children) //tempChildCount is an integer
}
if(button1 == 2 && button2 == 2){
let childNode = self.children[self.tempChildCount - 1 ] as! SKNode
self.removeChildrenInArray([childNode])
}

Related

Change the color of all nodes in a scene?

So this may seem like a stupid question; however, I'll see if anyone has an answer.
Is there any way to change the color of all nodes in a scene in swift? For example invert all the colors?
I've created a game using SpriteKit and would like to create different themes. Instead of changing every node one by one. I would like to at least do most in one shot. If anyone has any advice that would be greatly appreciated! Thanks!
-Matt
Inside of the scene you want,
for node in self.children {
// I used spritenode, but you can add as many nodes with color options as you like.
guard let snode = node as? SKSpriteNode else { continue }
snode.color = .blue
}
The inversion function would be a separate question I think :P but something like:
if snode.color == .black { node.color == .white }
But you could probably do this with RGB and math as well.

sceneDidLoad Running Twice

When I run my program. The code I put into "override func sceneDidLoad()" runs two times.
E.g.
Note: I have no idea why this picture is not uploading, but it shows "spawn" happening twice.
This code should only run once when "sceneDidLoad()" is called.
Here is the code for the "sceneDidLoad" function, and for the "testSpawn()" function (which is the specific one that gave the duplicated printout).
class GameScene: SKScene {
var mapTerrain: SKTileMapNode!
override func sceneDidLoad() {
cam = SKCameraNode()
cam.xScale = 1
cam.yScale = 1
//do zoom by change in scale in pinch. (E.g. if they start out 5 units apart and end up 15 units apart, zoom by a factor of 3
self.camera = cam
self.addChild(cam)
cam.position = CGPoint(x: 100, y: 100)
setupLayers()
loadSceneNodes()
setUpUI()
testSpawn()
//print("\(self.frame.width), \(self.frame.height)")
}
func testSpawn(){
let RedLegion = legion(texture: textureRedLegion, moveTo: nil, tag: 1, health: 2)
RedLegion.position = mapTerrain.centerOfTile(atColumn: 0, row: 0)
RedLegion.team = "Red"
unitsLayer.addChild(RedLegion)
legionList.append(RedLegion)
print("spawn")
}
}
Note: Not all of the code is here (like "setUpLayers()"), if needed I can supply it, I just do not think it is neccessary.
Search your whole document for "print("spawn")" just to make sure that is the only time you call the function. Also check for "testSpawn()" to make sure it is only called once. Additionally, instead of relying on this print to count how many times the sceneDidLoad runs, place a print directly within your sceneDidLoad. Finally, check to make sure you are not creating the scene twice.
I've also seen this and submitted a bug report but apple responded saying that it is intended behavior. Apple said that it creates a dummy scene and then creates the actual scene. Before it runs the second time it gets rid of anything done the first time so you shouldn't get any errors from it. The bug is really hard to reproduce, one of my friends working off the same repository that I was but did not experience the bug.
I changed sceneDidLoad to didMoveToView:(SKView *)view if you are looking for a solution to this. Make sure you xcode is up to date.

Respawning a node after it's been deleted? Swift Spritekit

Once a node is removed, I'm needing to respawn it back to it's original position.
I've tried a few things:
1) In the didBeginContact where it gets deleted, I've just added an addChild() after the delete, but that just added it back where it was, making it look like it just paused in place
2) When it dies, I'm setting a variable to 0, and I created a function that adds the node back where it starts out, and then I set up an if statement that looks like :
if playerLife == 0 {
spawnPlayer()
}
and the player life gets set to 0 down in my didBeginContact. Don't know if that even makes sense
3) I tried slapping all of this down in the didBeginContact
The ball is either freezing when I try to addchild directly back right after I delete it in the DidBegin, otherwise it gets deleted and never is respawned.
Try moving your code inside of the update function. also in your spawnPlayer function make sure to add your node if node.parent == nil
override func update(currentTime: NSTimeInterval) {
if playerLife == 0 {
spawnPlayer()
}
}

SKScene Pausing briefly When SKLabelNode's text is changed

I am programming a small game using SpriteKit
I added a SKLabelNode to my SKScene with the initial text of just "0".
When I try and update the text of this SKLabel using:
func updateScoreLabel() {
scoreNumber++
scoreLabel.text = String(scoreNumber)
}
There is a short pause of the entire SKScene between when it gets called and then when it is updated.
However this only happens the first time it is called so If I am running this a second time as in updating the scoreLabel any subsequent time the Scene Pausing then the pause does not occur.
what is triggering the method call is... CC is an enum of physicsBody categoryBitMasks typed to Int
func isCollisionBetween(nodeTypeOne: CC, nodeTypeTwo: CC, contact: SKPhysicsContact) -> Bool {
let isAnodeTypeOne = contact.nodeA.physicsBody!.categoryBitMask == nodeTypeOne.rawValue
let isAnodeTypeTwo = contact.nodeA.physicsBody!.categoryBitMask == nodeTypeTwo.rawValue
let isBnodeTypeOne = contact.nodeB.physicsBody!.categoryBitMask == nodeTypeOne.rawValue
let isBnodeTypeTwo = contact.nodeB.physicsBody!.categoryBitMask == nodeTypeTwo.rawValue
if (isAnodeTypeOne && isBnodeTypeTwo) || (isAnodeTypeTwo && isBnodeTypeOne) {
return true
} else {
return false
}
}
then if
if isCollisionBetween(CC.TypeA, nodeTypeTwo: CC.TypeB, contact: contact) {
updateScoreLabel()
}
Can someone please point out the problem. The score updating does not pause the scene when the same collision is detected and a println statement is used to output the score so I think it is specific to changing the text of the SKLabelNode
You should check for two things which for sure can cause the lag:
for typos in a font name
that you are not loading entire font family, ie Arial instead of just Arial-BoldMT or Arial-ItalicMT. You want to be specific, because loading entire font family can make a delay when using certain fonts. List of iOS fonts could be found here.
If you need to list available fonts(and see real font names), you can use something like this:
for familyName in UIFont.familyNames() as [String] {
println("\(familyName)")
for fontName in UIFont.fontNamesForFamilyName(familyName) as [String] {
println("\tFont: \(fontName)")
}
}
When initializing label for the first time (say at the moment when collision occurs) the delay may happen if you are using custom fonts which are not available in iOS.
In that case try to "preload" a font before using the label. So before actual gameplay, you should instantiate SKLabelNode and set its text property to some value. You have to set a text property, because by doing that the font will be preloaded and ready for use. Otherwise it will be loaded at the time you set label's text property.
EDIT:
Sorry, I just noticed that you are said that you are initializing already a label with initial text. So the just ignore part of my answer related to that and look for typos and the part about loading specific font.
Hope this will take you somewhere. Good luck!

How can I remove all nodes from a scenekit scene?

Hi I am trying to remove all nodes from my Scenekit scene but I cannot for the life of me figure out a way.
It seems logical to me that there must be a function for doing this automatically but I cannot find it.
In context, I am trying to remove all nodes so I can reset my scene, which will happen reasonably often. Perhaps there is another way of doing this and I would be fine with that, I'm not stuck with having to remove all nodes.
Thanks!
Try this (assuming you are using Swift):
rootNode.enumerateChildNodes { (node, stop) in
node.removeFromParentNode()
}
Works for me.
For me worked like below:
sceneView.scene.rootNode.enumerateChildNodes { (node, stop) in
node.removeFromParentNode() }
you can either create a new scene or call -[SCNNode removeFromParentNode] on every child node of the scene's rootNode
Where you need to remove all of your nodes, call this (if your scene isn't self, change it):
for (SCNNode *node in [self children]) {
[node removeFromParent]
}
Additionally, if you need to remove each node except for some, call this (say, we don't want to remove 3 nodes, and they're named a, b, and c)
for (SCNNode *node in [self children]) {
if (![node.name isEqualToString:#"a"] && ![node.name isEqualToString:#"b"] && ![node.name isEqualToString:#"c"]) {
[node removeFromParent]
}
}
Hope this helps!
Here is a solution in Objective-C (Yes it still exists!)
while (self.sceneView.scene.rootNode.childNodes.count) {
NSArray<SCNNode *> *nodes = self.sceneView.scene.rootNode.childNodes;
[nodes[0] removeFromParentNode];
}
Modifying a collection while looping through it is not good practice; here's an alternative:
while let n = node.childNodes.first { n.removeFromParentNode() }
the simplest way I found to remove all nodes from a scene is:
self.removeAllChildren()
This worked well for me in XCode version 7.2