I am building an infinite side scrolling game where I need to draw a line in which a ball can move upon. My original system of achieving the line was by spawning in a SKSpriteNode where the touch moved. This was unsuccessful due to performance. I then tried using a CGPath and an SKShapeNode, but the preformance of it was extremely poor and am out of ideas. Basically, I need to a path to be created where the player swipes or draws and I need a physics body to completely surround the stroke of the line drawn. It is also very important to remove the stroke or points of the path that are not in view of the camera anymore to save performance. An illustration of my goal is below.
1
votes
1 Answers
2
votes
Here is an example of how to get it working efficiently. You can work on how to get it on and off of the scene for even more efficiency.
The basic premises is you use 1 SKShapeNode
to draw your continuous line. Once you finished drawing the line, you convert it over to a texture to be used as an SKSpriteNode
//
// GameScene.swift
// physics
//
// Created by Anthony Randazzo on 7/28/17.
// Copyright © 2017 SychoGaming. All rights reserved.
//
import SpriteKit
import GameplayKit
class GameScene: SKScene {
private var shape = SKShapeNode()
private var path : CGMutablePath!
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let position = touches.first!.positionOnScene
path = CGMutablePath()
path.move(to: CGPoint.zero)
shape.path = path
shape.position = position
self.addChild(shape)
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
let position = touches.first!.positionOnScene - shape.position
path.addLine(to: position)
shape.path = path
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
let position = touches.first!.positionOnScene - shape.position
path.closeSubpath()
shape.removeFromParent()
autoreleasepool
{
let sprite = SKSpriteNode(texture: self.view?.texture(from: shape,crop:shape.frame))
sprite.position = CGPoint(x:shape.frame.midX,y:shape.frame.midY)
let physicsBody = SKPhysicsBody(polygonFrom: path)
physicsBody.isDynamic = false
sprite.physicsBody = physicsBody
addChild(sprite)
}
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
let position = touches.first!.positionOnScene
}
override func update(_ currentTime: TimeInterval) {
}
}
extension UITouch
{
var positionOnScene : CGPoint
{
return self.location(in: (self.view as! SKView).scene!)
}
}
extension CGPoint
{
static public func -(lhs:CGPoint,rhs:CGPoint) -> CGPoint
{
return CGPoint(x: lhs.x - rhs.x, y: lhs.y - rhs.y)
}
static public func -= (lhs:inout CGPoint,rhs:CGPoint)
{
lhs = lhs - rhs
}
}
SKShapeNode
to create the shape, then you convert theSKShapeNode
into aSKTexture
to be used on anSKSpriteNode
– Knight0fDragon