在没有framedrops的情况下创建无限的cgpath

时间:2015-05-28 18:43:54

标签: swift sprite-kit infinite frame-rate cgpath

我需要不断创建一个cgpath。目前我这样做:

 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

}

并称之为:

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

但问题是,随着时间的推移,帧越来越低。有什么我必须改变,以便帧率不再下降?

我的目标是创造一条随机的无尽路径。

1 个答案:

答案 0 :(得分:4)

在绘制逐渐增加的行数时保持高FPS计数的关键是快速达到向场景添加更多行对帧速率影响很小或没有影响的状态。至少有两种方法可以实现这一目标。

两者中最直接的方法是定期将先前绘制的线转换为SKTexture,并将结果显示为SKSpriteNode的纹理。以下是步骤:

  1. 创建一个SKNode以用作行容器
  2. 创建将用作线条画布的SKSpriteNode
  3. 创建用于绘制新行的SKShapeNode
  4. 将容器添加到场景中,将画布和形状节点添加到容器
  5. 使用形状节点的path属性
  6. 绘制一组连接的线段
  7. 当行数达到预定值时,将容器的内容转换为&#39; SKTexture&#39;
  8. 将画布的纹理属性设置为SKTexture。请注意,由于画布也是容器的子画面,其内容也将添加到纹理
  9. 泡沫,冲洗,重复步骤5 - 7
  10. 这是Swift中的一个示例实现,它在iPhone 6设备上以60 FPS绘制无穷无尽的行(您应该在不使用模拟器的设备上测试性能):

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