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 line segments connecting the origin of the sprite (point where it starts) and the point where you touched, and between the origin of the sprite and the end point at the edge of the screen, so I can visualize the path of the sprite and the relationship between the x and y offsets of the origin, touch point and end point.
Hopefully that was not too confusing.
TL;DR: I need to draw a line between two points and I don't know how to do that using SpriteKit Swift.
Thanks in advance.
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 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:
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 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))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With