Anoche hice un pequeño prototipo de simulador (con sus fallos y sin ser todavía todo lo rápido que debería) de fuegos artificiales usando flash para una cosa que quiero hacer. Y ya puestos me gustaría enseñarlo y comentar algunas cosas que considero interesantes.

Explicación y demo en flash tras el salto.

Nota: La demo en flash es un revienta ordenadores. Especialmente si cambiáis de pestaña y volvéis al poco xd. Lo he hecho y probado en un i7 bastante potente, así que es fácil que en ordenadores más modestos no vaya nada fino. La resolución real del flash (y de los BitmapData) es de 960x640, así que es un downscale y entre unas cosas y otras, que está pintado por software, y con un solo core, tiene bastante tralla.

He reducido a un cuarto la resolución del flash. Y lo he puesto a la resolución original con lo que debería ir mucho mejor en ordenadores modestos.

Movimiento:

Primero me encontré ante el problema del movimiento de partículas. Consideré varias opciones: usar alguna librería de físicas, usar fórmula de movimiento rectilinio uniformemente acelerado (que en este caso es suficiente), o hacer simulaciones paso a paso si la precisión de los double (64 bits) que usa flash me servía en este caso.

Hice pruebecitas y al final me quedé con la simulación paso a paso, que me permitía todo el control que quisiese, me quitaba dependencias externas y me permitía optimizarlo lo que necesitase. Aunque esta aproximación tiene también muchos puntos débiles, que son la precisión de la coma flotante, la predictividad y la posibilidad de saltar pasos en momentos de carga, con lo que muchos rangos de parámetros me tocó definirlos por ensayo y error. Después de este spike es posible que en la implementación final me plantease usar formulas determinísticas para evitar todos estos problemas. Realmente para este problema la cinemática se me antoja bastante mejor que la dinámica.

Lo que hice fue calcular las variaciones de posición y de velocidad en cada iteración por cada partícula. Simulé la atenuación y la resistencia a lo cutre, con un simple factor. Más que exacto me interesaba que fuese rápido y resultón. Cuando una partícula de primer nivel empezaba a descender, explota. La explosión produce X partículas que toman todas las direcciones y con una atenuación que va reduciendo la velocidad de las partículas y reduciendo la gravedad para simular la resistencia con el aire sin tener que hacer más operaciones.

Renderización:

La renderización inicial fue un movieclip por partícula sin efectos de ningún tipo. Luego, para simular la atenuación progresiva de la luz, lo que hice fue pintar en cada frame todas las partículas en un BitmapData, luego pintar antes  de cada frame un rectángulo negro medio transparente en el BitmapData de forma que hiciese un poco más oscuro lo que ya había. Flash hace todas estas cosas por software y se queda medio frito, aunque mi implementación final estará hecha usando la tarjeta gráfica y todos estos efectos los hará sobradísima.

Hay una cosa que mola bastante cuando ves fuegos articiales. Suele ser de noche y la luz ilumina las nubes. Queda muy guay, y no podía permitirme no implementar algo que le da tanta vidilla. Apliqué un pequeño truco que desarrollé hace tiempo. Consiste en tener dos imágenes: una con el color y otra con el canal alpha. Flash permite copiar un canal (incluso con transformaciones de color) de un BitmapData sobre otro, incluyendo la transferencia del canal alpha. Debido a que flash permultiplica el canal alpha, hacen falta 3 BitmapData para no perder información. Una con el color, otro con el canal alpha y un último que juntará ambos. (Pintamos el de color primero y luego definimos el canal alpha). Cada vez que había una explosión, se pinta un círculo con un degradado radial cobre el canal alpha. En cada iteración se atenúa el bitmap con el canal alpha de la misma forma que se atenuaba la luz de las partículas.

El color de la imagen de fondo es procedural, usando la implementación de PerlinNoise que soporta el BitmapData.