I am trying to make a simple app where you touch a point, and a sprite follows a line through that point to the edge of the screen, no matter where you touch. I want to draw lin
This can be done using CGPath and SKShapeNode.
Lets start with CGPath. CGPath is used when we need to construct a path using series of shapes or lines. Paths are line connecting two points. So to make a line:
You can check the documentation here: http://developer.apple.com/library/mac/#documentation/graphicsimaging/Reference/CGPath/Reference/reference.html
What you need to do is:
var path = CGPathCreateMutable()
CGPathMoveToPoint(path, nil, 100, 100)
CGPathAddLineToPoint(path, nil, 500, 500)
Now to make the path visible, and give it attributes like stroke color, line width etc. you create a SKShapeNode in SpriteKit and add the path to it.
let shape = SKShapeNode()
shape.path = path
shape.strokeColor = UIColor.whiteColor()
shape.lineWidth = 2
addChild(shape)
Hope this helps :).
For Swift 3, the CGPathMoveToPoint
method doesn't like a nil
for the second argument anymore, so I needed a new solution. Here's what I came up with:
let line_path:CGMutablePath = CGMutablePath()
line_path.move(to: CGPoint(x:x1, y:y1))
line_path.addLine(to: CGPoint(x:x2, y:y2))
Follow THIS tutorial step by step and you can achieve that.
Consider the below code:
override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {
let location = touches.anyObject()!.locationInNode(scene)
if let pig = movingPig {
pig.addMovingPoint(location)
}
}
This is a simple method. You get the next position of the user’s finger and if you found a pig in touchesBegan(_:,withEvent:)
, as indicated by a non-nil movingPig value, you add the position to this pig as the next waypoint.
So far, you can store a path for the pig—now let’s make the pig follow this path. Add the following code to update()
inside GameScene.swift
:
dt = currentTime - lastUpdateTime
lastUpdateTime = currentTime
enumerateChildNodesWithName("pig", usingBlock: {node, stop in
let pig = node as Pig
pig.move(self.dt)
})
And you can see result:
Drawing Lines:
At the moment, only the pig knows the path it wants to travel, but the scene also needs to know this path to draw it. The solution to this problem is a new method for your Pig
class.
func createPathToMove() -> CGPathRef? {
//1
if wayPoints.count <= 1 {
return nil
}
//2
var ref = CGPathCreateMutable()
//3
for var i = 0; i < wayPoints.count; ++i {
let p = wayPoints[i]
//4
if i == 0 {
CGPathMoveToPoint(ref, nil, p.x, p.y)
} else {
CGPathAddLineToPoint(ref, nil, p.x, p.y)
}
}
return ref
}
this method to draw the pig’s path:
func drawLines() {
//1
enumerateChildNodesWithName("line", usingBlock: {node, stop in
node.removeFromParent()
})
//2
enumerateChildNodesWithName("pig", usingBlock: {node, stop in
//3
let pig = node as Pig
if let path = pig.createPathToMove() {
let shapeNode = SKShapeNode()
shapeNode.path = path
shapeNode.name = "line"
shapeNode.strokeColor = UIColor.grayColor()
shapeNode.lineWidth = 2
shapeNode.zPosition = 1
self.addChild(shapeNode)
}
})
}
And here is your result:
And you can set that path for the pig.
You can modify that as per your need.
Hope it will help.
For the sake of simplicity, I pulled everything necessary to draw a line into an extension of SKShapeNode
that allows you to create a line with a start
& end
point, as well as a strokeColor
and strokeWidth
(you could always preset these or make default values should you choose too)
extension SKShapeNode {
convenience init(start: CGPoint,
end: CGPoint,
strokeColor: UIColor,
lineWidth: CGFloat) {
self.init()
let path = CGMutablePath()
path.move(to: start)
path.addLine(to: end)
self.path = path
self.strokeColor = strokeColor
self.lineWidth = lineWidth
}
}
The basic idea is that it will create a CGMutablePath with the provided points and assign it to the shape node for drawing a line.
To call it:
let horizontalLine = SKShapeNode(start: CGPoint(x: 0, y: 50),
end: CGPoint(x: size.width, y: 50),
strokeColor: .orange,
lineWidth: 2.0)
addChild(horizontalLine)
And the output: