【问题标题】:SKAction on a programmatically built node? How to target the node?以编程方式构建的节点上的 SKAction?如何定位节点?
【发布时间】:2021-10-05 11:19:31
【问题描述】:

我之前对每个角色使用了单独的方法,并将它们写在每个场景文件中,但它是混乱和巨大的。

所以为了清理代码,我编写了一个 buildCharater 方法来创建我在不同场景中需要的角色。如您所见,它还构建了相关的纹理图集和动画动作。但是,我需要让这些角色处于非活动状态 - 并且当被触摸时,动画会与其他动作一起开始。我可以使用 if let 切换可选名称来检测触摸,但我无法对如何在各个节点上调用操作进行排序 - 在此之前我能够执行 node.run(someAction) 但现在我迷路了如何定位单个节点以及使用关联的图集为它们设置动画。这是 buildCharacter 方法 -

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)
    
   }

我不想像现在那样立即运行动作 - 我希望能够通过开始触摸开始和停止动作。

我之前为每个角色编写了一个动画方法,但我正在努力简化整个事情 - 对任何想法都持开放态度!

谢谢

【问题讨论】:

  • 我会在函数范围之外创建变量animationAction,比如在类的顶部,然后将let animationAction 更改为animationAction,并删除builtCharacter.run(animationAction)。当buildCharacter 函数运行时,该变量将存储动画并准备好使用。然后当检测到触摸时使用builtCharacter.run(animationAction)
  • 哦,这是个好主意 - 但只能解决部分情况。我有 5 个字符 - 它们每个都来自于 builtCharacter 方法 - 我需要能够单独对它们运行操作,以及基于哪个节点被触摸的各种节点分组。所以假设我有 character1 和 character2 - 当我触摸 character1 时,我想对 character1 和 character2 运行动作 - 所以调用 builtCharacter.run(someAnimation) 不太有效 - 这有意义吗?如果特定节点都作为builtCharacter 从方法中出来,我该如何定位它们?
  • 请看看我的回答,看看是否有帮助

标签: sprite-kit skaction sknode


【解决方案1】:

您可以使用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)
    }
  }

这将在您的触摸位置找到的任何节点上运行动画。 touchedNodes 是一个数组,用于存储在您所在位置找到的所有节点。它们存储为SKNode,因此您可以根据需要将它们转换为SKSpriteNode

您可以在检查node.namefor node.. 中添加if 语句,然后您可以根据您选择的节点运行特定的动画。在您评论的示例中,如果您单击 character1 并希望在 character1 和 character2 上运行动画,您可以使用:

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 ==....


}

【讨论】:

  • 我一直在使用这种方法,问题是animationAction变量只存储最后一个builtCharacter的动作/图集。因此,如果在 viewDidLoad 中为 5 个不同的字符运行 buildCharacter 5 次 - 唯一存储的动作是最后构建的字符 - 我想知道是否可以将每个动作/图集加载到数组中并根据需要访问它们?我有 4 个场景和 5 个字符(都一样),所以整个想法只是为了减少重复代码 - 我可以很容易地完成这项工作 - 但真的想尝试这样的方法......
  • 我明白你在说什么。您可以将所有动画存储在字典中,并给它们一个可识别的键。在从 didMoveTo 视图调用的函数中构建所有这些。然后,您可以随时拉出您需要的任何动画。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-09
  • 1970-01-01
  • 1970-01-01
  • 2014-08-02
  • 1970-01-01
相关资源
最近更新 更多