Astrum Astrum - 4 months ago 14
Swift Question

creating multiple sprite nodes with slight variations?

I have a game menu that displays multiple achievements which are defined as SKSpriteNodes there are 18 of them and they only have slight variations in the positioning, here is a snippet of the code:

Achievement1 = SKSpriteNode(color: SKColor.whiteColor(), size: CGSize(width: 100, height: 100))
Achievement1.position = CGPointMake(-120, 100)
page1ScrollView.addChild(Achievement1)

Achievement2 = SKSpriteNode(color: SKColor.whiteColor(), size: CGSize(width: 100, height: 100))
Achievement2.position = CGPointMake(0, 100)
page1ScrollView.addChild(Achievement2)

Achievement3 = SKSpriteNode(color: SKColor.whiteColor(), size: CGSize(width: 100, height: 100))
Achievement3.position = CGPointMake(120, 100)
page1ScrollView.addChild(Achievement3)

Achievement4 = SKSpriteNode(color: SKColor.whiteColor(), size: CGSize(width: 100, height: 100))
Achievement4.position = CGPointMake(-120, -25)
page1ScrollView.addChild(Achievement4)


Also I have gone to great lengths to define all of them one by one as vars as seen here:

var Achievement1: SKSpriteNode!
var Achievement2 = SKSpriteNode()
var Achievement3 = SKSpriteNode()
var Achievement4 = SKSpriteNode()
var Achievement5 = SKSpriteNode()
var Achievement6 = SKSpriteNode()
var Achievement7 = SKSpriteNode()
var Achievement8 = SKSpriteNode()


It looks like a complete mess and just takes up too much space. I want to be able to define all of the sprite nodes and have them all able to be pressed to display a box that states what the achievement is for like so:

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

let touch: UITouch = touches.first!
let location: CGPoint = touch.locationInNode(self)
let node: SKNode = self.nodeAtPoint(location)


if (node == Achievement1) {

//achievement details here

}


I am still new to this swift language and I am not very advanced yet I would appreciate the help.

Answer

If you think your code is a mess, try to find patterns in your code.

See those Achievement1, Achievement2, Achievement3, Achievement4 thingys? When you see this kind of pattern, you should probably create an array to store the achievements.

I'm sure you know how to use an array, so I won't talk about it too much. For more info, you can go to the definition of the Array class.

The other pattern you might notice is that you use the same arguments to create the sprite nodes. The only difference between the achievements is their positions.

The best way to fix this is to create a method:

func createAchievement(location: CGPoint) -> SKSpriteNode {
    let node = SKSpriteNode(color: SKColor.whiteColor(), size: CGSize(width: 100, height: 100))
    node.position = location
    return node
}

And you just need one line to add a new achievement to the aforementioned array:

someArray.append(createAchievement(CGPointMake(-120, 100)))

EDIT:

If you use the indexOf(_:) (or index(of:) in swift 3), you can create a switch statement instead of an if statement:

switch someArray.indexOf(node) {
    case 0:
        // this means that the first achievement is tapped!
    case 1:
        // this means that the second achievement is tapped!
    case 2:
        // this means that the third achievement is tapped!
}