Статьи

Блиттинг с AS3: удаление цвета фона растрового изображения

Сегодня вы узнаете, как удалить цвет фона со спрайт-листа с помощью AS3, и перетащите результат на растровый холст. Читайте дальше, чтобы узнать больше!


Давайте посмотрим на конечный результат, к которому мы будем стремиться:

Блиттинг во Flash: удаление фона

Итак, пришло время нарисовать вашу таблицу. Откройте вашу любимую программу «pixel-art», создайте изображение размером 128×128 и задайте для него цвет фона «# e731f2», который является приятным фиолетовым цветом!

Это моя удивительная работа:

Мой SpriteSheet

Сохраните свое изображение где-нибудь организованно и давайте продолжим


Теперь я называю это спрайт- лист, хотя это всего лишь одно изображение. «Лист спрайтов» обычно состоит из нескольких спрайтов, но мы можем представить, что у нас их больше, верно?

В любом случае, если вы используете Flash CS4 или выше, просто импортируйте изображение через File | Импорт | Импорт в библиотеку :

Файл | Импорт | Импорт в библиотеку ...

Если вы используете любую другую AS3 IDE, я включил SWC-файл, поэтому вам, вероятно, следует пропустить этот шаг. Если вы хотите встроить свои собственные изображения, я уверен, что у вашей IDE будет эта функция.


Теперь у нас есть наш список спрайтов в библиотеке; мы действительно должны сделать это в Class .

Щелкните правой кнопкой мыши изображение в библиотеке и выберите «Свойства». Придайте изображению следующие свойства:

Изображение | Свойства ...

Хит ОК. Если вы получаете предупреждение, просто игнорируйте его; это не имеет значения здесь.


Если вы не знакомы с концепцией класса документа, ознакомьтесь с этим кратким советом, прежде чем читать дальше.

Создайте новый класс ActionScript 3.0 и назовите его «Главный». Когда файл будет создан, сохраните его как «Main.as».

Этот код должен быть помещен в наш новый класс:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
package
{
     
    import flash.display.MovieClip;
     
     
    public class Main extends MovieClip {
         
         
        public function Main()
        {
            // constructor code
        }
         
         
    }
     
     
}

Однако мы еще не закончили! Если вы используете Flash IDE, перейдите на «Панель свойств» и установите для «Класса документа» значение «Основной». Если вам интересно, что это делает, это означает, что когда ваше приложение / игра запускается Flash Player, Main.as будет классом, который связан с самим SWF. Круто, да?

Создание класса документа!

Запустите программу; если вы не получили ошибок, то вам нужно идти!


Перед тем, как мы сделаем блиц, нам нужно будет создать холст, на который можно будет бить. Если вы не знаете термин Blitting или хотите узнать больше о нем, ознакомьтесь с этим руководством .

Теперь мы объявим новую переменную Bitmap, в которую мы будем копировать (копировать) изображение.

1
private var canvas:Bitmap;

После того, как мы это сделаем, мы добавим function Initialize() которая позволит нам все настроить аккуратно:

1
2
3
4
public function Main()
{
    Initialize();
}

Давайте создадим функцию сейчас:

1
2
3
4
5
private function Initialize():void
{
    canvas = new Bitmap( new BitmapData( 550, 400, false, 0x000000 ) );
    stage.addChild( canvas );
}

Однако мы еще не закончили, поскольку нам еще нужно добавить imports :

1
2
3
import flash.display.MovieClip;
import flash.display.Bitmap;
import flash.display.BitmapData;

Запустите программу; если у него черный фон, это сработало!


Во-первых, нам нужно будет создать новую переменную типа SpriteSheet — каким был класс для изображения, которое мы импортировали ранее, помните?

1
2
private var canvas:Bitmap;
private var spriteSheet:SpriteSheet;

Затем мы инициализируем его:

1
2
3
4
5
6
private function Initialize():void
{
    canvas = new Bitmap( new BitmapData( 550, 400, false, 0x000000 ) );
    spriteSheet = new SpriteSheet();
    stage.addChild( canvas );
}

Запустите программу, и вы ничего не увидите; давайте исправим это прямо сейчас!


Теперь нам нужно добавить событие ENTER_FRAME . Это позволит программе обновляться 24 раза в секунду (24 FPS) в нашем случае.

В функцию Main() добавьте следующую строку:

1
2
3
4
5
public function Main()
{
    Initialize();
    stage.addEventListener( Event.ENTER_FRAME, Update );
}

Теперь нам нужно сделать функцию Update() . Добавьте эту функцию после других функций:

1
2
3
4
private function Update(e:Event):void
{
     
}

Не забывайте imports :

1
2
3
4
import flash.display.MovieClip;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.events.Event;

Теперь мы готовы сделать блиц!


Здесь начинается интересная часть!

Хорошо, так что мы хотим сделать это:

  • Очистить холст.
  • Blit изображение и удалить цвет фона.

В функции обновления введите следующий код:

1
2
3
4
5
6
7
8
9
private function Update(e:Event):void
{
 
    canvas.bitmapData.lock();
    canvas.bitmapData.fillRect( new Rectangle( 0,0,stage.width, stage.height ), 0x000000 );
    canvas.bitmapData.copyPixels( spriteSheet, new Rectangle( 0,0,128,128 ), new Point( 100, 100 ) );
    canvas.bitmapData.unlock();
     
}

Если вы запустите это, вы получите свое изображение на холсте! Однако это не только то, к чему мы стремимся, так как мы хотим удалить этот цвет фона с изображения.

Сначала я объясню часть кода выше:

  • canvas.bitmapData.lock(); — Эта линия оптимизирует блиттинг, и это хорошая привычка печатать ее большую часть времени!
  • canvas.bitmapData.fillRect(); — Эта линия очищает холст, заполняя его черным цветом.
  • canvas.bitmapData.copyPixels(); — Не очень полезно в нашей ситуации, но копирует все пиксели из части изображения.
  • canvas.bitmapData.unlock(); — Это работает с lock() для оптимизации процесса.

Теперь вы должны иметь это на экране …

Мой SpriteSheet

Да, я знаю, вы, вероятно, правы. Я думаю, что мы должны избавиться от пурпура тоже …


Наконец пришло время убрать фиолетовый цвет!

Что мы хотим сделать, это проверить каждый пиксель; если пиксель фиолетовый, мы просто не копируем его на холст. Для этого мы сделаем нашу собственную функцию.

Замените Update() на следующее:

01
02
03
04
05
06
07
08
09
10
11
private function Update(e:Event):void
{
     
    canvas.bitmapData.lock();
    canvas.bitmapData.fillRect( new Rectangle( 0,0,stage.width, stage.height ), 0x000000 );
     
    CustomBlitting( spriteSheet, new Rectangle( 0,0,128,128 ), new Point( 100, 100 ), 0xE730F2 );
     
    canvas.bitmapData.unlock();
     
}

Наша новая функция ( CustomBlitting() , которую мы еще не написали) принимает большинство параметров, которые делает copyPixels, вместе с дополнительным: цвет, который мы хотим удалить.

Время написать функцию. Этот код может выглядеть сложным, если вы никогда не делали nested for-loop . Этот цикл работает в основном так:

  • Для каждого ряда у нас есть …
  • Проверьте каждый пиксель в этой строке …
  • Перейти к следующему ряду вниз …
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
private function CustomBlitting( src:BitmapData, srcRect:Rectangle, destPoint:Point, color:uint ):void
{
     
    for( var i:int = 0; i < srcRect.height; i++ )
    {
        for( var j:int = 0; j < srcRect.width; j++ )
        {
 
            var currentPixel:uint = src.getPixel( srcRect.x + j, srcRect.y + i );
             
            if( currentPixel != color )
            {
                canvas.bitmapData.setPixel( destPoint.x + j, destPoint.y + i, currentPixel );
            }
                 
        }
    }
         
}

Позвольте мне объяснить getPixel и setPixel, хотя они, вероятно, должны быть понятны:

  • getPixel( x, y ); — Это возвращает цвет пикселя в X, Y месте.
  • setPixel( x, y, color ); — Это устанавливает цвет пикселя в X, Y месте холста.

Теперь, если вы запустите программу, она работает!

Блиттинг во Flash: удаление фона

У меня есть только одна задача для этого урока:

Примите Массив цветов в качестве параметра и удалите все цвета из изображения, которые находятся в массиве.

Удачи!

Я надеюсь, что вам понравился этот урок и вы узнали что-то новое сегодня. Если вы хотите показать мне свой SWF с выполненными заданиями, оставьте комментарий ниже!