Search code examples
swiftsprite-kitmulti-touchuitouchtouchesbegan

Detect touches on two separate sprite nodes


so what i am trying to do here, is to able to move two of the four sprite nodes, independently from each other. I used an enum to detect what slide was touched then use that information to move the correct node, i know i could of used the name of the node but seemed to work better with what i am trying to do. everything works good so far except i can only move one node at a time. i would like to be able to move... say, leftSlide upwards, while at the same time move rightSlide downwards.

Thank you for any suggestions or comments, any feedback is welcome..

var selectedSlides: [SKSpriteNode] = []
var theSlideTouched: SlideTouched = .nothing

enum SlideTouched
{
    case left
    case right
    case bottom
    case top
    case nothing
}

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

        if leftSlide.contains((touch.location(in: self)))
        {
            selectedSlides.append(leftSlide)
            theSlideTouched = .left

        }

        if rightSlide.contains((touch.location(in: self)))
        {
            selectedSlides.append(rightSlide)
            theSlideTouched = .right

        }

        if bottomSlide.contains((touch.location(in: self)))
        {
            selectedSlides.append(bottomSlide)
            theSlideTouched = .bottom
        }

        if topSlide.contains((touch.location(in: self)))
        {
            selectedSlides.append(topSlide)
            theSlideTouched = .top
        }
     }
 }

 override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?)
{
    for touch in touches
    {
        let location = touch.location(in: self)

        switch theSlideTouched
        {
            case .bottom:
                if selectedSlides.contains(bottomSlide)
                {
                    bottomSlide.color = UIColor.white
                    bottomSlide.position.x = location.x
                }
            case .top:
                if selectedSlides.contains(topSlide)
                {
                    topSlide.color = UIColor.white
                    topSlide.position.x = location.x
                }
            case .left:
                if selectedSlides.contains(leftSlide)
                {
                    leftSlide.color = UIColor.white
                    leftSlide.position.y = location.y
                }
            case .right:
                if selectedSlides.contains(rightSlide)
                {
                    rightSlide.color = UIColor.white
                    rightSlide.position.y = location.y
                }
            case .nothing: break
        }
    }

}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?)
{
        switch theSlideTouched
        {
            case .bottom: bottomSlide.color = UIColor.clear
            case .top: topSlide.color = UIColor.clear
            case .left: leftSlide.color = UIColor.clear
            case .right: rightSlide.color = UIColor.clear
            case .nothing: break
        }
            theSlideTouched = .nothing
            selectedSlides.removeAll()
}

Solution

  • I would move the slider objects into their own class. That way you could handle their movement independently and not clutter up your GameScene with these objects. Now when I created this example I placed the objects visually in the GameScene.sks file throughout Scene Editor, so my initialization might be different then yours if you create these in code.

    in GameScene...

    var topSlide: DragObject!
    var rightSlide: DragObject!
    var bottomSlide: DragObject!
    var leftSlide: DragObject!
    
    override func didMove(to view: SKView) {
    
        self.view!.isMultipleTouchEnabled = true
    
        if let topSlide = self.childNode(withName: "topSlide") as? DragObject {
            self.topSlide = topSlide
            topSlide.type = .top
        }
    
        //if you were to create this in code you could do
        //topSlide = DragObject(color: .red, size: CGSize(width: 100, height: 100)
        //topSlide.type = .top
        //topSlide.position = CGPoint(x: 500, y: 500)
        //topSlide.zPosition = 1
        //addChild(topSlide)
    
        if let rightSlide = self.childNode(withName: "rightSlide") as? DragObject {
            self.rightSlide = rightSlide
            rightSlide.type = .right
        }
    
        if let bottomSlide = self.childNode(withName: "bottomSlide") as? DragObject {
            self.bottomSlide = bottomSlide
            bottomSlide.type = .bottom
        }
    
        if let leftSlide = self.childNode(withName: "leftSlide") as? DragObject {
            self.leftSlide = leftSlide
            leftSlide.type = .left
        }
    }
    

    in DragObject class...

    class DragObject: SKSpriteNode {
    
        enum SlideType {
            case left
            case right
            case bottom
            case top
            case nothing
        }
    
        var type: SlideType = .nothing
    
        init(color: SKColor, size: CGSize) {
    
            super.init(texture: nil, color: color, size: size)
    
            setup()
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
    
            setup()
        }
    
        func setup() {
            self.isUserInteractionEnabled = true
        }
    
        override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    
        }
    
        override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    
            for touch in touches {
                let location = touch.location(in: self.parent!)
    
                self.color = .white
                if type == .bottom || type == .top {
                    position.x = location.x
                }
                else if type == .left || type == .right {
                    position.y = location.y
                }
            }
        }
    
        override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
            self.color = .red
        }
    }