SKAction on a programmatically built node? How to target the node?

111 views Asked by At

I had previously used a separate method for each character and wrote them in each scene file but it was messy and huge.

So in an effort to clean up code I wrote a buildCharater method to create the characters I need in different scenes. As you can see it also builds the associated texture atlas and the animation action. However I need to have these characters build in a non active state - and when touched the animation begins along with other actions. I am able to detect touches using an if let switch on the optional names but I cannot sort how to call an action on the individual nodes - previous to this I was able to do node.run(someAction) but now I'm lost on how to target the individual nodes as well as animate them with the associated atlas's. Here is the buildCharacter method -

func buildCharacter(name:String, height: CGFloat, width: CGFloat, position: CGPoint, zPosition: CGFloat) {
    let animatedAtlas = SKTextureAtlas(named: name)
    var animationFrames: [SKTexture] = []
    
    let numImages = animatedAtlas.textureNames.count
    for i in 1...numImages {
        let textureName = "\(name)\(i)"
        
        animationFrames.append(animatedAtlas.textureNamed(textureName))
    }
    
    animatedCharacter = animationFrames
    let firstFrameTexture = animatedCharacter[0]
    builtCharacter = SKSpriteNode(texture: firstFrameTexture)
    builtCharacter.size.height = height
    builtCharacter.size.width = width
    builtCharacter.position = position
    builtCharacter.zPosition = zPosition
    builtCharacter.name = name
    
    isUserInteractionEnabled = true
    addChild(builtCharacter)
    builtCharacters.append(builtCharacter)
    
    let animationAction = SKAction.repeatForever(SKAction.animate(with: animatedCharacter, timePerFrame: 0.1, resize: false, restore: true))
    builtCharacter.run(animationAction)
    
   }

I do not want to run the action immediately like it currently does - I want to be able to start and stop the action(s) via touches began.

I had previously written an animation method for each character but am trying to streamline the whole thing - open to any ideas!

Thanks

1

There are 1 answers

2
JohnL On

You can get the nodes at your touch location using this code in touchesBegan:

  for t in touches {
    
    let location = t.location(in: self)
    let touchedNodes = self.nodes(at: location)
    
    for node in touchedNodes {
      let sprite = node as! SKSpriteNode
      sprite.run(animationAction)
    }
  }

This will run the animation on whatever nodes are found at your touch location. touchedNodes is an array which stores all nodes found at your location. They are stored as SKNode so you can convert them to SKSpriteNode if need be.

You can add an if statement in the for node.. which checks the node.name, and you can then run specific animations depending on what node you have selected. In your example in your comment, if you clicked on character1 and want to run animations on character1 AND character2, you could use:

for node in touchedNodes {
    if node.name == "character1" {
      let char1 = node as! SKSpriteNode
      char1.run(animationAction)
      let char2 = childNode(withName: "//character2") as? SKSpriteNode
      char2.run(animationAction)
    } //else if node.name ==....


}