swiftxcodesprite-kitskshapenode

How to make one line follow touch instead of drawing infinite in spritekit?


I am trying to make one single, straight line follow my finger after I touch a certain sprite object. I have it working so far except instead of one single line being drawn, infinite lines are drawn following the touch...

My Code:

import SpriteKit
import GameplayKit

class WireDrawTest: SKScene{
    
    
    var drawingLayer: CAShapeLayer!
    var redBox = SKSpriteNode()
    var redBoxPoint = CGPoint(x: 445, y: 800)
    var redBoxTouched:Int = -1
    
    var currentTouch = touchesMoved
    
    func drawLine(from: CGPoint, to: CGPoint) {
        let line = SKShapeNode()
        let path = CGMutablePath()
        path.addLines(between: [from, to])
        line.path = path
        line.strokeColor = UIColor.yellow
        line.lineWidth = 13
        addChild(line)
    }
    
    override func didMove(to view: SKView) {
        redBox = self.childNode(withName: "redBox") as! SKSpriteNode
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        print(redBoxTouched)
    }
    
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        
        let touch = touches.first
        
        if let location = touch?.location(in: self){
            let nodesArray = self.nodes(at: location)
            
            if nodesArray.first?.name == "redBox" {
                if redBoxTouched == -1 {
                    redBoxTouched = 1
                }
            }
        
            if redBoxTouched == 1 {
                drawLine(from: redBoxPoint, to: location)
            }
        
        }
        
    }
    
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        print(redBoxTouched)
        if redBoxTouched == 1 {
            redBoxTouched = -1
        }
    }    
}

This is a screenshot of the current result: screenshot

TIA!!


Solution

  • Every time you call drawLine, you're creating a new shape node and adding it to the scene. However, you're never removing any of these shape nodes, so the number of lines is increasing as you move your finger.

    One fix is to have an optional shape node that remembers the previous line, if any. Then just remove and discard the previous shape node if there is one whenever the touch moves. And when the touch ends, remove the line.

    Or you could create one shape node and add it to the scene when the touch begins, change its path as the touch moves, and remove it from the scene when the touch ends. If I recall correctly, the shape node makes a copy of the path internally, so just having a mutable path and changing the path won't update the shape node. But I believe you can make a new path and assign to the shape node's path property to update the node.