Hola, estoy diseñando una "pizarra" de dibujos para niños y estoy intentando diseñar la parte del "bote de pintura" pero me estoy encontrando con que el script ralentiza la animación hasta tal punto que me sale el dichoso mensaje de que "Un script está haciendo que Flash Player vaya como el cu...". Y por el momento no encuentro una manera más eficiente de hacerlo. Os explico cómo tenía pensado hacerlo:

Después de probar de distintas maneras se me ocurrió lo siguiente: tengo por un lado una imagen con el dibujo totalmente en blanco con las líneas del dibujo negras. Entonces al hacer clic con el bote de pintura, lo que hago es detectar en el dibujo con un BitmapData cuándo me encuentro con un píxel en negro. Para ir rellenando de un color, lo que hago es intentar dibujar en todas direcciones, arriba, abajo, izquierda y derecha. Cuando me quedo "atascado", vuelvo hacia atrás a intentar otro "movimiento". Cuando haya vuelto al primero y no pueda seguir "moviéndome", habré terminado de dibujar el área.

Os pongo el código:

Código :

function Bote(bmd:BitmapData,pos_x:Number,pos_y:Number)
{
   // bmd es el bitmap donde guardo qué pixeles dibujo para al final aplicarlos a un nuevo mc
   // _global.BitmapDibujo es la imagen que tengo en blanco y negro para detectar cuándo llego
   // al borde del área para dibujar
   // _global.ColorPincel es el color seleccionado para rellenar el área
   
   // Comprobamos que el punto esté en las coordenadas del lienzo
   if((pos_x>200)&&(pos_x<680)&&(pos_y>20)&&(pos_y<740))
   {
      if(_global.BitmapDibujo.getPixel(pos_x,pos_y).toString(16)<>"000000")
      {
         // El pixel no está en negro, así que comenzamos
         Coordenadas=new Array();
         // Apuntamos el punto en las coordenadas
         // Indice activo (ia): índice del vector de coordenadas ya dibujadas
         var ia:Number=0;
         Coordenadas[ia]=Array(pos_x,pos_y);
         while(ia>=0)
         {
            atasco=true;
            // Probamos a ir hacia arriba
            // Tres comprobaciones: si está fuera de las coordenadas, si es un pixel negro
            // y si ya está dibujado con el color del pincel. Si se da algun caso, es un atasco
            // y hay que probar con otro "movimiento".
            if((Coordenadas[ia][0]>200)&&(Coordenadas[ia][0]<680)&&
               ((Coordenadas[ia][1]-1)>20)&&((Coordenadas[ia][1]-1)<740))
            {
               if(_global.BitmapDibujo.getPixel(
                  Coordenadas[ia][0],(Coordenadas[ia][1]-1)).toString(16)<>"000000")
               {
                  if(bmd.getPixel(Coordenadas[ia][0],(Coordenadas[ia][1]-1))<>
                     _global.ColorPincel)
                  {
                     // Se puede pintar. Quitamos el atasco
                     atasco=false;
                     // Dibujamos el pixel
                     bmg.setPixel(Coordenadas[ia][0],(Coordenadas[ia][1]-1),
                        _global.ColorPincel);
                     // Añadimos el nuevo pixel a la lista
                     Coordenadas[ia+1]=Array(Coordenadas[ia][0],(Coordenadas[ia][1]-1));
                     ia=ia+1;
                  }
               }
            }
            // Si sigue habiendo atasco, probamos con el de la izquierda
            if(atasco==true)
            {
               if(((Coordenadas[ia][0]-1)>200)&&((Coordenadas[ia][0]-1)<680)&&
                  ((Coordenadas[ia][1])>20)&&(Coordenadas[ia][1]<740))
               {
                  if(_global.BitmapDibujo.getPixel(
                     (Coordenadas[ia][0]-1),Coordenadas[ia][1]).toString(16)<>"000000")
                  {
                     if(bmd.getPixel((Coordenadas[ia][0]-1),Coordenadas[ia][1])<>
                        _global.ColorPincel)
                     {
                        // Se puede pintar. Quitamos el atasco
                        atasco=false;
                        // Dibujamos el pixel
                        bmg.setPixel((Coordenadas[ia][0]-1),Coordenadas[ia][1],
                           _global.ColorPincel);
                        // Añadimos el nuevo pixel a la lista
                        Coordenadas[ia+1]=Array((Coordenadas[ia][0]-1),Coordenadas[ia][1]);
                        ia=ia+1;
                     }
                  }
               }
            }
            // Si sigue habiendo atasco, probamos con el de abajo
            if(atasco==true)
            {
               if((Coordenadas[ia][0]>200)&&(Coordenadas[ia][0]<680)&&
                  ((Coordenadas[ia][1]+1)>20)&&((Coordenadas[ia][1]+1)<740))
               {
                  if(_global.BitmapDibujo.getPixel(
                     Coordenadas[ia][0],(Coordenadas[ia][1]+1)).toString(16)<>"000000")
                  {
                     if(bmd.getPixel(Coordenadas[ia][0],(Coordenadas[ia][1]+1))<>
                        _global.ColorPincel)
                     {
                        // Se puede pintar. Quitamos el atasco
                        atasco=false;
                        // Dibujamos el pixel
                        bmg.setPixel(Coordenadas[ia][0],(Coordenadas[ia][1]+1),
                           _global.ColorPincel);
                        // Añadimos el nuevo pixel a la lista
                        Coordenadas[ia+1]=Array(Coordenadas[ia][0],(Coordenadas[ia][1]+1));
                        ia=ia+1;
                     }
                  }
               }
            }
            // Si sigue habiendo atasco, probamos con el de la derecha
            if(atasco==true)
            {
               if(((Coordenadas[ia][0]+1)>200)&&((Coordenadas[ia][0]+1)<680)&&
                  ((Coordenadas[ia][1])>20)&&(Coordenadas[ia][1]<740))
               {
                  if(_global.BitmapDibujo.getPixel(
                     (Coordenadas[ia][0]+1),Coordenadas[ia][1]).toString(16)<>"000000")
                  {
                     if(bmd.getPixel((Coordenadas[ia][0]+1),Coordenadas[ia][1])<>_global.ColorPincel)
                     {
                        // Se puede pintar. Quitamos el atasco
                        atasco=false;
                        // Dibujamos el pixel
                        bmg.setPixel((Coordenadas[ia][0]+1),Coordenadas[ia][1],
                           _global.ColorPincel);
                        // Añadimos el nuevo pixel a la lista
                        Coordenadas[ia+1]=Array((Coordenadas[ia][0]+1),Coordenadas[ia][1]);
                        ia=ia+1;
                     }
                  }
               }
            }
            // Si hay atasco en todas las direcciones, tenemos que probar con la coordenada
            // anterior
            if(atasco==true)
            {
               ia--;
            }
         }
      }
   }
}


Depurando el código y ejecutando paso por paso he comprobado que funciona. El problema es que la animación se ralentiza una barbaridad, hasta que me sale el dichoso mensaje de que un script está haciendo que vaya muy lento y que si quiero detener el script.

Ésta es la tercera versión, jejejeje. Al principio probé con recursividad, con el mismo procedimiento: pintaba un píxel y sus adyacentes, y los apuntaba en un array, y seguia pintando píxeles de la misma manera siempre que no estuvieran en la lista de los ya pintados. Pero me encuentro con que Actionscript no soporta más de 256 ejecuciones recursivas... vamos, que me cortó el rollo. Cuando pasé esa función de recursiva a iterativa, me encontré con el mismo problema, que se ralentizaba pero pensé que podría ser por buscar tantas veces en el Array coordenadas ya dibujadas, así que al final di con esta solución para sólo tener que moverte hacia delante y hacia atrás en el Array y no tener que recorrerlo cada vez que intentas dibujar un pixel. Pero vamos, las desgracias nunca vienen solas, jejejeje.

Por si a alguien le ha gustado la idea, le comento que por el momento lo he solucionado "mapeando" las zonas que puedes rellenar, de la siguiente forma: Photoshop en mano, he invertido los colores de la imagen, y guardado cada "trozo" que se puede rellenar. En el script cargo todas las imagenes en mc separados. Cuando uso el bote de pintura miro todos estos mc con un BitmapData a ver dónde se encuentra dibujado en negro. Cuando lo encuentro, duplico la capa y utilizo ésta nueva como máscara de otra que relleno del color elegido con setMask(). Lo malo de esta solución es que tienes que preparar la imagen con anterioridad para poder usarla, cuando tiene más gracia que pudiera hacerse con cualquier gif que cargues.

Un saludo, y gracias de antemano por la ayuda.

Anubis