Nickoflaus Nickoflaus - 5 months ago 23
Swift Question

Access Constant from outside Function Swift

I have a game that runs like this: The class file is run and uses the function "addObject()" to an add an object to the screen. The object then falls from the top of the screen to the bottom and the player has to try to catch the object by tapping on it. However, the object is declared (as an SKSpriteNode)in the addObject function. So when I go to add the "touch controls" function to the game, I can't reference the object. What can I do to fix this? Here is some of my code:

class GameSceneTest: SKScene, SKPhysicsContactDelegate {

var ObjectDestroyed = 0
let label = SKLabelNode(fontNamed: "Title 1")
var money: Int = 0

override func didMoveToView(view: SKView) {

backgroundColor = SKColor.clearColor()
physicsWorld.gravity = CGVectorMake(0, 0)
physicsWorld.contactDelegate = self


//Change duration
runAction(SKAction.repeatActionForever(SKAction.sequence([SKAction.runBlock(addObject), SKAction.waitForDuration(1)])
))

}

func random() -> CGFloat {
return CGFloat(Float(arc4random()) / 0xFFFFFFFF)
}

func random(min min: CGFloat, max: CGFloat) -> CGFloat {
return random() * (max - min) + min
}

func addObject() {


let Object = SKSpriteNode(imageNamed: "Object\(arc4random_uniform(6) + 1).png")
Object.size = CGSize(width: 50, height: 50)
Object.physicsBody = SKPhysicsBody(rectangleOfSize: Object.size)
Object.physicsBody?.dynamic = true

//Determine where to spawn Object across y axis

let actually = random(min: Object.size.width/2, max: size.width - Object.size.width/2)

//Position Object slightly off screen along right edge
//and along random y axis point
//Object.position = CGPoint(x: size.width + Object.size.width/2 , y: actually)

Object.position = CGPoint(x: actually, y: size.height + Object.size.height/2)

//Add the Object to the scene

addChild(Object)

//Determines speed of Object (edit later to where speed depends on type of Object)

let actualDuration = random(min: CGFloat(4), max: CGFloat(5))

//Create the Actions

let actionMove = SKAction.moveTo(CGPoint(x: actually, y: gem.size.height/2), duration: NSTimeInterval(actualDuration))

let actionMoveDone = SKAction.removeFromParent()

let loseAction = SKAction.runBlock() {
let reveal = SKTransition.flipHorizontalWithDuration(0.5) //Change to flipe vertical
let gameOverScene = GameOverScene(size: self.size, won: false)
self.view?.presentScene(gameOverScene, transition: reveal)
}



Object.runAction(SKAction.sequence([actionMove, loseAction, actionMoveDone]))
}



override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch = touches.first!

if Object.containsPoint(touch.locationInNode(self)) {
Object.removeFromParent()
print("touched")
}
}


}

Answer

There are several different ways that you could correctly implement this. One option would be to make an class level variable that is an array of type SKSpriteNode and append the objects to it when you create them in that function.

// Declare an array variable at the class level
var objectArray = [SKSpriteNode]()
// Then in the function after you create the object and configure it
objectArray.append(object)

Another alternative would be to use a dictionary that you add the new objects to. It just depends on exactly what you need to do with the objects when you reference them again.

Note: This answer assumes that you will have multiple objects that you need reference to at any given time. If you only need reference to one at a time, you can just make a class level variable of type SKSpriteNode and set it in your addObject function

For Example:

// Declaring class level variable
var myNode: SKSpriteNode?

When your addObject method is called, set myNode equal to the object that you create and configure

// When you go to use myNode, just unwrap it to make sure that it has a value
if let unwrappedNode = self.myNode {
    // Do something with unwrappedNode
}