0
votes
  1. I make a path using UIBezierPath then from this path I create a SKShapeNode.
  2. I want from the user to draw a same path by his touches on screen to match my original path.

this is the code:

import SpriteKit import GameplayKit

class GameScene: SKScene {

var orginalPath: UIBezierPath!

var orgialShape: SKShapeNode!
var userTouchs = [CGPoint]()
var drawingLine: SKShapeNode!


override func didMove(to view: SKView) {

    orginalPath = UIBezierPath()
    orginalPath.move(to: CGPoint(x: 170, y: 230))
    orginalPath.addLine(to: CGPoint(x: 370, y: 230))
    orginalPath.addQuadCurve(to: CGPoint(x: 480, y: 55), controlPoint: CGPoint(x: 525, y: 150))


    orgialShape = SKShapeNode(path: orginalPath.cgPath)
    orgialShape.strokeColor = UIColor.white
    orgialShape.lineWidth = 30
    orgialShape.lineCap = .round
    orgialShape.lineJoin = .round
    orgialShape.zPosition = 0
    orgialShape.name = "orginal"
    addChild(orgialShape)

}

func createLine() {
    if userTouchs.count > 2 {
        let line = SKShapeNode(points: &userTouchs, count: userTouchs.count)
        line.strokeColor = UIColor.red
        line.lineWidth = 10
        line.lineCap = .round
        line.zPosition = 10
        line.isAntialiased = true
        line.name = "newLine"
        addChild(line)

    }
}


override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    if let touch = touches.first {
        let location = touch.location(in: self)
        let objects = nodes(at: location)
        for object in objects {
            if object.name == "orginal" {
                    userTouchs.append(location)
            }
        }
    }
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    if let touch = touches.first {
        let location = touch.location(in: self)
        let objects = nodes(at: location)
        for object in objects {
            if object.name == "orginal" {
                    print(location)
                    userTouchs.append(location)
                    createLine()
            }
        }
    }
}

this code should make the user draw "only" on my path like I show in the picture:

enter image description here

but the problem is when I write the code I found the that I can draw a line out of the path, actually its look like a square not just a path like I show in the pictures:

enter image description here enter image description here enter image description here

So please did anyone can explain to me the right way to make the user only draw over my path and if he touch out the path he can't draw any thing.

1

1 Answers

0
votes

You could define a path where the user is allowed to draw in, e.g. see the green path here:

clip path

Then clip to this path:

self.currentBezierPath.addClip()

See more details for this approach in my answer here: How to draw inside the black edges in iOS SDK with OpenGL ES?

Ensure that the user follows the path in one direction

You could divide the area e.g. into small rectangles and store them in order into an array, see sketch here:

divide path into areas

Then make sure that the user starts by touching the rectangles (shown in red in the illustration) only in ascending order and that the user does not leave the outer boundary (shown in green in the illustration).

To check whether a point lies within a path, the following can be used:

    let inside = bezierPath.contains(point)

Would that solve your use case?