2015-05-28 12 views
8

Potrzebuję utworzyć ciągłą ścieżkę cgpath. W tej chwili robię to tak:Twórz nieskończoną ścieżkę cgpath bez ramek

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 

} 

i nazwać tak:

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

Ale problemem jest to, że ramki spadać niżej i niżej w czasie. Czy jest coś, co muszę zmienić, aby framerate już nie spadło?

Moim celem jest stworzenie losowej, niekończącej się ścieżki.

+0

przypuszczam, że trzeba zrzucić stare części swojej drodze. W przeciwnym razie będziesz miał coraz większą liczbę segmentów ścieżki. Alternatywnie, dlaczego nie utworzyć nowej ścieżki za każdym razem, gdy dojdzie do końca bieżącej ścieżki? – sangony

+0

Nie mogę naprawdę stworzyć nowej ścieżki, ponieważ potrzebuję, aby była nieskończona lub przynajmniej, że nowa ścieżka nie jest widoczna dla gracza. – Christian

+2

To powinno pomóc [buforowanie linii] (http://stackoverflow.com/questions/24553245/poor-performance-with-skshapenode-in-sprite-kit) – 0x141E

Odpowiedz

4

Kluczem do utrzymania wysokiej liczby FPS podczas rysowania stopniowo rosnącą liczbę wierszy jest, aby szybko osiągnąć stan, w którym dodając kolejne linie do scena ma niewielki lub żaden wpływ na ilość klatek na sekundę. Istnieją co najmniej dwa sposoby, aby to osiągnąć.

Najprostszym z nich jest okresowa konwersja wcześniej narysowanych linii na SKTexture i wyświetlenie wyników jako tekstury SKSpriteNode. Oto kroki:

  1. Utwórz SKNode być stosowany jako pojemnik linii
  2. Załóż SKSpriteNode, który będzie używany jako płótna linii
  3. Załóż SKShapeNode być wykorzystane do opracowania nowych linii
  4. Dodawanie kontenera do sceny i kanwy oraz węzła kształtu do kontenera
  5. Rysowanie zestawu połączonych segmentów linii za pomocą właściwości path węzła kształtu
  6. Gdy liczba linii osiągnie określoną wartość, zamień zawartość kontenera na "SKTexture"
  7. Ustaw właściwość tekstury płótna na SKTexture. Warto zauważyć, że płótno jest również dzieckiem pojemnika, jego zawartość zostanie również dodany do tekstury
  8. Lather, spłukać, powtórzyć kroki 5 - 7

Oto realizacja przykład w Swift, który rysuje niekończąca zestaw linii w 60 FPS na urządzeniu iPhone 6 (należy przetestować działanie na urządzeniu nie z symulatorem):

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

Co jeśli chcesz linię do „fade out”, tak, że każdy odcinek częściowy ma trochę więcej niż jednego alfa poprzedzającego go? Czy ta odpowiedź nadal ma zastosowanie w takim przypadku? A co z nieuchwytną alternatywną techniką, o której wspomniałeś? – Andrew

+0

@Andrew tego podejścia jest dla gier, które rysuje duże Oś liczbowa, które nadal istnieją.Proponuję utworzyć zmienną tablicę linii 'SKShapeNode', która zaniknie (zmieniając właściwość' strokeColor') w czasie. – 0x141E