【问题标题】:Detecting touches on nodes built programmatically? Cannot access node name correctly?检测以编程方式构建的节点上的触摸?无法正确访问节点名称?
【发布时间】:2021-07-28 19:49:39
【问题描述】:

所以我通过构建这样的 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)
    
   }

然后我像这样在每个场景的基础上调用它们 -

buildCharacter(name: "Bear", height: 370, width: 370, position: CGPoint(x: 295, y: 25), zPosition: 10)

buildCharacter(name: "Cat", height: 240, width: 240, position: CGPoint(x: 134, y: -38), zPosition: 12)

这非常适合构建并将它们添加到场景中,但是我正在努力检测触摸然后为它们设置动画。我之前的 TouchesBegan 是这样的 -

func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    super.touchesBegan(touches, with: event)

    if let touch = touches.first {
           let location = touch.location(in: self)

           var closest:CGFloat?
            let nodes = nodes(at:location)
            for node in nodes as [SKNode] {
               if let sprite = node as? SKSpriteNode {
                   // Calculate the distance from the node to the touch
                   let dx = location.x - node.position.x
                   let dy = location.y - node.position.y
                   let distance = dx*dx + dy*dy
                   // Find the closest
                   if closest == nil || distance < closest! {
                       closest = distance
                       selectedNode = sprite

                   }
               }
           }
       }

switch selectedNode {
        case bear:
            
            if builtCharacter.hasActions() {
                SoundEngine.shared.stopBackgroundMusic(fadeOut: false)
                stopAllAnimation()
            } else {
                SoundEngine.shared.playBackgroundMusic("blueRail.aif", loop: false)
                startAllAnimation()
            }
        case cat:
            
            if cat.hasActions() {
                SoundEngine.shared.stopBackgroundMusic(fadeOut: false)
                stopAllAnimation()
            } else {
                SoundEngine.shared.playBackgroundMusic("cluckOldHen.aif", loop: false)
                animateCat()
                DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
                    self.startAllAnimation()
                   }

            }

所以基本上我正在努力访问节点名称?我尝试了builtCharacter.name,但无法弄清楚...我想我可以在 TouchesBegan 中做一些不同的事情,或者在 buildCharacter 方法中添加一些东西?

我知道我可以很容易地在情节提要中做到这一点,这是我的备用计划 - 只是尝试通过这种方法学习更多内容。提前致谢!

【问题讨论】:

  • 在您的switch selectedNode 语句中,您不需要对所选节点的名称进行切换并将案例:熊和猫放在引号中吗?是熊和猫字符串还是它们不在您提供的代码中的枚举?
  • 它们是字符串 - 所以如果我把它们作为 case 他们会出错,因为 selectedNode 是 SKSpriteNode...我也尝试将 selectedNode 转换为字符串 - 也有错误...但我喜欢它也是那个部分的东西。
  • 您必须打开所选节点的名称:selectedNode.name,其中包含“bear”或“cat”的情况,因为它们是字符串。该名称是可选的,因此您可能无法直接切换该名称。在您当前的代码中,您正在打开所选节点。 SpriteKit 没有熊和猫精灵节点,因此这些情况下的代码永远不会执行。
  • 这是有道理的——我尝试使用字符串大小写打开“selectNode.name”,是的,它不起作用。我不确定还有什么要打开的?是否可以在 buildCharacters 方法中创建一个熊和猫精灵节点,而不仅仅是使用 builtCharacter 节点?
  • selectedNode.name 不能直接工作,因为SKNode 的name 属性是可选的。您需要在名称上使用 if let 声明并打开它。该名称是确定所触摸的精灵类型的唯一直接方法。唯一的选择是为角色创建自己的结构或类,以及为角色类型创建一个枚举:熊、猫或其他。结构/类具有枚举和精灵节点的属性。使用枚举来确定被触摸的字符类型。

标签: swift sprite-kit


【解决方案1】:

好吧,在@Mark Szymczyk 的帮助下想通了。由于 SKNode 的 name 属性是可选的,我必须在 if let 语句中运行 switch 并打开非可选名称

 if let nodeName = selectedNode.name {
            switch nodeName {
                    case "Bear" :
                        print("Bear touched")
                    case "Cat":
                        print("Cat touched")
                    default:
                        print("No node touched")

现在我可以访问节点名称并检测触摸。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-20
    • 2021-10-05
    • 1970-01-01
    • 1970-01-01
    • 2019-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多