2

I have a menu button (skSpriteNode) and a small play icon inside this sprite

mainButton.addChild (playIcon)
mainButton.name = "xyz"
addchild (mainButton)

ok, I gave the button the name to check if a sprite with this name is touched.

when I touch the icon child inside the button, the touchedNode.name is nil. I set isUserInteractionEnabled = false for the icon child. I want to pass the touch to the parent. how can I do this.

  for touch in touches {

            let location = touch.location(in: self)
            let touchedNode  = self.atPoint(location)

            if (touchedNode.name != nil) {
                print ("node \(touchedNode.name!)")
            } else {
                continue
            }
 }
bluelemonade
  • 1,115
  • 1
  • 14
  • 26

2 Answers2

5

You have to implement touchesBegan in a subclass of SKSpriteNode and to set its isUserInteractionEnabled = true, in order to accept and process the touches for that particular node (button).

import SpriteKit

protocol ButtonDelegate:class {

    func printButtonsName(name:String?)
}

class Button : SKSpriteNode{

    weak var delegate:ButtonDelegate?

    init(name:String){
        super.init(texture: nil, color: .purple, size: CGSize(width: 250, height: 250))
        self.name = name
        self.isUserInteractionEnabled = true
        let icon = SKSpriteNode(color: .white, size: CGSize(width:100, height:100))
        addChild(icon)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }


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



        delegate?.printButtonsName(name: self.name)
    }  
}

class GameScene: SKScene, ButtonDelegate {

    override func didMove(to view: SKView) {

        let button = Button(name:"xyz")
        button.delegate = self


        button.position = CGPoint(x: frame.midX - 50.0, y: frame.midY)


        addChild(button)

    }

    func printButtonsName(name: String?) {

        if let buttonName = name {
            print("Pressed button : \(buttonName) ")
        }
    }
}

Now, this button will swallow the touches and the icon sprite will be ignored.

I just modified the code from one of my answers to make an example specific to your needs, but you can read, in that link, about whole thing more in detail if interested.

Whirlwind
  • 14,286
  • 11
  • 68
  • 157
  • thanks, I learned a few things. How can I check if the touch location is on a transparent pixel? when I have two buttons with amorph form, but overlapping rect areas, the first in the zposition is clicked. – bluelemonade Aug 01 '17 at 18:36
  • @bluelemonade That could be solved in at least two ways (eg extracting a pixel alpha value using CGImage) or making a physics body of an irregular shape (well this really depends on a shape) and use PhysicsWorld's `bodyAt(point:)` method. Take a look at this: https://stackoverflow.com/a/20932809/3402095 – Whirlwind Aug 01 '17 at 18:46
  • ok, I can detect the alpha of the texture. but the touch event didn't 'bubble' to the underlaying button. – bluelemonade Aug 04 '17 at 19:20
1

I implemented the button Touchbegan and tried to implement a subclass for a slider with a background and the child thumb inside the slider. I added the sliderDelegate Protocoll in my GameScene. the down touch is ok, but I didn't get the moved in

import Foundation
import SpriteKit


protocol SliderDelegate:class {

    func touchesBeganSKSpriteNodeSlider(name:String?, location: CGPoint?)
    func touchesMovedSKSpriteNodeSlider(name:String?, location: CGPoint?)
    func touchesEndedSKSpriteNodeSlider(name:String?, location: CGPoint?)

}


class SKSpriteNodeSlider : SKSpriteNode{

    weak var delegate:SliderDelegate?

    init(imageNamed: String){

        // super.init(imageNamed: imageNamed)
        let texture = SKTexture(imageNamed: imageNamed)
        super.init(texture: texture, color: .white, size: texture.size())
        // self.name = name
        self.isUserInteractionEnabled = true
        // let icon = SKSpriteNode(color: .white, size: CGSize(width:100, height:100))
        // addChild(icon)
    }

    required init?(coder aDecoder: NSCoder) {

        fatalError("init(coder:) has not been implemented")

    }


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

        // for touch in touches {
        if let touch = touches.first {
            let loc = touch.location(in: self)
            delegate?.touchesBeganSKSpriteNodeSlider(name: self.name, location: loc)

        }

    }


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

        print ("touchesMoved")

        // for touch in touches {
        if let touch = touches.first {
            let loc = touch.location(in: self)
            delegate?.touchesMovedSKSpriteNodeSlider(name: self.name, location: loc)
         }

    }


    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        if let touch = touches.first {
            let loc = touch.location(in: self)
            delegate?.touchesEndedSKSpriteNodeSlider(name: self.name, location: loc)
        }

    }

}
bluelemonade
  • 1,115
  • 1
  • 14
  • 26