2015-05-28 2 views
8

Мне нужно создать cgpath непрерывно. На данный момент я делаю это так:Создать бесконечный cgpath без 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 

} 

И называю это так:

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

Но проблема в том, что кадры падения ниже и ниже в течение долгого времени. Есть ли что-то, что я должен изменить, чтобы частота кадров больше не снижалась?

Моя цель - создать случайный бесконечный путь.

+0

Я предположил бы, что вам нужно сбросить старые части вашего пути. В противном случае вы получаете все большее количество сегментов пути. Альтернативно, почему бы не создать новый путь каждый раз, когда будет достигнут конец текущего пути? – sangony

+0

Я не могу создать новый путь, потому что мне нужно, чтобы он был бесконечным или, по крайней мере, что новый путь не отображается для игрока. – Christian

+2

Это должно помочь [line caching] (http://stackoverflow.com/questions/24553245/poor-performance-with-skshapenode-in-sprite-kit) – 0x141E

ответ

4

Ключом к поддержанию высокого количества FPS при увеличении количества строк является быстрое достижение состояния, когда добавление большего количества строк в сцену мало или вообще не влияет на частоту кадров. Есть по крайней мере два способа достичь этого.

Наиболее простой из них состоит в том, чтобы периодически преобразовывать ранее нарисованные линии в SKTexture и отображать результаты как текстуру SKSpriteNode. Вот шаги:

  1. Создать SKNode для использования в качестве контейнера линии
  2. Создание SKSpriteNode, который будет использоваться в качестве линии холста
  3. Создание SKShapeNode будет использоваться для построения новых линий
  4. Добавить контейнер в место происшествия, а холст и узел формы - в контейнер
  5. Нарисуйте набор связанных сегментов линии с использованием свойства path объекта формы
  6. Когда количество строк достигает заданного значения, преобразуйте содержимое контейнера в 'SKTexture'
  7. Установите свойство текстуры холста на SKTexture. Обратите внимание, что, так как холст также является дочерним контейнером, его содержимое также будет добавлен к текстуре
  8. намыливать, полоскание, повторите шаги 5 - 7

Вот пример реализации в Swift, который привлекает бесконечное множество линий при 60 FPS на iPhone 6 устройства (вы должны проверить производительность на устройстве не с имитатором):

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

Что делать, если вы хотите, чтобы линия «исчезла», так что каждый частичный сегмент имеет немного больше альфа, чем предыдущий? Этот ответ по-прежнему применим в этом случае? Как насчет намеченной альтернативной техники? – Andrew

+0

@ Этот подход подходит для игр, которые рисуют большое количество строк, которые сохраняются.Я предлагаю вам создать изменяемый массив строк 'SKShapeNode', которые будут исчезать (изменяя свойство' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ''). – 0x141E

Смежные вопросы