Статьи

Создайте свой собственный эффект взрыва пикселя ActionScript 3.0

В этом уроке вы узнаете, как создать эффект, который наверняка попался вам на глаза (например, в файлах, подобных этому ), Pixel Explosion. В процессе его создания мы узнаем, как извлечь BitmapData из MovieClip, как использовать механизм анимации движения и как использовать прослушиватели событий.

Тогда начнем!




Первое, что мы сделаем, это создадим флеш-файл AS3. Затем мы настроим нашу сцену на 400px x 400px и 30 кадров в секунду. Мы будем писать на временной шкале, чтобы упростить задачу, но те, кто знает, как программировать на ООП, могут писать этот код в классах. Вам понадобятся базовые знания AS3, чтобы понять все процессы, включенные в это руководство; однако я постараюсь сделать это очень просто. Кнопки с синими крыльями — это те, которые вам придется нажимать в вашей IDE. Поначалу это может показаться трудоемким, но на самом деле все очень просто.

Теперь нарисуем векторное изображение того, что нам нужно. Вы можете действительно настроить любое изображение с этим эффектом (.jpg, .png), но векторы круче. Как вы заметите, я не большой дизайнер. Все, что вам нужно сделать, это нарисовать ваше изображение (или импортировать JPG с вашего компьютера), выбрать его и преобразовать в MovieClip (нажмите F8 в Windows).

После того, как вы преобразовали свое изображение в мувиклип, вы можете подготовить его к коду, который на него нацелится. Мы создадим новый слой для действий (1.), а затем дадим ему имя экземпляра mcLogo (2.). Затем мы импортируем классы для использования в нашем слое действий. Для этого эффекта нам понадобится хороший анимационный движок. Лучший из найденных мной, который поддерживает скорость и стабильность, это TweenMax. Вы можете скачать его с http://blog.greensock.com/tweenmaxas3/ (пожертвуйте, если вам это нравится). Не забудьте скопировать каталог классов в тот же каталог, что и ваш .fla (как вы можете видеть в синем поле). Наконец, импортируйте класс TweenMax в вашу временную шкалу (3.).

Теперь мы настроим сцену и наши основные переменные. Мы выровняем сцену по углу TOP_LEFT и настроим ее так, чтобы она не масштабировалась. Со стороны переменных, мы создадим контейнер для хранения всех пикселей, которые будут взорваться. Мы также создадим GlowFilter, это, конечно, не обязательно, но это увеличит потрясающий эффект. «Анимация» — это переключатель, который становится истинным, когда эффект имеет место, а «pixelBMP» — это растровые данные вашего изображения.

1
2
3
4
5
6
7
stage.align = StageAlign.TOP_LEFT;
  stage.scaleMode = StageScaleMode.NO_SCALE;
   
  var pixelContainer:MovieClip = new MovieClip();
  var glow:GlowFilter = new GlowFilter(0xFFFF00, 1, 10, 10,5,2);
  var animating:Boolean=false;
  var pixelBMP:BitmapData;

Далее мы создадим переменные повторения и назначим положение контейнера для пикселей таким же, как у вашего изображения.

1
2
var i:int = 0;
var j:int = 0;

Теперь мы извлечем данные растрового изображения (цвета пикселей) из изображения, которое вы настроили (1.). Запомните эти две строки, они помогут вам и в других проектах. Мы создадим новый символ из библиотеки (2.) и нажмем кнопку «Дополнительно». После нажатия выберите «Экспорт для ActionScript» (3.). Найдите текстовое поле Class и введите «myPixel».

Теперь мы настроим пиксельный контейнер. Мы введем наш недавно созданный пиксельный эффект и создадим слой с именем «action».

На слое действий мы настроим растровое изображение. Этот небольшой фрагмент кода поможет вам каждый раз, когда вы захотите манипулировать данными bitmapData объекта (например, с другими полезными эффектами, такими как десатурация и размытие).

1
2
pixelBMP=new BitmapData(mcLogo.width,mcLogo.height,true,0x000000)
pixelBMP.draw(mcLogo)

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
var orgX:int=0;
var orgY:int=0;
var bmpImg:Bitmap;
function setUpPixel(bdData:BitmapData,glow:GlowFilter)
{
    var mc:MovieClip = new MovieClip();
    mc.graphics.beginFill(bdData.getPixel(0,0));
    mc.graphics.drawCircle(0,0,2)
    mc.graphics.endFill();
    mc.filters=[glow];
     
 
    addChild(mc);
     
}

Мы создадим два оператора for для всех пикселей нашего изображения. Первое для (i) для вертикальной, а второе (j) для горизонтальной. Метод getPixel возвращает единицу, представляющую цвет пикселя в этой позиции. Если оно не равно нулю, начнутся операции, представленные на шаге 9. Мы пересечем пиксели два на два из-за управления памятью.

1
2
for(i = 0; i < mcLogo.height; i+=2)
for(j = 0; j < mcLogo.width; j+=2)

Мы начнем с назначения цвета пикселя фильтру свечения. Затем мы создадим новый myPixel, который назовем «pixel_mc». Мы назовем функцию «setUpPixel», которую мы определили на шаге 7. Это передает bitmapData — 2 пикселя в ширину, 2 пикселя в высоту, цвет текущего пикселя, originalX, originalY и фильтр свечения. Наконец, мы добавляем этот пиксель в контейнер пикселей (строка 12)

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
for(i = 0; i < mcLogo.height; i+=2)
    for(j = 0; j < mcLogo.width; j+=2) {
    if(pixelBMP.getPixel(j, i)>0)
    {
        glow.color = pixelBMP.getPixel(j, i);
        var pixel_mc:myPixel = new myPixel()
        pixel_mc.setUpPixel(new BitmapData(2, 2, false, pixelBMP.getPixel(j, i)), glow)
        pixel_mc.y = i;
        pixel_mc.x = j;
         
 
        pixelContainer.addChild(pixel_mc);
        pixelContainer.visible=false;
         
    }
}

Маленькие ошибки очень распространены в программировании, поэтому нам нужно время от времени проверять наш мувиклип. Это дает нам наше изображение, но и немного размытости. Размытость из-за светящегося фильтра, поэтому не стоит беспокоиться. Как вы, возможно, уже знаете, нам не нужны эти пиксели, чтобы быть видимыми, кроме случаев, когда к ним применяется наш эффект. До этого у нас есть хороший образ. Поэтому все, что вам нужно сделать на этом шаге — это раскомментировать строку 13 — pixelContainer.visible = false; и вы получите свое первоначальное изображение обратно.

У нас есть пиксели на месте, теперь все, что нам нужно сделать, это анимировать их. Это где TweenMax выходит на сцену. Мы запускаем функцию, делая исходное изображение невидимым, а пиксели видимыми. Далее мы установим исходное изображение и кнопку, которую мы создадим позже (для включения функции), в самом верхнем указателе. Запомните эту функцию — setChildIndex (yourmc, numChildren-1), она поможет вам в других проектах.

1
2
3
4
5
6
7
function explode() {
    pixelContainer.alpha=1;
    mcLogo.visible = false;
    setChildIndex(mcLogo, numChildren — 1)
    setChildIndex(btn_mc,numChildren-1)
    pixelContainer.visible = true;
}

Здесь пиксели оживают. «For» пересекает каждого дочернего элемента pixelContainer. Пиксель извлекается с помощью метода getChildAt (i) . Xdest и ydest — это случайные места назначения, куда будут летать наши пиксели (поскольку Math.random () возвращает число от 0 до 1, необходимо умножить его). Наконец, мы добавляем переход и тип легкости через TweenMax.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
function explode() {
    pixelContainer.alpha=1;
    mcLogo.visible = false;
    setChildIndex(mcLogo, numChildren — 1)
    setChildIndex(btn_mc,numChildren-1)
    pixelContainer.visible = true;
 
    for(var i:int = 0; i<pixelContainer.numChildren; i++) {
    var pixel_mc:myPixel = myPixel(pixelContainer.getChildAt(i));
    pixel_mc.visible = true;
    var xdest:int = Math.random()*(stage.stageWidth+300)-300;
    var ydest:int = Math.random()*(stage.stageHeight+300)-300;
    TweenMax.to(pixel_mc,14,{x:xdest,y:ydest,ease:Circ.easeOut});
 
}
}

Конечно, для взрыва нам нужно где-то хранить наши начальные значения. Мы создадим (1.) 2 массива — xArray и yArray, которые хранят эти значения. После этого (2.) мы вставим в for (j = 0; j <mcLogo.width; j + = 2) код для отправки значений в следующий индекс.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
var xArray:Array = new Array();
var yArray:Array = new Array();
 
for(i = 0; i0)
    {
        glow.color = pixelBMP.getPixel(j, i);
        var pixel_mc:myPixel = new myPixel()
        pixel_mc.setUpPixel(new BitmapData(2, 2, false, pixelBMP.getPixel(j, i)), glow)
        pixel_mc.y = i;
        pixel_mc.x = j;
        xArray.push(j);
        yArray.push(i);
 
        pixelContainer.addChild(pixel_mc);
        pixelContainer.visible=false;
         
    }
}

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

Давайте создадим нашу кнопку. Начните с рисования (1.). Создание мувиклипа (как вы узнали на шаге 2. Создание нового слоя действий и ввод stop (); (2.). Это предотвращает зацикливание нашего mc. Теперь мы вставим ключевой кадр, когда кнопка была нажата ( 3.). Это изменит текст и покажет, что теперь, когда вы щелкнете по нему, произойдет обратный процесс.

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

Свойство buttonMode устанавливает обычный курсор для изменения в действии.

Свойство mouseChildren при значении false запрещает дочерним элементам украсть mouseEvents.

Метод addEventListener позволяет кнопке запускать функцию clickHandler при нажатии (MouseEvent.CLICK).

1
2
3
4
5
6
7
function initbutton()
{
    btn_mc.buttonMode=true;
    btn_mc.mouseChildren=false;
    btn_mc.addEventListener(MouseEvent.CLICK, clickHandler);
}
initbutton();

Теперь мы настроим функцию, которая устанавливает взрыв. «анимация» — это значение, которое указывает, должны ли пиксели взорваться или взорваться.

01
02
03
04
05
06
07
08
09
10
11
12
function clickHandler(e:MouseEvent) {
            if (animating==false) {
                explode();
                animating = true;
                btn_mc.gotoAndStop(2);
            }
            else {
                 
                implode()
                btn_mc.gotoAndStop(1);
            }
}

Добавление фильтров, изменение значений фильтров и изменение типов смягчения переходов — отличные вещи для игры. Для изменения типов замедления вам необходимо импортировать классы замедления. Вы можете просмотреть типы анимации здесь .

1
import gs.easing.*;

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

1
2
3
4
5
6
7
onComplete:smoothit
 
function smoothit()
    {
        mcLogo.visible=true;
        TweenMax.to(pixelContainer,1,{alpha:0,onComplete:function(){pixelContainer.visible=false; mcLogo.visible=true; animating = false;}}
    }

Итак, что мы покрыли сегодня?

  1. Импортируем наши основные классы.
  2. Выравнивание сцены.
  3. Объявление основных переменных.
  4. Добавление пиксельного контейнера на сцене.
  5. Извлечение растровых данных из нашего изображения.
  6. Создание класса MyPixel и отправка цвета каждого из пикселей изображения в эти пиксели.
  7. Создание функции, которая выбирает все пиксели, а затем настраивает их на случайную позицию.
  8. Создание функции, которая перемещает пиксели обратно в исходное положение.
  9. Создание кнопки, которая вызывает эти функции.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import gs.TweenMax;
import gs.easing.*;
 
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
 
var pixelContainer:MovieClip = new MovieClip();
var glow:GlowFilter = new GlowFilter(0xFFFF00, 1, 10, 10,5,2);
var animating:Boolean=false;
var pixelBMP:BitmapData;
 
var i:int = 0;
var j:int = 0;
 
var xArray:Array = new Array();
var yArray:Array = new Array();
 
 
addChild(pixelContainer)
pixelContainer.x=mcLogo.x;
pixelContainer.y=mcLogo.y;
 
pixelBMP=new BitmapData(mcLogo.width,mcLogo.height,true,0x000000)
pixelBMP.draw(mcLogo)
 
for(i = 0; i<mcLogo.height; i+=2)
    for(j = 0; j<mcLogo.width; j+=2) {
    if(pixelBMP.getPixel(j, i)>0)
    {
        glow.color = pixelBMP.getPixel(j, i);
        var pixel_mc:myPixel = new myPixel()
        pixel_mc.setUpPixel(new BitmapData(2, 2, false, pixelBMP.getPixel(j, i)), glow)
        pixel_mc.y = i;
        pixel_mc.x = j;
        xArray.push(j);
        yArray.push(i);
 
        pixelContainer.addChild(pixel_mc);
        pixelContainer.visible=false;
         
    }
    }
function initbutton()
{
    btn_mc.buttonMode=true;
    btn_mc.mouseChildren=false;
    btn_mc.addEventListener(MouseEvent.CLICK, clickHandler);
    function clickHandler(e:MouseEvent) {
            if (animating==false) {
                explode();
                animating = true;
                btn_mc.gotoAndStop(2);
            }
            else {
                 
                implode()
                btn_mc.gotoAndStop(1);
            }
            }
}
initbutton();
 
 
function explode() {
    pixelContainer.alpha=1;
            mcLogo.visible = false;
            setChildIndex(mcLogo, numChildren — 1)
            setChildIndex(btn_mc,numChildren-1)
            pixelContainer.visible = true;
             
            for(var i:int = 0; i<pixelContainer.numChildren; i++) {
                var pixel_mc:myPixel = myPixel(pixelContainer.getChildAt(i));
                pixel_mc.visible = true;
                var xdest:int = Math.random()*(stage.stageWidth+300)-300;
                var ydest:int = Math.random()*(stage.stageHeight+300)-300;
                 
             
                TweenMax.to(pixel_mc,14,{x:xdest,y:ydest,ease:Circ.easeOut});
                 
            }
}
 
function implode()
{
    for(var i:int = 0; i<pixelContainer.numChildren; i++) {
    var pixel_mc:myPixel = myPixel(pixelContainer.getChildAt(i));
    pixelContainer.visible=true;
    TweenMax.to(pixel_mc,3,{y:yArray[i],x:xArray[i],ease:Strong.easeIn,onComplete:smoothit});
    }
}
function smoothit()
{
    mcLogo.visible=true;
    TweenMax.to(pixelContainer,1,{alpha:0,onComplete:function(){pixelContainer.visible=false; mcLogo.visible=true; animating = false;}})
}

Я надеюсь, вам понравился этот урок. Спасибо за прочтение!