Создать бесконечный 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 ответ
Ключом к поддержанию высокого количества кадров в секунду при рисовании постепенно увеличивающегося количества линий является быстрое достижение состояния, при котором добавление большего количества линий в сцену практически не влияет на частоту кадров. Есть как минимум два способа сделать это.
Самым простым из них является периодическое преобразование ранее нарисованных линий в SKTexture
и отображать результаты в виде текстуры SKSpriteNode
, Вот шаги:
- Создать
SKNode
для использования в качестве линейного контейнера - Создать
SKSpriteNode
это будет использоваться как холст линии - Создать
SKShapeNode
использоваться для рисования новых линий - Добавьте контейнер на сцену и узел Canvas и shape в контейнер
- Нарисуйте набор связанных отрезков линии, используя
path
свойство узла формы - Когда счетчик строк достигает заданного значения, преобразуйте содержимое контейнера в 'SKTexture'
- Установите свойство текстуры холста на
SKTexture
, Обратите внимание, что поскольку canvas также является дочерним элементом контейнера, его содержимое также будет добавлено в текстуру. - Вспенить, промыть, повторить шаги 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()
}
}