Comunidad de diseño web y desarrollo en internet online

Efecto de fuego con BitmapData en Flash 8

En este tip les mostraré cómo simular llamas y fuego con Flash 8 y la clase BitmapData. Cómo en otros ejemplos de esta serie de efectos, basta con emplear adecuadamente la mezcla de perlinNoise y el Desplazamiento de Mapa de bits y sus parámetros para conseguirlo:

Este es un código muy simple para iniciarse:

Solo hay que vincular una imagen con nombre "imagen" desde la biblioteca.

Código :

import flash.display.BitmapData;
import flash.geom.*;
import flash.filters.*;
img = BitmapData.loadBitmap("imagen");
createEmptyMovieClip("efecto", 0);
efecto.attachBitmap(img, 0);
efecto._yscale = 190;
efecto._xscale = 160;
olas = ola = new BitmapData(efecto._width, efecto._height);
offset = new Point(0, 0);
desMap = new DisplacementMapFilter(olas, new Point(50, 40), 1, 1, 100, -100, "warp");
onEnterFrame = function ()
{
   offset.y += 10;
   //offset.x -= 9.8;
   ola.perlinNoise(6, 18, 2, 0, true, true, 1, true, [offset]);
   efecto.filters = [desMap];
};


Usando una imagen que es "medio sol" no genera este resultado:



Veamos ahora como "mejorar" el código para aumentar el realismo.

Añadimos filtros de Blur y Transformación de color combinados a un MovieClip cualquiera e con el nombre de instancia MCtexto. Como siempre hay que ajustar los parámetros al gusto o necesidad.

Este es el código:

Código :

import flash.filters.*;
import flash.geom.*;
import flash.display.*;
w = MCtexto._width + 20;
h = MCtexto._height + 150;
ori = new BitmapData(w, h, true, 0xffaa6600);
createEmptyMovieClip("marco", 1);
sal = new BitmapData(w, h, true, 0xff000000);
capt = sal.clone();
dif = sal.clone();
marco.attachBitmap(sal, 0);
Mx = new Matrix();
Pt = new Point();
R0 = sal.rectangle;
B1 = new BlurFilter(2, 4, 2);
CM1 = new ColorMatrixFilter([.33, .33, .33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, .5, 0, 0, 0, 0, 1, 0]);
CM2 = new ColorMatrixFilter([.72, .5, 0, 0, 0, .02, .65, 0, 0, 0, 0, 0, .25, 0, 0, 0, 0, 0, 1, 0]);
DM1 = new DisplacementMapFilter(dif, Pt, 1, 2, -6, -36);
MCtexto._visible = false;
setInterval(flamatexto, 40);
function flamatexto()
{
   dif.draw(capt);
   capt.draw(MCtexto);
   dif.applyFilter(dif, R0, Pt, CM1);
   dif.threshold(dif, R0, Pt, ">", 0xff330000, 0xff808080, 0x00ffffff);
   dif.applyFilter(dif, R0, Pt, B1);
   sal.draw(dif, Mx, null, 8);
   dif.perlinNoise(9, 18, 3, random(255), false, true, 7, false);
   dif.draw(ori, Mx, null, 6);
   sal.applyFilter(sal, R0, Pt, DM1);
   sal.applyFilter(sal, R0, Pt, CM2);
}


Añado un botón para bajar el FLA para que lo podáis trastear mejor:



El "encendido" que le he puesto al ejemplo se puede modificar o anular cambiando este parámetro:
  • dif.threshold(dif, R0, Pt, ">", 0xff330000, 0xff808080, 0x00ffffff);

Por ejemplo podemos poner valores mayores o menores en el rojo. 0xff120000 ó 0xff440000.

Depende también de la transparencia y color del relleno del MCtexto (instancia) usado.

La "agitación" de la llama está controlada por el Perlin Noise y la "intensidad" y dirección por el Desplazamiento de mapa de bits. El color evidentemente pertenece a los valores de la matriz de ColorTransform.

Veamos ahora un ejemplo de llama simple.


Este efecto simula una llama de vela. No necesita ninguna imagen. Simplemente copiar y pegar. Crea un gradiente y se le aplican los filtros y métodos. Como siempre variando los parámetros conseguimos cambios de color, forma, velocidad..etc.

Código :

createEmptyMovieClip("llama", 0);
colores = [0xffffffff, 0xfff2f215, 0xffff9900, 0xff00000f];
alphas = [40, 90, 85, 40];
ratios = [20, 90, 175, 235];
Pt = new flash.geom.Point();
Mx = new flash.geom.Matrix();
Mx.createGradientBox(30, 90, Math.PI / 2, 0, 10);
with (llama) {
   beginGradientFill("radial", colores, alphas, ratios, Mx, "pad", "RGB", .98);
   moveTo(0, 0);
   lineTo(0, 100);
   lineTo(40, 100);
   lineTo(40, 0);
   lineTo(0, 0);
   endFill();
}
ola = new flash.display.BitmapData(llama._width, llama._height + 30);
dM = new flash.filters.DisplacementMapFilter(ola, null, 1, 1, 3, 3, "ignore");
onEnterFrame = function ()
{
   Pt.y += 3.3;
   Pt.x -= .3;
   a = random(7) * (random(10) < 1);
   llama._yscale = 120 + a;
   llama._y = -a;
   ola.perlinNoise(24, 32, 1, 0, true, true, 1, false, [Pt]);
   llama.filters = [dM];
};



0,5 Kb


Prosigamos, ahora vamos a dar movimiento un "objeto ardiente":

Añadimos ahora algunas cosillas más (que ya había ido colocando poco a poco en otros efectos de esta serie) sobre filtros y Blendmode.

Como casi siempre en los ejemplos anteriores y por seguir ese estilo, vincularemos una imagen desde la biblioteca con nombre "imagen" y pondremos simplemente el código en el primer fotograma del raiz.

Podemos clicar en la imagen para cambiar los Blendmode.


4.7Kb


Código :

import flash.filters.*;
import flash.geom.*;
import flash.display.*;
velox = veloy = 8;
img = BitmapData.loadBitmap("imagen");
ori = new BitmapData(400, 300, false, 0xff8000);
createEmptyMovieClip("marco", 1);
createEmptyMovieClip("marco2", 2);
img2 = marco2.createEmptyMovieClip("copia", 0);
img2.attachBitmap(img, 5);
marco2.blendMode = 7;
marco.blendMode = 7;
sal = new BitmapData(400, 300, false, 0);
capt = sal.clone();
dif = sal.clone();
sal.draw(img);
marco.attachBitmap(sal, 0);
Mx = new Matrix();
Pt = new Point();
R0 = new Rectangle(0, 0, 400, 300);
B1 = new BlurFilter(6, 6, 2);
CM1 = new ColorMatrixFilter([.3, .3, .3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0]);
CM2 = new ColorMatrixFilter([.7, .5, 0, 0, 0, 0, .7, 0, 0, 0, 0, 0, .5, 0, 0, 0, 0, 1, 0]);
DM1 = new DisplacementMapFilter(dif, Pt, 1, 2, 6, -24, "clamp");
setInterval(flama, 20);
function flama()
{
   dif.draw(capt);
   capt.draw(marco2);
   dif.draw(capt, Mx, null, 7);
   dif.applyFilter(dif, R0, Pt, CM1);
   dif.threshold(dif, R0, Pt, ">", 0x330000, 0xffaaaaaa, 0xff0000);
   dif.applyFilter(dif, R0, Pt, B1);
   sal.draw(dif, Mx, null, 8);
   dif.perlinNoise(10, 10, 2, random(255), false, true, 7, false);
   dif.draw(ori, Mx, null, 6);
   sal.applyFilter(sal, R0, Pt, DM1);
   sal.applyFilter(sal, R0, Pt, CM2);
   img2._x += velox;
   img2._y += veloy;
   img2._x > 300 || img2._x < 0 ? velox = -velox : null;
   img2._y > 200 || img2._y < 0 ? veloy = -veloy : null;
}


Al clicar en la imagen cambia el valor de marco2.blendMode entre 0 y 14. Cómo siempre es bueno experimentar con los valores del PerlinNoise y del Desplazamiento de mapa. Con ello conseguiremos mas fuerza, viveza, velocidad, forma , etc...

El cambio en los colores de los filtros de color evidentemente coloreará de otro modo la "estela".
En este ejemplo es importante el fondo donde se efectúa (por el Blend) de modo que distintos fondos también crean distintos efectos.

Le he puesto en la función un simple movimiento de rebote para presentar el efecto (puede ser cualquiera).

También manejando algunas "cargas" del filtro podemos hacer el efecto de quemar un papel o mapa , cortar a laser, etc, etc... Ya los iré posteando.

La imagen puede ser un logo, texto, o forma cambiante.......

Veamos ahora una pequeña variación de este código fusionado junto a otro antiguo código que posteé sobre detección por cam y tendremos la ya muy conocida fuegocam:

Aquí lo que tenemos que poner en la biblioteca es el icono de la cam. Arrastramos la misma al escenario y la colocamos en la esquina superior izquierda. A esa instancia la llamamos cam y ponemos el código en el primer frame del raiz.

Código :

import flash.filters.*;
import flash.geom.*;
import flash.display.*;
cam.attachVideo(Camera.get());
createEmptyMovieClip("marco", 1);
marco.blendMode = 8;
marco._xscale = marco._yscale = cam._xscale = cam._yscale = 250;
w = cam._width;
h = cam._height;
sal = new BitmapData(w, h, false, 0);
capt = sal.clone();
dif = sal.clone();
marco.attachBitmap(sal, 0);
ori = new BitmapData(w, h, false, 0xff8000);
Mx = new Matrix();
Pt = new Point();
R0 = new Rectangle(0, 0, w, h);
B1 = new BlurFilter(6, 6, 1);
CM1 = new ColorMatrixFilter([.3, .3, .3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0]);
CM2 = new ColorMatrixFilter([.7, .5, 0, 0, 0, 0, .7, 0, 0, 0, 0, 0, .5, 0, 0, 0, 0, 1, 0]);
DM1 = new DisplacementMapFilter(dif, Pt, 1, 2, 6, -24);
setInterval(flamacam, 30);
function flamacam()
{
   dif.draw(capt);
   capt.draw(cam);
   dif.draw(capt, Mx, null, 7);
   dif.applyFilter(dif, R0, Pt, CM1);
   dif.threshold(dif, R0, Pt, ">", 0x330000, 0xffaaaaaa, 0xff0000);
   dif.applyFilter(dif, R0, Pt, B1);
   sal.draw(dif, Mx, null, 8);
   dif.perlinNoise(10, 10, 2, random(255), false, true, 7, false);
   dif.draw(ori, Mx, null, 6);
   sal.applyFilter(sal, R0, Pt, DM1);
   sal.applyFilter(sal, R0, Pt, CM2);
}


Este es el resultado:


0,7Kb


Cómo siempre se puede jugar algo con los parámetros para afinarlo a nuestras propias necesidades o estilo.

Nota: Al estar varios SWF activos al mismo tiempo, puede que ordenadores lentos presenten los efectos a saltos. Es conveniente pausar el swf antes de abrir otro.

¿Sabes SQL? ¿No-SQL? Aprende MySQL, PostgreSQL, MongoDB, Redis y más con el Curso Profesional de Bases de Datos que empieza el martes, en vivo.

Publica tu comentario

o puedes...

¿Estás registrado en Cristalab y quieres
publicar tu URL y avatar?

¿No estás registrado aún pero quieres hacerlo antes de publicar tu comentario?

Registrate