2010-03-21 4 views
3

Одна вещь, которая кажется особенно легкой в ​​работе с Flash IDE, но с которой сложно сделать код, - это набросок органической формы. В среде IDE вы можете просто использовать инструмент inkbucket, чтобы нарисовать штрих вокруг чего-то. Использование ничего, кроме кода, кажется намного сложнее. Один из методов, который я видел, заключается в том, чтобы добавить фильтр свечения к рассматриваемой форме и просто испортить силу. Но что, если я хочу только показать схему?Рисование очертаний вокруг органических фигур

Что бы я хотел сделать, это собрать все точки, составляющие край формы, а затем просто соединить точки. На самом деле я дошел до того, что собрал все точки с быстрым и грязным сценарием обнаружения границ, который я написал. Итак, теперь у меня есть вектор всех точек, которые составляют мою форму. Как подключить их в правильной последовательности, чтобы она действительно выглядела как исходный объект?

Для тех, кто заинтересован здесь мой край сценарий обнаружения:

  // Create a new sprite which we'll use for our outline 
     var sp:Sprite = new Sprite(); 
     var radius:int = 50; 
     sp.graphics.beginFill(0x00FF00, 1); 
     sp.graphics.drawCircle(0, 0, radius); 
     sp.graphics.endFill(); 
     sp.x = stage.stageWidth/2; 
     sp.y = stage.stageHeight/2; 

     // Create a bitmap data object to draw our vector data 
     var bmd:BitmapData = new BitmapData(sp.width, sp.height, true, 0); 

     // Use a transform matrix to translate the drawn clip so that none of its 
     // pixels reside in negative space. The draw method will only draw starting 
     // at 0,0 
     var mat:Matrix = new Matrix(1, 0, 0, 1, radius, radius); 
     bmd.draw(sp, mat); 

     // Pass the bitmap data to an actual bitmap 
     var bmp:Bitmap = new Bitmap(bmd); 

     // Add the bitmap to the stage 
     addChild(bmp); 

     // Grab all of the pixel data from the bitmap data object 
     var pixels:Vector.<uint> = bmd.getVector(bmd.rect); 

     // Setup a vector to hold our stroke points 
     var points:Vector.<Point> = new Vector.<Point>; 

     // Loop through all of the pixels of the bitmap data object and 
     // create a point instance for each pixel location that isn't 
     // transparent. 
     var l:int = pixels.length; 
     for(var i:int = 0; i < l; ++i) 
     { 
      // Check to see if the pixel is transparent 
      if(pixels[i] != 0) 
      { 
       var pt:Point; 

       // Check to see if the pixel is on the first or last 
       // row. We'll grab everything from these rows to close the outline 
       if(i <= bmp.width || i >= (bmp.width * bmp.height) - bmp.width) 
       { 
        pt = new Point(); 
        pt.x = int(i % bmp.width); 
        pt.y = int(i/bmp.width); 
        points.push(pt); 
        continue; 
       } 

       // Check to see if the current pixel is on either extreme edge 
       if(int(i % bmp.width) == 0 || int(i % bmp.width) == bmp.width - 1) 
       { 
        pt = new Point(); 
        pt.x = int(i % bmp.width); 
        pt.y = int(i/bmp.width); 
        points.push(pt); 
        continue; 
       } 

       // Check to see if the previous or next pixel are transparent, 
       // if so save the current one. 
       if(i > 0 && i < bmp.width * bmp.height) 
       { 
        if(pixels[i - 1] == 0 || pixels[i + 1] == 0) 
        { 
         pt = new Point(); 
         pt.x = int(i % bmp.width); 
         pt.y = int(i/bmp.width); 
         points.push(pt); 
        } 
       } 
      } 
     } 

ответ

2

В настоящее время это не представляется возможным вникать форму то, что вы нарисовали во время разработки (то есть, чтобы выяснить, где углы всех линии и заливки), поэтому единственный хороший способ нарисовать контур вокруг произвольной формы - это как растровый эффект. Однако то, как вы собираетесь это делать, вероятно, не будет плодотворным. Flash дает вам несколько способов обработки растровых изображений, но все, что связано с циклизацией по каждому пикселю, обычно не заканчивается достаточно быстро, чтобы использовать его во время выполнения.

Скорее, я бы взял один из двух подходов: лучшим и легким будет использование встроенных фильтров. Как вы говорите, обычно, когда люди хотят нарисовать контур, они используют фильтр свечения с большой силой и коротким радиусом. Если вы хотите показать только контур, проверьте свойство knockout. (Вы можете сделать это в скрипте или в среде IDE.) Если вам не нравится, что вы получаете с этим, вы можете попробовать смешивать фильтры - скажем, добавляя размытие до или после свечения. Или вы можете использовать код для генерации эффекта свечения в пустую растровую карту, а затем вы можете обрабатывать результат различными способами - например, с BitmapData.threshold, который я нашел очень мощным. Во всяком случае, я бы поиграл с этим некоторое время и убедился, что это действительно не решит вашу проблему, прежде чем вы попробуете что-то еще, потому что это, безусловно, самое простое решение.

Другой вариант - PixelBender. Это функция, которая позволяет вам определять настраиваемый фильтр на языке C, который вы предварительно компилируете, а затем загружаете в свой Flash-фильм и применяете к рассматриваемому растровому изображению. Этот процесс очень похож на программирование фильтра фотошоп. Это дает вам полный контроль над тем, какую обработку вы хотите сделать для растрового изображения, но для этого требуется, чтобы вы работали вне Flash и наружного ActionScript.

Выполнение текущего маршрута и обработка вручную пикселей - это, конечно, третий вариант, но возникает вопрос, действительно ли вы делаете что-либо, что вы не могли бы сделать в обычном или настраиваемом фильтре. Если вы действительно хотите закончить то, что у вас есть, вы можете попробовать создать новый прозрачный растровый рисунок, и для каждой точки, которую вы захватили в приведенном выше коде, нарисуйте белую точку (с помощью setPixel32) в этой точке. Это даст вам пиксельный контур, который вы, вероятно, затем захотите размыть или обработать иным способом. Но на самом деле, вы соберете что-то очень похожее на то, что вы могли бы получить с помощью обычного фильтра свечения, и это займет много времени.

+0

Я тестирую код, который я использую, чтобы получить края, и, если я не сделаю что-то неправильно, похоже, это довольно быстро. Согласно тест-жгуту Гранта Скиннера он работает в 9,63 мс или 9631 мс за 1000 итераций. Буду признателен, если кто-нибудь успеет дважды проверить это. Код, который я использую, находится здесь: http://pastebin.com/s59FPGvB –

+0

Создание эффекта в пустой растровой картинке, вероятно, ближе всего к тому, что мне нужно. Вы бы просто применили объект преобразования от исходного растрового изображения к пустому? это даже работает? –

Смежные вопросы