Actionscript 3.0: Colisiones a nivel de pixel

Etiquetas: complexIntersectionRectangle hitTestObject

La función hitTestObject(obj:DisplayObject) evalúa un objeto para comprobar si choca con el objeto obj. Por ejemplo, si tenemos dos objetos "Item1_mc" e "Item2_mc", podemos comprobar si chocan con:

  1.  
  2. Item1_mc.hitTestObject(Item2_mc)
  3.  

Esta función, tiene el inconveniente de que comprueba los choques entre los contenedores rectangulares de los objetos. Por ejemplo:

Colisiones en FLash

por tanto, sin queremos comprobar las colisiones entre dos objetos no rectangulares, puede devolver valores que aparentemente no son correctos. Aquí tenemos un ejemplo en Flash:

Si queremos utilizar colisiones a nivel de pixel, podemos crear un objeto bitmapData, superponer los dos objetos en el objeto bitmapData con un filtro de color cada uno, y comprobar si hay pixels que tienen el color de la combinación de filtros utilizados. En el blog de tink , podemos descargar una clase que nos ahorra todo este proceso y utilizar directamente métodos que nos devuelven true o false como resultado de la colisión. Por ejemplo, si queremos comprobar la colisión a nivel de pixel entre los dos objetos del ejemplo anterior, pondríamos:

  1.  
  2. HitTest.complexHitTestObject(Item1_mc,Item2_mc)
  3.  

Y si queremos recibir el rectángulo de colisión:

  1.  
  2. var rect:Rectangle = HitTest.complexIntersectionRectangle(Item1_mc,Item2_mc);
  3.  

El resultado, sería este:

Los fuentes, y la clase HitTest de tink, tras el salto.

mas

Problemas al cargar combobox en Actionscript 2.0

Esta trampa es una de esas alegrías que nos dá Flash de vez en cuando. La sorpresa se suele producir asi:

-Tenemos que hacer una película que luego vamos a cargar en otra película madre. En esta película "hija", utilizamos un combobox de los de Flash. Probamos nuestra película, y obtenemos algo parecido a esto:

-Una vez tenemos el SWF funcionando, probamos a cargarlo en la película madre, y obtenemos esto:

Como se puede ver, el combo está, aparece incluso la primera opción, pero no podemos desplegarlo.

La solución: hay que incluir una instancia de combobox en la biblioteca de la película principal.

Por suerte, esto sólo ocurre en Actionscript 2.0. En Actionscript 3.0 no hace falta tener el combo en la película principal.

mas

Comparar pixels de imágenes en Actionscript 3.0 con threshold

Etiquetas: BitmapData clone threshold

Comparar pixels de imágenes en Actionscript 3.0 con threshold

La función threshold permite hacer comparaciones pixel a pixel en una imagen. Por ejemplo, podemos separar todos los pixels mayores de un color de una imagen, y obtener otra imagen con esos pixels. La función threshold tiene 5 parámetros obligatorios (y varios opcionales):

threshold(sourceBitmapData:BitmapData, sourceRect:Rectangle, destPoint:Point, operation:String, threshold:uint)

-sourceBitmapData: la imagen que vamos a utilizar

-sourceRect: rectángulo que define el area de la imagen de origen que vamos a utilizar

-destPoint: punto de la imagen de destino que corresponde a la esquina superior izquierda del rectángulo

-operation: operación que vamos a utilizar

-threshold: valor con el que comparamos cada pixel

Por ejemplo, si queremos separar los pixels mayores de 0xFFCCCCCC de los menores en una imagen, podemos utilizar:

  1.  
  2. img1.threshold(img1, new Rectangle(0, 0, 350, 242), new Point(0, 0), ">", 0xFFCCCCCC);
  3. img2.threshold(img2, new Rectangle(0, 0, 350, 242), new Point(0, 0), "<=", 0xFFCCCCCC);

El código completo y los fuentes:

mas

Actionscript 3.0: Mostrar imagen en blanco y negro con ColorMatrixFilter

Etiquetas: ColorMatrixFilter filters

Actionscript 3.0: Mostrar imagen en blanco y negro con ColorMatrixFilter

La clase ColorMatrixFilter de Actionscript 3.0 permite aplicar una transformación a los valores de color y alfa de cada pixel de una imagen. Se puede aplicar sobre cualquier objeto que herede de la clase DisplayObject (es decir MovieClip, SimpleButton, TextField...).

Los filtros ColorMatrixFilter, se crean a partir de una matriz de transformación de 4x5, con lo valores de modificación que queremos aplicar a cada canal. Por ejemplo, si tenemos la matriz:

  1.  
  2. private var rLum:Number = 0.2225;
  3. private var gLum:Number = 0.7169;
  4. private var bLum:Number = 0.0606;
  5.  
  6. private var bwMatrix:Array = [rLum, gLum, bLum, 0, 0,
  7. rLum, gLum, bLum, 0, 0,
  8. rLum, gLum, bLum, 0, 0,
  9. 0, 0, 0, 1, 0];
  10.  

Podemos crear un filtro con ella, asi:

  1.  
  2. var filtroBW:ColorMatrixFilter
  3. filtroBW = new ColorMatrixFilter(bwMatrix);
  4.  

y aplicarlo a un MovieClip (que en este caso está en el escenario con el nombre Imagen2_mc):

  1.  
  2. Imagen2_mc.filters = [filtroBW]
  3.  

De esta manera, hacemos que el contenido de Imagen2_mc aparezca en blanco y negro, pero podemos modificar los valores de bwMatrix para obtener otros efectos.

El código completo y los fuentes, son estos:

mas

Comparando imágenes en Actionscript 3.0 con compare()

Etiquetas: BitmapData draw Bitmap compare

Comparando imágenes en Actionscript 3.0 con compare()

Esta prueba se me ha ocurrido hoy en el metro. Es algo muy sencillo, hacer una captura de un video, y compararla con la anterior para sacar los pixels diferentes y mostrar esta diferencia.

La comparación se puede hacer con la función compare de BitmapData:

  1.  
  2. var df:BitmapData = BitmapData(bmd.compare(ant));
  3.  

Hay que tener "cuidado" con esta función, ya que no siempre devuelve un objeto BitmapData. Según la ayuda de Flash:

Si los objetos BitmapData son equivalentes (con la misma anchura y altura e idénticos valores de píxeles), el método devolverá el número 0.

Si la anchura de los objetos BitmapData no es la misma pero la altura sí, el método devolverá el número -3.

Si la altura de los objetos BitmapData no es la misma pero la anchura sí, el método devolverá el número -4.

El video que he utilizado para la prueba es D.A.N.C.E., del grupo francés Justice.

mas

Actionscript 2.0: Problemas al pasar de texto a número

Etiquetas: String Number parseInt

Esta "trampa" de Flash, la descubrí la semana pasada en uno de los foros de Cristalab.

Uno de los usuarios tenia problemas al pasar Strings a números en Actionscript 2.0, siempre que los Strings tuvieran algún cero por la izquierda. Por ejemplo, si en Actionscript 2.0 hacemos:

  1.  
  2. var cadena:String = "033";
  3. var numero:Number = Number(cadena);
  4. trace(numero);
  5.  

El trace devuelve...27.

Como ya pensaba que era alguna especie de bug maligno de Flash, de esos que surgen en los momentos de crisis y con los que pierdes una tarde tranquilamente, se me ocurrió solucionarlo eliminando los ceros iniciales con un while:

  1.  
  2. var cadena:String = "033";
  3. while(cadena.substr(0,1) == 0){
  4. cadena = cadena.substr(1,cadena.length-1);
  5. }
  6. var numero:Number = Number(cadena);
  7. trace(numero);
  8.  

Devuelve 33.

Al mismo tiempo, Zguillez y Anduril encontraron la respuesta "lógica" a la maldad de Flash:

En Actionscript 2.0, si creas un número con un 0 como cifra inicial, Flash lo toma como número octal. Por eso "033" daba 27 al pasar a número:

033 = 3x8 + 3x1 = 27

Sabiendo esto, podemos convertir la cadena a entero en base 10, mediante la función parseInt, que recibe como parámetros la cadena y la base a la que queremos convertir el número:

  1.  
  2. var cadena:String = "033";
  3. var numero:Number = parseInt(cadena,10);
  4. trace(numero);
  5.  

Devuelve 33.

Por último, comentar que esto solo ocurre en Actionscript 2.0. Según la ayuda de Flash:

En ActionScript 3.0 la función Number() ya no admite números octales (de base 8). Si se suministra una cadena con un cero inicial a la función Number() de ActionScript 2.0, el número se interpreta como un número octal y se convierte en su equivalente decimal. Esto no es así con la función Number() de ActionScript 3.0, que omite el cero inicial.

mas

Actionscript 3.0: Ejemplo básico para cargar imágenes

Etiquetas: Loader URLRequest contentLoaderInfo addEventListener

Uno de los primeros post que escribí, fue "Carga de imágenes y SWF en AS3 con Loader" . Básicamente era una explicación de los diferentes eventos disponibles para trabajar con Loader, y de como añadirlos al objeto. Esta es una explicación más "sencilla" de como cargar una imagen, o un SWF en Actionscript.

Lo primero que tenemos que hacer es crear un objeto tipo Loader. Los Loader son los encargados de cargar imágenes (JPG, PNG o GIF) y SWFs en Flash. Esto lo hacemos así:

  1.  
  2. var loader:Loader = new Loader();
  3.  

Ahora que tenemos un "cargador", hay que pedirle que informe de los eventos de la carga. Hay muchos eventos, pero los principales son tres:

-Error al cargar la imagen (no se encuentra el archivo)

-Progreso de la imagen (nos informa del progreso de la carga)

-Imagen cargada (la imagen ya se ha cargado y podemos trabajar con ella).

Para que el Loader nos informe de estos eventos, tenemos que asociar cada uno a una función. Es decir, debemos decirle: "si la carga falla, ejecuta esta función, y si se carga, ejecuta esta". Esta charla, traducida a Actionscript 3.0 es:

  1.  
  2. loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imagenCargada);
  3. loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, imagenError);
  4. loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, imagenProgreso);
  5.  

Lo que hemos hecho es "añadir listener de los eventos". Como se puede ver, cada evento vá asociado a una función. El evento Event.COMPLETE, por ejemplo, está asociado a la función "imagenCargada". Estas funciones suelen tener esta apariencia:

  1. private function imagenCargada(e:Event):void {
  2. trace("Cargada: " + e);
  3. addChild(e.target.content);
  4. }
  5.  
  6. private function imagenError(e:IOErrorEvent):void {
  7. trace("Error: " + e);
  8. }
  9.  
  10. private function imagenProgreso(e:ProgressEvent):void {
  11. trace("Cargados=" + e.bytesLoaded + " Total=" + e.bytesTotal);
  12. }

Como se puede ver, cada función recibe un parámetro (al que hemos llamado "e", en este caso) que no servirá para obtener información del evento. Por ejemplo, cuando pongamos a cargar la foto, se comenzará a ejecutar periódicamente la función imagenProgreso hasta que termine la carga. Cada vez que Flash ejecute esa función, pasará como parámetro un "e distinto", que contendrá información sobre el progreso de carga en los atributos bytesLoaded y bytesTotal del evento.

Una vez que tenemos añadidos los eventos, tenemos que cargar la imagen mediante la función load:

  1.  
  2. loader.load( new URLRequest(url));
  3.  

Y listo. El loader que hemos creado se encargará de ejecutar las funciones asignadas a los eventos que le hemos asociado. El evento más importante es Event.COMPLETE, que ejecuta la función imagenCargada cuando el archivo termina de cargarse. Podemos acceder al archivo dentro del parámetro e.target.content den evento.

El código completo, sería el siguiente:

mas

Actionscript 3.0: Aplicar estilos CSS a campos de texto

Etiquetas: StyleSheet parseCSS styleSheet htmlText

Actionscript 3.0: Aplicar estilos CSS a campos de texto

Los campos de texto en flash pueden contener texto simple o texto en formato HTML. El texto en formato HTML se almacena en la propiedad htmlText. Sobre los campos con texto HTML podemos aplicar hojas de estilo CSS, creadas en el código de la aplicación o cargadas en tiempo de ejecución.

En este ejemplo vamos a ver como cargar un archivo css, y aplicar estos CSS a un TextField que contiene un teto HTML. La hoja de estilos que vamos a utilizar, es esta:

  1.  
  2. h1 {
  3. font-family: Times New Roman, Times, _serif;
  4. font-size: 30;
  5. font-weight: bold;
  6. }
  7. h2 {
  8. font-family: Arial, Helvetica, _sans;
  9. font-size: 24;
  10. }
  11. p{
  12. font-size: 15;
  13. }
  14. a{
  15. color: #009900;
  16. }
  17. a:hover{
  18. color: #00ff00;
  19. }
  20.  

Lo primero que tenemos que hacer, es cargar la hoja de estilos. Para ello, utilizamos una instancia de Loader:

  1.  
  2. cargador = new URLLoader();
  3. cargador.addEventListener(Event.COMPLETE, onCSSFileLoaded);
  4. cargador.load(new URLRequest("http://www.esedeerre.com/ejemplos/as3/css/ejemplo.css"));
  5.  

Una vez cargado el archivo, salta el evento COMPLETE, y creamos una instancia de StyleSheet, parseamos el CSS cargado, y se lo aplicamos al campo de texto. Después de aplicar el CSS al campo de texto, podemos rellenar el campo con el texto HTML que queramos:

  1.  
  2. public function onCSSFileLoaded(event:Event):void
  3. {
  4. var sheet:StyleSheet = new StyleSheet();
  5. sheet.parseCSS(cargador.data);
  6. campo.styleSheet = sheet;
  7. campo.htmlText = texto;
  8. }
  9.  

El código completo, y el ejemplo en Flash, tras el salto.

mas

Papervision GreatWhite: crear un plano con dos caras

Etiquetas: Plane DisplayObject3D Viewport3D BasicRenderEngine

Papervision GreatWhite: crear un plano con dos caras

Existen dos maneras de crear una plano con dos caras en Papervision3D:

-Crear un cubo con una profundidad de 1pixel, y utilizar las caras delantera y trasera como caras del plano.

-Crear un contenedor DisplayObject3D, y meter dentro dos planos. El plano "b" debe tener una profundidad de 1 y una rotatión de -180º.

El segundo método es el que me parece más cómodo, ya que gestionar los materiales con un cubo es más engorroso que con un plano. Un ejemplo de plano con dos caras podrías ser:

  1.  
  2. contenedor = new DisplayObject3D();
  3. var planoA = new Plane(new MovieAssetMaterial("CaraA"), 400, 400, 4, 4);
  4. var planoB = new Plane(new MovieAssetMaterial("CaraB"), 400, 400, 4, 4);
  5. planoB.z = 1;
  6. planoB.rotationY = -180;
  7. contenedor.addChild(planoA);
  8. contenedor.addChild(planoB);
  9. escena.addChild(contenedor);
  10.  

mas

Actionscript 2.0: Como dibujar un círculo

Etiquetas: lineTo lineStyle beginFill

Actionscript 2.0: Como dibujar un círculo

En la API de dibujo de Actionscript 2.0 no existe ninguna función para dibujar directamente un círculo (en Actionscript 3.0 tenemos drawCircle()). Sin embargo, podemos dibujar círculos con dos métodos diferentes.

El primero es el más intuitivo. Se trata de unir diversos puntos con lineTo() para formar el círculo. Por ejemplo podemos utilizar una función como esta para crear un círculo:

  1. function circuloLine(px, py, radio, color, alfa) {
  2. lineStyle(1,color,alfa);
  3. beginFill(color,alfa);
  4. moveTo(px+radio,py);
  5. for (grados=0; grados<=360; grados++) {
  6. x = radio*Math.cos(Math.PI/180*grados);
  7. y = radio*Math.sin(Math.PI/180*grados);
  8. lineTo(px+x, py+y);
  9. }
  10. endFill();
  11. }

Como se puede ver en la función son matemáticas básicas. Unimos 360 puntos, calculando las coordenadas con seno y coseno, y forman un círculo. En realidad es un polígono de 360 lados, pero los lados no se ven planos porque son muy pequeños. Para figuras muy grandes, se podría mejorar la función utilizando curveTo() en lugar de lineTo():

  1. function circuloCurve(px, py, radio, color, alfa) {
  2. lineStyle(1,color,alfa);
  3. beginFill(color,alfa);
  4. moveTo(px+radio,py);
  5. for (grados=0; grados<=360; grados++) {
  6. x = radio*Math.cos(Math.PI/180*grados);
  7. y = radio*Math.sin(Math.PI/180*grados);
  8. curveTo(px+x,py+y,px+x,py+y);
  9. }
  10. endFill();
  11. }

La función es la misma, pero en vez de unir los puntos por rectas, los unimos por curvas.

La tercera opción que conozco para dibujar un círculo, es la más rápida e ingeniosa. Se trata de dibujar una linea muy pequeña, pero con un grosor igual al diametro que buscamos. Sería como "dibujar un punto muy gordo". El resultado es el más exacto de los 3, además del más eficiente.

  1. function circuloPunto(px, py, radio, color, alpha){
  2. lineStyle(radio*2, color,alpha);
  3. moveTo(px,py);
  4. lineTo(px,py + 0.15);
  5. }

mas

Páginas: [1] [2] [3] 4 [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16]