1
votes

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.

Illustration of goal

1
You use SKShapeNode to create the shape, then you convert the SKShapeNode into a SKTexture to be used on an SKSpriteNodeKnight0fDragon
@Knight0fDragon Doing this gives me absolutely horrid performance.bwiz
then you are not doing it correctlyKnight0fDragon

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
    }
}