Naming Sprites compared to i in for loop(swift) - swift

I was running into this problem that instead of writing this:
let enemy1 = SKSpriteNode(imageNamed: "enemy")
let enemy2 = SKSpriteNode(imageNamed: "enemy")
let enemy3 = SKSpriteNode(imageNamed: "enemy")
over and over again and making a thousand enemies, I would just make a for loop like this:
for i in 1...1000{
let enemy(i) = SKSpriteNode(imageNamed: "enemy")
}
but as you would know just doing enemy(i) doesn't work.
If you know the answer to this problem or can help me in any way by sugesting any other technique please reply.
Any help would be much appreciated :)

for statement is like this:
for value in range {
statements
}
I've written a simple example:
As #ColGraff mentiond. for the name of the enemy you can code like this: SKSpriteNode(imageNamed: "enemy\(i)"). but not as the name of the variable.
var enemy = [SKSpriteNode]()
for _ in 1...1000 {
enemy.append(SKSpriteNode(imageNamed: "enemy"))
// or use this:
// enemy[i] = SKSpriteNode(imageNamed: "enemy")
}

Related

Assigning texture to SKSpriteNode is not working

Changing the texture of a SKSpriteNode is not working
I'm trying to learn SpriteKit and am running into something that is puzzling me. I am trying to display a sprite. I try two methods that should work, but only one is actually causing the sprite to be displayed on the screen! I would really like to actually understand why. Can anybody help?
This works:
func loadLevel() {
let point: CGPoint = CGPoint(x:300,y:300)
var block = SKSpriteNode(imageNamed: "Block_blue")
block.position = point
self.addChild(block)
}
This does not:
func loadLevel() {
let point: CGPoint = CGPoint(x:300,y:300)
var block = SKSpriteNode()
block.position = point
block.texture = SKTexture(imageNamed: "Block_blue")
self.addChild(block)
}
I would expect both functions to result in displaying the sprite, but only the first works? I would like to understand what is going on here.

swift - use an integer for loop in a variable's name

I' like to doe something like this :
for i in 0...3 {
let skspritenode\(i) = SKSpriteNode(imageNamed: "Layer_\(i)")
self.addChild(skspritenode\(i))
}
that doesn't work because my skspritenode(i) is a let and not a string
and I have tried this:
for i in 0...3 {
let skspritenode = SKSpriteNode(imageNamed: "Layer_\(i)")
self.addchild(skspritenode)
}
which doesn't work because skspritenode already has a parent.
Is there a way of doing this in a for loop or do i have to declare each let separately? Thank you in advanced
Why would you need to name each node differently? skspritenode variable is scoped in for loop, thus the following code should work just fine:
for i in 0...3 {
let skspritenode = SKSpriteNode(imageNamed: "Layer_\(i)")
self.addchild(skspritenode)
}
Your point
which doesn't work because skspritenode already has a parent
is incorrect, since you're creating new SKSpriteNode on each iteration.

Swift SpriteKit unwrapping and wrapping

func bombTowerTurnShoot() {
let zombieGreen = self.childNode(withName: "zombie") as! SKSpriteNode
self.enumerateChildNodes(withName: "bomb tower") {
node, stop in
if let bombTower = node as? SKSpriteNode {
let angle = atan2((zombieGreen.position.x) - bombTower.position.x, (zombieGreen.position.y) - bombTower.position.y)
let actionTurn = SKAction.rotate(toAngle: -(angle - CGFloat(Double.pi/2)), duration: 0.2)
bombTower.run(actionTurn)
}
}
}
My issue is on the let angle line. When I call the function when there is no zombieGreens on the scene I get a Thread 1 problem. How can I change the code to take into account when the zombie is not present?
if there is no ZombiGreens in the scene the error should happen already at the second line:
let zombieGreen = self.childNode(withName: "zombie") as! SKSpriteNode
I think the simplest solution without changing to much of your code would be to use an if let just as you did for the bomb tower. and it would look something like this:
func bombTowerTurnShoot() {
if let zombieGreen = self.childNode(withName: "zombie") as? SKSpriteNode{
self.enumerateChildNodes(withName: "bomb tower") {
node, stop in
if let bombTower = node as? SKSpriteNode {
let angle = atan2((zombieGreen.position.x) - bombTower.position.x, (zombieGreen.position.y) - bombTower.position.y)
let actionTurn = SKAction.rotate(toAngle: -(angle - CGFloat(Double.pi/2)), duration: 0.2)
bombTower.run(actionTurn)
}
}
}
}
But it could be a good idea to review your code when you have more logic to handle. it might be a better way to do things but this should work :)

SKAction Updating Last Instantiated Sprite Only

teaching myself spritekit while recouping from back surgery. Any help or instruction you may provide is greatly appreciated.
I have a function that adds a "monster" sprite with a child SKEmitter. I would like to update this emitter to "turn on" and "turn off" the SKEmitter. This functions as long as there is only a single sprite on the screen. The moment a second node is created from the function, the first one stops turning on and off.
It appears to me that the SKAction is only acting on the latest node. I just can't anything that would tell me how to fix this.
Example of what I see in the UI.
My code:
flameThrowerSplash = SKEmitterNode(fileNamed: "flamesThrowerSplash.sks")!
let newX = flameThrowerSplash.position.x - 475
let newY = flameThrowerSplash.position.y + (zombie1.size.height * 0.7)
let newLocation = CGPointMake(newX, newY)
flameThrowerSplash.position = newLocation
flameThrowerSplash.targetNode = currentScene
let wait = SKAction.waitForDuration(0.5)
let pauseEmitter = SKAction.runBlock({self.flameThrowerSplash.particleBirthRate = 0})
let startEmitter = SKAction.runBlock({ self.flameThrowerSplash.particleBirthRate = 455})
let wait2 = SKAction.waitForDuration(0.5)
let run = SKAction.sequence([wait, startEmitter,wait2, pauseEmitter])
zombie1.runAction(SKAction.repeatActionForever(run))
it doesnt look like you want flameThrowerSplash to be a scene property.
instead of this
flameThrowerSplash = SKEmitterNode(fileNamed: "flamesThrowerSplash.sks")!
just declare it as a new variable
let flameThrowerSplash = SKEmitterNode(fileNamed: "flamesThrowerSplash.sks")
then you can add it to each zombie independently.
you were reassigning it for each new zombie.. thats why it was disappearing.

Detect if a SKSpriteNode left the screen at the bottom and call a function

I have tried to find a way to detect if a SKSpriteNode left the screen (I would like to call a Game Over function).
I have declared the node within a function (It is not global if I get that right?) and made and SKAction that moves the Node out of the screen and removes it afterwards.
This is what I came up with:
var node = SKSpriteNode()
let nodeTexture = SKTexture(imageNamed: "node")
nodeTexture.filteringMode = .Nearest
node = SKSpriteNode(texture: nodeTexture)
let nodeFalling = SKAction.moveToY(-70, duration: 1.6)
let nodeRemoving = SKAction.removeFromParent()
node.runAction(SKAction.sequence([nodeFalling, nodeRemoving]))
self.addChild(node)
Now what I need is to call GameOver() if the node left the screen.
I am very thankful for every answer!
In your scene you have to remember the reference for node you want to check and then in update method you just do the following:
if node.position.y < -node.size.height/2.0 {
node.removeFromParent()
gameOver()
}
Edit:
class MyScene: SKScene {
// ....
//here is the list of nodes which you want to check
var nodesToCheck = [SKSpriteNode]()
//here is your spawn function
func spawnNewNode() {
var node = SKSpriteNode()
let nodeTexture = SKTexture(imageNamed: "node")
nodeTexture.filteringMode = .Nearest
node = SKSpriteNode(texture: nodeTexture)
let nodeFalling = SKAction.moveToY(-70, duration: 1.6)
let nodeRemoving = SKAction.removeFromParent()
node.runAction(SKAction.sequence([nodeFalling, nodeRemoving]))
self.addChild(node)
nodesToCheck.append(node)
}
//and here is the update method
override func update(currentTime: NSTimeInterval) {
super.update(currentTime)
// ... every other update logic
for node in nodesToCheck {
if node.position.y < -node.size.height/2.0 {
node.removeFromParent()
gameOver()
}
}
}
func gameOver() {
println("Damn!")
}
}
Dont forget to remove your node from nodeToCheck array when they are no longer scene members.