2015-05-28 10 views
8

Ich muss einen cgpath kontinuierlich erstellen. Im Moment mache ich es wie folgt aus:Create endlosen cgpath ohne framedrops

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 

} 

Und nennen Sie es wie folgt aus:

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

Aber das Problem ist, dass die Rahmen fallen immer tiefer und tiefer über die Zeit. Muss ich etwas ändern, damit die Framerate nicht mehr abfällt?

Mein Ziel ist es, einen zufälligen endlosen Pfad zu erstellen.

+0

ich würde vermuten, dass Sie die alten Teile des Pfades entleeren müssen. Andernfalls haben Sie eine immer größere Anzahl von Pfadsegmenten. Alternativ können Sie nicht jedes Mal, wenn das Ende des aktuellen Pfads erreicht wird, einen neuen Pfad erstellen. – sangony

+0

Ich kann nicht wirklich einen neuen Pfad erstellen, weil ich brauche, dass es endlos ist oder zumindest, dass ein neuer Pfad für den Spieler nicht sichtbar ist. – Christian

+2

Das sollte helfen [line caching] (http://stackoverflow.com/questions/24553245/poor-performance-with-skshapenode-in-sprite-kit) – 0x141E

Antwort

4

Der Schlüssel zum Aufrechterhalten einer hohen FPS-Anzahl beim Zeichnen einer progressiv zunehmenden Anzahl von Zeilen besteht darin, schnell einen Zustand zu erreichen, in dem das Hinzufügen von mehr Zeilen zur Szene die Bildrate wenig oder gar nicht beeinflusst. Es gibt mindestens zwei Möglichkeiten, dies zu erreichen.

Die einfachste der zwei ist, die zuvor gezeichneten Linien in eine SKTexture zu konvertieren und die Ergebnisse als Textur eines SKSpriteNode anzuzeigen. Hier sind die Schritte:

  1. Neues SKNode als Linie Behälter verwendet werden
  2. eine SKSpriteNode erstellen, die als Linie Leinwand verwendet wird
  3. eine SKShapeNode erstellen verwendet werden, um neue Linien zu zeichnen
  4. Fügen Sie den Container der Szene und dem Canvas- und Formknoten dem Container hinzu.
  5. Zeichnen Sie eine Gruppe verbundener Liniensegmente unter Verwendung der path-Eigenschaft des Formknotens
  6. Wenn die Zeilenanzahl einen vorgegebenen Wert erreicht, konvertieren Sie den Inhalt des Containers in eine 'SKTexture'.
  7. Legen Sie die Textureigenschaft der Zeichenfläche auf SKTexture fest. Beachten Sie, dass, da die Leinwand auch ein Kind des Behälters ist, sein Inhalt wird auch auf die Textur
  8. Lather hinzugefügt werden, spülen Sie Schritte 5 - 7

Hier ist ein Beispiel-Implementierung in Swift, die zieht eine endlose Reihe von Linien bei 60 FPS auf einem iPhone 6-Gerät (Sie auf einem Gerät nicht mit dem Simulator testen Leistung sollen):

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

Was ist, wenn die Linie "ausgeblendet" werden soll, so dass jedes Teilsegment ein wenig mehr Alpha hat als das vorherige? Ist diese Antwort in diesem Fall noch anwendbar? Was ist mit der schwer fassbaren alternativen Technik, die du angedeutet hast? – Andrew

+0

@Andrew dieser Ansatz ist für Spiele, die eine große Anzahl von Zeilen zieht, die bestehen bleiben.Ich schlage vor, Sie erstellen ein veränderbares Array von 'SKShapeNode'-Zeilen, die im Laufe der Zeit verblassen (indem Sie die Eigenschaft' strokeColor' ändern). – 0x141E