button SpriteKit

Hello, i am a problem in my gamescene, i created two button in my gamescene and my problem is that I have to separate them strongly so that both are OK and more, when I click a centimeter next to one of the two buttons, this one has a reaction. Why ?


I send you my code:


In my GameScene:

        backgroundColor = SKColor.white
        let buttonTextureCadre2: SKTexture! = SKTexture(imageNamed: "Cadre")
        let buttonTextureSelectedCadre2: SKTexture! = SKTexture(imageNamed: "CadreAppuye")
        let buttonCadre2 = FTButtonNode(normalTexture: buttonTextureCadre2, selectedTexture: buttonTextureSelectedCadre2, disabledTexture: buttonTextureCadre2)
        buttonCadre2.setButtonAction(target: self, triggerEvent: .TouchUpInside, action: #selector(GameScene.buttonCadre2))
        buttonCadre2.setButtonLabel(title: "X", font: "Arial", fontSize: 12)
        buttonCadre2.zPosition = 6
        buttonCadre2.size.height = VueProchainNiveau.frame.width
        buttonCadre2.size.width = buttonCadre2.frame.height
        let PositionXButtonCadre2 = Cadre1.position.x + buttonCadre2.frame.width + 5
        buttonCadre2.position = CGPoint(x: PositionXButtonCadre2, y: 0)
        buttonCadre2.name = "buttonCadre2"
        self.VueProchainNiveau.addChild(buttonCadre2)
       
        backgroundColor = SKColor.white
        let buttonTexture2: SKTexture! = SKTexture(imageNamed: "Cadre")
        let buttonTextureSelected2: SKTexture! = SKTexture(imageNamed: "CadreAppuye")
        let buttonCadre3 = FTButtonNode(normalTexture: buttonTexture2, selectedTexture: buttonTextureSelected2, disabledTexture: buttonTexture2)
        buttonCadre3.setButtonAction(target: self, triggerEvent: .TouchUpInside, action: #selector(GameScene.buttonCadre3))
        buttonCadre3.setButtonLabel(title: "X", font: "Arial", fontSize: 12)
        buttonCadre3.zPosition = 6
        buttonCadre3.size.height = VueProchainNiveau.frame.width
        buttonCadre3.size.width = buttonCadre3.frame.height
        let PositionXButtonCadre3 = buttonCadre2.position.x + buttonCadre3.frame.width + 75
        buttonCadre3.position = CGPoint(x: PositionXButtonCadre3, y: 0)
        buttonCadre3.name = "buttonCadre3"
self.VueProchainNiveau.addChild(buttonCadre3)

In my FTButtonNode:


import SpriteKit

class FTButtonNode: SKSpriteNode {
   
    enum FTButtonActionType: Int {
        case TouchUpInside = 1,
        TouchDown, TouchUp
    }
   
    var isEnabled: Bool = true {
        didSet {
            if (disabledTexture != nil) {
                texture = isEnabled ? defaultTexture : disabledTexture
            }
        }
    }
    var isSelected: Bool = false {
        didSet {
            texture = isSelected ? selectedTexture : defaultTexture
        }
    }
   
    var defaultTexture: SKTexture
    var selectedTexture: SKTexture
    var label: SKLabelNode
   
    required init(coder: NSCoder) {
        fatalError("NSCoding not supported")
    }
   
    init(normalTexture defaultTexture: SKTexture!, selectedTexture:SKTexture!, disabledTexture: SKTexture?) {
       
        self.defaultTexture = defaultTexture
        self.selectedTexture = selectedTexture
        self.disabledTexture = disabledTexture
        self.label = SKLabelNode(fontNamed: "Helvetica");
       
        super.init(texture: defaultTexture, color: UIColor.white, size: defaultTexture.size())
        isUserInteractionEnabled = true
       
        //Creating and adding a blank label, centered on the button
        self.label.verticalAlignmentMode = SKLabelVerticalAlignmentMode.center;
        self.label.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.center;
        addChild(self.label)
       
        // Adding this node as an empty layer. Without it the touch functions are not being called
        // The reason for this is unknown when this was implemented...?
        let bugFixLayerNode = SKSpriteNode(texture: nil, color: UIColor.clear, size: defaultTexture.size())
        bugFixLayerNode.position = self.position
        addChild(bugFixLayerNode)
       
    }
   
    /**
     * Taking a target object and adding an action that is triggered by a button event.
     */
    func setButtonAction(target: AnyObject, triggerEvent event:FTButtonActionType, action:Selector) {
       
        switch (event) {
        case .TouchUpInside:
            targetTouchUpInside = target
            actionTouchUpInside = action
        case .TouchDown:
            targetTouchDown = target
            actionTouchDown = action
        case .TouchUp:
            targetTouchUp = target
            actionTouchUp = action
        }
       
    }
   
    /*
     New function for setting text. Calling function multiple times does
     not create a ton of new labels, just updates existing label.
     You can set the title, font type and font size with this function
     */
   
    func setButtonLabel(title: NSString, font: String, fontSize: CGFloat) {
        self.label.text = title as String
        self.label.fontSize = fontSize
        self.label.fontName = font
    }
   
    var disabledTexture: SKTexture?
    var actionTouchUpInside: Selector?
    var actionTouchUp: Selector?
    var actionTouchDown: Selector?
    weak var targetTouchUpInside: AnyObject?
    weak var targetTouchUp: AnyObject?
    weak var targetTouchDown: AnyObject?
   
    override func touchesBegan(_ touches: Set, with event: UIEvent?) {
        if (!isEnabled) {
            return
        }
        isSelected = true
        if (targetTouchDown != nil && targetTouchDown!.responds(to: actionTouchDown)) {
            UIApplication.shared.sendAction(actionTouchDown!, to: targetTouchDown, from: self, for: nil)
        }
    }
   
    override func touchesMoved(_ touches: Set, with event: UIEvent?) {
       
        if (!isEnabled) {
            return
        }
       
        let touch: AnyObject! = touches.first
        let touchLocation = touch.location(in: parent!)
       
        if (frame.contains(touchLocation)) {
            isSelected = true
        } else {
            isSelected = false
        }
       
    }
   
    override func touchesEnded(_ touches: Set, with event: UIEvent?) {
        if (!isEnabled) {
            return
        }
       
        isSelected = false
       
        if (targetTouchUpInside != nil && targetTouchUpInside!.responds(to: actionTouchUpInside!)) {
            let touch: AnyObject! = touches.first
            let touchLocation = touch.location(in: parent!)
           
            if (frame.contains(touchLocation) ) {
                UIApplication.shared.sendAction(actionTouchUpInside!, to: targetTouchUpInside, from: self, for: nil)
            }
           
        }
       
        if (targetTouchUp != nil && targetTouchUp!.responds(to: actionTouchUp!)) {
            UIApplication.shared.sendAction(actionTouchUp!, to: targetTouchUp, from: self, for: nil)
        }
    }
   
}


Thank you for your help !

Replies

Which buttons ?


buttonCadre2 and buttonCadre3 ?


Which one is sensitive beyond its intended area ?


Where do you define the frame of the buttons ?


Do you also want the width to equal its height ?

       buttonCadre2.size.width = buttonCadre2.frame.height

both are sensitive outside their ranges. I do not know how to define the sensitivity framework. the buttons are squares, which is why I put equal, height and width.

OK. But what are their frames ? May be it is larger than what you think.

maybe, I just wish the sensitivity is equal to the width and the height

Hello Claude31,


I changed my way for use my button, i am use touchesBegan and .name like this:


my cadre2:

     Cadre2 = SKSpriteNode(imageNamed: "Cadre")
        Cadre2.name = "Cadre2"
        Cadre2.zPosition = 2
        Cadre2.size.width = VueProchainNiveau.frame.width
        Cadre2.size.height = Cadre2.frame.width
        Cadre2.position = CGPoint(x: Cadre1.frame.maxX+Cadre2.frame.width/2 + 5, y: 0)
self.VueProchainNiveau.addChild(Cadre2)


my touchesBegan:


for touch in touches {
            let location = touch.location(in: self)
            let touchedNode = atPoint(location)
            if touchedNode.name == "Cadre2" {
                print("toto2")
            }
            if touchedNode.name == "Cadre3" {
                print("toto3")
            }
        }



thank for your help 😉

So, does it work now ? Would be great. In that case, don't forget to close the thread.


AFAIK, sensitivity does not deal with active zone, but about the gestures dynamics.


Hence, checking what is the frame of the buttons could give a clue to the problem.

Yes, it work now, I only have find chang my image when touch my button, it should be fine 😉


Thank for your help !

Great. Please, close the thread as it is solved.