Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create endless cgpath without framedrops

I need to create a cgpath continuously. At the moment I do it like that:

 func createLine(){
        var rand = randomBetweenNumbers(1, 2)
        currentY--
        if rand < 1.5{
            currentX--
            CGPathAddLineToPoint(leftPath, nil, currentX, currentY)
        }else{
            currentX++
            CGPathAddLineToPoint(leftPath, nil, currentX, currentY)
        }
        CGPathAddLineToPoint(rightPath, nil, currentX+tileSize, currentY)
        lineNode.path = leftPath
        rightNode.path = rightPath

}

And call it like that:

NSTimer.scheduledTimerWithTimeInterval(0.05, target: self, selector: Selector("startTile"), userInfo: nil, repeats: true)

But the problem is, that the frames drop lower and lower over time. Is there something I have to change so that the framerate no longer drops?

My goal is to create a random endless path.

like image 541
Christian Avatar asked May 28 '15 18:05

Christian


People also ask

How do I create a frameless browserwindow?

To create a frameless window, you need to set the frame property to false in the BrowserWindow instance that you want: Tipically, you may want to enable this feature in your main Window ( main.js ), that should be similar to:

What is the API for frameless windows?

This "api" allow you to create a frameless window that has no chrome, the parts of the window, like toolbars, that are not a part of the web page. In a browser, the chrome is any visible aspect of a browser aside from the webpages themselves (e.g., toolbars, menu bar, tabs).

How do I create a window without chrome?

To create a window without chrome, or a transparent window in arbitrary shape, you need to use the Frameless Window API. This "api" allow you to create a frameless window that has no chrome, the parts of the window, like toolbars, that are not a part of the web page.


1 Answers

The key to maintaining a high FPS count while drawing a progressively increasing number of lines is to quickly reach a state where adding more lines to the scene has little or no effect on frame rate. There are at least two ways to accomplish this.

The most straightforward of the two is to periodically convert the previously drawn lines to an SKTexture and display the results as texture of an SKSpriteNode. Here are the steps:

  1. Create an SKNode to be used as a line container
  2. Create an SKSpriteNode that will be used as a line canvas
  3. Create an SKShapeNode to be used to draw new lines
  4. Add the container to the scene and the canvas and shape node to the container
  5. Draw a set of connected line segments using the path property of the shape node
  6. When the line count reaches a predetermined value, convert the contents of the container to an 'SKTexture'
  7. Set the texture property of the canvas to the SKTexture. Note that since the canvas is also a child of the container, its contents will also be added to the texture
  8. Lather, rinse, repeat steps 5 - 7

Here's an example implementation in Swift that draws an endless set of lines at 60 FPS on an iPhone 6 device (you should test performance on a device not with the simulator):

class GameScene: SKScene {
    // 1. Create container to hold new and old lines
    var lineContainer = SKNode()
    // 2. Create canvas
    var lineCanvas:SKSpriteNode?
    // 3. Create shape to draw new lines
    var lineNode = SKShapeNode()

    var lastDrawTime:Int64 = 0
    var lineCount = 0
    var timeScan:Int64 = 0
    var path = CGPathCreateMutable()

    var lastPoint = CGPointZero

    override func didMoveToView(view:SKView) {
        scaleMode = .ResizeFill

        // 4. Add the container to the scene and the canvas to the container 
        addChild(lineContainer)
        lineCanvas = SKSpriteNode(color:SKColor.clearColor(),size:view.frame.size)
        lineCanvas!.anchorPoint = CGPointZero
        lineCanvas!.position = CGPointZero
        lineContainer.addChild(lineCanvas!)
        lastPoint = CGPointMake(view.frame.size.width/2.0, view.frame.size.height/2.0)
    }

    // Returns a random value in the specified range
    func randomInRange(minValue:CGFloat, maxValue:CGFloat) -> CGFloat {
        let r = CGFloat(Double(arc4random_uniform(UInt32.max))/Double(UInt32.max))
        return (maxValue-minValue) * r + minValue
    }

    func drawLine() {
        if (CGPathIsEmpty(path)) {
            // Create a new line that starts where the previous line ended
            CGPathMoveToPoint(path, nil, lastPoint.x, lastPoint.y)
            lineNode.path = nil
            lineNode.lineWidth = 1.0
            lineNode.strokeColor = SKColor.blueColor()
            lineNode.zPosition = 100
            lineContainer.addChild(lineNode)
        }
        // Add a random line segment
        let x = randomInRange(size.width*0.1, maxValue: size.width*0.9)
        let y = randomInRange(size.height*0.1, maxValue: size.height*0.9)
        CGPathAddLineToPoint(path, nil, x, y)
        lineNode.path = path
        // Save the current point so we can connect the next line to the end of the last line
        lastPoint = CGPointMake(x, y)
    }

    override func update(currentTime: CFTimeInterval) {
        let lineDrawTime = timeScan / 10
        // 5. Draw a new line every 10 updates. Increment line count
        if (lineDrawTime != lastDrawTime) {
            drawLine()
            ++lineCount
        }
        // 6. and 7. Add all newly and previously drawn lines to the canvas
        if (lineCount == 8) {
            addLinesToTexture()
            lineCount = 0
        }
        lastDrawTime = lineDrawTime
        ++timeScan
    }

    func addLinesToTexture () {
        // Convert the contents of the line container to an SKTexture
        let texture = self.view!.textureFromNode(lineContainer)
        // Display the texture
        lineCanvas!.texture = texture
        // Start a new line
        lineNode.removeFromParent()
        path = CGPathCreateMutable()
    }
}
like image 75
0x141E Avatar answered Sep 26 '22 04:09

0x141E