Cómo mantener la animation iOS sin problemas con muchas subvenciones.

Estoy probando diferentes looks de un pequeño juego que estoy escribiendo para jugar con animation en iOS.

Mi objective es tener una grilla de fichas que, según el juego, cambie la visualización de cada ficha a una de un set de imágenes. Me gustaría que cada ficha (hasta 24×24) se voltea cuando cambia la cara. A medida que avanza el juego, es necesario voltear más y más fichas al mismo time. En la primera implementación en la que traté de voltearlos simultáneamente la animation se puso muy desigual.

Cambié mi enfoque para no voltearlos todos a la vez, sino unos pocos a la vez, progtwigndo la animation para cada mosaico con un retraso ligeramente creciente por mosaico, de modo que cuando se diga que el mosaico 10 comienza a animar, el primero ya está hecho. Se tarda un poco más en terminar todo el process, pero también conduce a un bonito efecto de ondulación visual.

Captura de pantalla desde el simulador

Sin embargo, sigue habiendo un problema: al comienzo de un movimiento de juego, cuando el jugador selecciona un nuevo color, toma algunas fracciones de segundo en el dispositivo, antes de que comience la animation. Esto empeora a medida que avanza el juego y es necesario progtwigr más vueltas por movimiento, hasta el punto en que la animation parece colgar y luego se completa casi instantáneamente sin que ninguno de los fotogtwigs en medio sea realmente discernible.

Este es el código (en mi subclass de la grilla del juego UIView ) que activa el cambio de fichas relevantes. (Eliminé una optimization que omite fichas, porque solo importa en las primeras etapas del juego).

 float delay = 0.0f; for (NSUInteger row=0; row<numRows; row++) { for (NSUInteger col=0; col<numCols; col++) { delay += 0.03f; [self updateFlippingImageAtRow:row col:col delay:delay animated:YES]; } } 

La vista de cuadrícula del juego tiene una NSArray de subvistas de baldosas que se abordan utilizando las variables row y col en el ciclo anterior.

updateFlippingImageAtRow:col:delay:animated es un método en mi FlippingImageView (también una subclass de UIView ) se networkinguce a esto (se omite la lógica del juego):

 -(void)animateToShow:(UIImage*)image duration:(NSTimeInterval)time delay:(float)delay completion:(void (^)(BOOL finished))completion { [UIView animateWithDuration:time delay:delay options:UIViewAnimationOptionTransitionFlipFromLeft animations:^{ [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self cache:YES]; self.frontImage = image; } completion:completion ]; } 

Funciona bien, sin embargo, concluyo desde la medición de Instrumentos que me dice que mi time se gasta en el bloque de animation, que a medida que avanza el juego y aumenta la cantidad de fichas para voltear, la cantidad de animaciones que se progtwign en el El comienzo de la operación es un problema, y ​​el sistema intenta ponerse al día al eliminar los cuadros.

Imagen de pantalla de instrumentos de algunas operaciones de flip

¿Alguna sugerencia sobre cómo mejorar el performance de esto? El momento exacto de la animation no es realmente importante.

Puedes pensar en hacer esto con CoreAnimation y CALayers en lugar de UIViews. Es increíblemente poderoso y optimizado marco.

No es algo fácil, tendrás que recodificar al less algunas de tus classs (ver jerarquía y testings de impacto son las primeras cosas que vienen a mi mente), pero vale la pena intentarlo y es un process bastante sencillo, porque CALayer es muy similar a UIView.

El próximo paso es OpenGL. Definitivamente puede operar varios cientos de objects en time real, pero requiere mucho más trabajo por hacer.

Es posible que desee intentar usar CoreAnimation en su lugar. Una forma de hacer la animation invertida sería:

  • Cree una CABasicAnimation que anima la primera mitad del flip (rotation a lo largo del eje y).
  • En el método delegate animationDidStop:finished: configura la nueva image y luego crea una nueva animation que anima la segunda mitad.
  • Simplemente aplica la animation a la propiedad de layer de su vista.
  • Tenga en count que puede usar setValue:forKey: para "anotar" una animation (recuerde de qué object se trata la animation). Cuando agrega una animation a una capa, se copy, no se retiene, por lo que no puede identificarla simplemente comparando valores de puntero.