Sprite Kit: Un montón de sprites (1000+) con Bit Blitting

Estoy tratando de crear una escena con SpriteKit que tiene miles de sprites (~ 500 – 2000). Cada sprite es solo un píxel blanco 1×1, no hay necesidad de usar texturas para ellos.

Agregar estos sprites a la escena directamente a la vez es imposible (o al less así lo creo). En iPhone 6 termino con ~ 200 sprites agregados, luego el sistema termina el process de adición debido a la memory y el rest de los sprites no se agregan.

He encontrado una solución inteligente a este llamado Bit Blitting en el que todos los sprites se agregan a un nodo, que luego se "convierte" en textura con textureFromNode: método y de esta textura se crea un solo sprite que finalmente se agregará a un pantalla. Funciona muy bien y puedo crear más de 10 000 sprites a la vez con grandes fps.

Mi problema es que no puedo mover estos sprites después (= cambiar de position). La textura siempre permanece igual sin importar lo que haga. ¿Qué me estoy perdiendo?

Mi código:

 override func didMoveToView(view: SKView) { self.generateRandomSprites() } func generateRandomSprites() { let texture = SKTexture(imageNamed: "whitePixel") self.canvasNode = SKNode() log("started generating all sprites") for var i = 0;i < 1000;i++ { let width = self.scene!.frame.size.width let height = self.scene!.frame.size.height let x: CGFloat = CGFloat(arc4random_uniform(UInt32(width))) let y: CGFloat = CGFloat(arc4random_uniform(UInt32(height))) let cell = SKSpriteNode(texture: texture) cell.position = CGPointMake(x, y) self.arrCells.append(cell) self.canvasNode.addChild(cell) } self.canvasTexture = self.view!.textureFromNode(self.canvasNode) self.canvasSprite = SKSpriteNode(texture: self.canvasTexture, size: self.frame.size) self.canvasSprite.anchorPoint = ccp(0,0) self.addChild(self.canvasSprite) } override func update(currentTime: CFTimeInterval) { for oneCell in self.arrCells { oneCell.position = CGPointMake(oneCell.position.x + 1, oneCell.position.y) } self.canvasTexture = self.view!.textureFromNode(self.canvasNode) self.canvasSprite.texture = self.canvasTexture } 

Captura de pantalla de la aplicación (esto es estático, no pasa nada):

introduzca la descripción de la imagen aquí

Esta no es la respuesta, sino una colección de cosas que he intentado.

Realmente tengo curiosidad por ese código. Lo intenté y no funcionó. Cambié el método de actualización para simplemente colocar los puntos en posiciones aleatorias y funciona:

Entonces tengo una pregunta. ¿Por qué el código no se puede actualizar desde su position actual o es un arenque rojo?

 override func update(currentTime: CFTimeInterval) { let width = self.scene!.frame.size.width let height = self.scene!.frame.size.height for oneCell in self.canvasNode.children as! [SKSpriteNode] { let x: CGFloat = CGFloat(arc4random_uniform(UInt32(width))) let y: CGFloat = CGFloat(arc4random_uniform(UInt32(height))) oneCell.position = CGPointMake(x, y) } self.canvasTexture = self.view!.textureFromNode(self.canvasNode) self.canvasSprite.texture = self.canvasTexture } 

ok, he estado jugando con esto aún más, esto funciona, solo obteniendo un valor aleatorio y agregando eso al puesto …

 override func update(currentTime: CFTimeInterval) { let width = self.scene!.frame.size.width let height = self.scene!.frame.size.height for oneCell in self.canvasNode.children as! [SKSpriteNode] { let x2: CGFloat = CGFloat(arc4random_uniform(UInt32(10))) let y2: CGFloat = CGFloat(arc4random_uniform(UInt32(10))) let x:CGFloat = oneCell.position.x - x2 let y:CGFloat = oneCell.position.y - y2 let point = CGPointMake(x, y) oneCell.position = point } self.canvasTexture = self.view!.textureFromNode(self.canvasNode) self.canvasSprite.texture = self.canvasTexture } 

Ahora creo que tiene algo que ver con el comstackdor, ya que funciona:

 override func update(currentTime: CFTimeInterval) { let width = self.scene!.frame.size.width let height = self.scene!.frame.size.height var x3:CGFloat = 10.0 var y3:CGFloat = 10.0 for oneCell in self.canvasNode.children as! [SKSpriteNode] { let x:CGFloat = oneCell.position.x - x3 let y:CGFloat = oneCell.position.y - y3 let point = CGPointMake(x, y) oneCell.position = point x3 += 0.01 } self.canvasTexture = self.view!.textureFromNode(self.canvasNode) self.canvasSprite.texture = self.canvasTexture } 

Más investigación, Interesante, si usa el valor 1.3 y ejecuta el código, puede ver que los puntos cambian una vez. ( http://llvm.org/docs/LangRef.html#simple-constants )

 override func update(currentTime: CFTimeInterval) { let width = self.scene!.frame.size.width let height = self.scene!.frame.size.height for oneCell in self.canvasNode.children as! [SKSpriteNode] { let x:CGFloat = oneCell.position.x - 1.3 let y:CGFloat = oneCell.position.y - 1.3 let point = CGPointMake(x, y) oneCell.position = point } self.canvasTexture = self.view!.textureFromNode(self.canvasNode) self.canvasSprite.texture = self.canvasTexture } 

Un número como 50.3333333333 muestra sacudidas visibles, pero luego parece detenerse.

Para ser honesto, creo que el enfoque que sugiere no va a funcionar bien y parece realmente complejo sin razón. Por ejemplo, con SpriteKit puede crear un nodo con un color de textura de background y hacer que sea 1×1 sin hacer ninguna de estas cosas blit. Me gusta esto:

 SKSpriteNode *node = [SKSpriteNode spriteNodeWithColor:[UIColor whiteColor] size:CGSizeMake(1,1)];