Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a line with two CGPoints SpriteKit Swift

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.

like image 273
rookr Avatar asked Jun 29 '15 06:06

rookr


4 Answers

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:

  1. moveToPoint: It sets the current point of the path to the specified point.
  2. addLineToPoint: It draws a straight line from the current point to the specified point. or addCurveToPoint: It draws a curved line from the current point to the specified point based on certain tangents and control points.

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 :).

like image 162
Mehul Avatar answered Nov 11 '22 14:11

Mehul


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:

enter image description here

like image 45
CodeBender Avatar answered Nov 11 '22 12:11

CodeBender


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:

enter image description here

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:

enter image description here

And you can set that path for the pig.

You can modify that as per your need.

Hope it will help.

like image 8
Dharmesh Kheni Avatar answered Nov 11 '22 13:11

Dharmesh Kheni


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))
like image 8
DrRobotNinja Avatar answered Nov 11 '22 13:11

DrRobotNinja