Добро пожаловать в это введение в работу на уровне пикселей с объектом ActionScript 3 BitmapData. Мы возьмем несколько 2D-изображений, разбим их на составляющие их пиксели, а затем соберем их в виде 3D-изображений, которые мы можем перемещать и вращать.
Окончательный результат предварительного просмотра
Давайте посмотрим на конечный результат, к которому мы будем стремиться:
Шаг 1: настроить
Перед тем, как начать, давайте на минутку посмотрим, как устроен пример проекта. Открыв исходный zip-файл для этого урока, у вас будут источники для каждого значимого шага, вы можете пойти дальше и сделать копию начальной папки, так как это послужит нашей отправной точкой.
Внутри этой папки вы найдете две другие папки; SRC и бен . В папке src мы будем сохранять весь наш код и FLA-файлы, а в папке bin — Flash, где будут сохраняться SWF-файлы. Внутри папки src находятся классы Main.FLA и Main.AS.
Если по какой-либо причине вы обнаружите ошибку в своем коде, попытайтесь ее исправить (всегда полезно учиться на ошибках), но если вы не можете, то не беспокойтесь! Вы можете сразу перейти обратно и использовать одну из папок шагов в исходном zip-файле, ближайшую к тому шагу, на котором вы были.
Шаг 2: Загрузите Away3D
Если вы уже Main.as файл Main.as вы уже заметили несколько ссылок на Away3D, 3D-фреймворк для Flash. Нам нужно скачать это и добавить его в наш проект, чтобы продолжить.
Вы можете получить их последнюю версию с сайта Away3D .
После завершения загрузки откройте zip-файл, и внутри папки away3d_3_6_0 \ src вы найдете три папки away3d , nochump и wumedia . Скопируйте их, как показано ниже, в папку src .

Шаг 3: Флэш-файл
Если вы еще этого не сделали, откройте Main.fla и Main.as Глядя в библиотеку Flash, вы можете увидеть изображение с именем img1 и MovieClip с именем экземпляра img1 , которое будет служить основным контейнером для png.
Мы собираемся выполнить быструю компиляцию, чтобы убедиться, что мы правильно добавили Away3D. Если все идет хорошо, мы должны увидеть пустой Flash-фильм с темно-серым фоном и без сообщений об ошибках от Flash.
Шаг 4: Файл Main.as
Main.as файл Main.as мы увидим несколько переменных, которые используются в Away3D, на Away3D уже есть множество учебных пособий, но мы быстро повторим их:
|
1
2
3
4
|
// basic Away3D properties
protected var scene:Scene3D;
protected var camera:TargetCamera3D;
protected var view:View3D;
|
-
Scene3D— это пространство, которое мы можем использовать для добавления трехмерных объектов, таких как кубы и сферы. -
TargetCamera3D— это один из многих типов камер, доступных в Away3D, и именно его мы используем, чтобы взглянуть на Scene3D. -
View3D— это окно просмотра, часто описываемое как «окно», в котором мы видим нашу сцену.
Не вдаваясь в подробности, вы также можете увидеть, что базовая сцена настроена для использования с initAway3d() . Обратите внимание, что он добавляет ENTER_FRAME EventListener , это просто говорит Away3D render() (или рисовать) любые объекты, добавленные в Scene3D каждый кадр.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
/**
* Away3D basic scene setup
*/
private function initAway3d():void
{
scene = new Scene3D();
camera = new TargetCamera3D({z: -200});
view = new View3D({scene:scene, camera:camera});
addChild(view);
addEventListener(Event.ENTER_FRAME, renderLoop);
}
/**
* the render loop
*/
private function renderLoop(event:Event):void
{
view.render();
}
|
Вот и все для ознакомления с классом Main.as , мы будем строить все остальное по ходу дела.
Шаг 5: Растровые изображения и BitmapData
Мы собираемся сразу перейти к этим двум классам, так как будем работать с ними на протяжении всего урока. Если вы новичок в Bitmap и BitmapData вы можете думать о них как о холсте художников и наборе мазков краски. Это совершенно разные объекты, но оба они связаны, BitmapData содержит всю информацию о пикселях или мазках кисти и ничего бы не нарисовало на холсте или в этом случае, Bitmap!
Давайте проверим это, добавив экземпляр img1 MovieClip на stage и сделав его копию, используя Bitmap/BitmapData .
Изменить Main.as к следующему:
|
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
|
/**
* constructor
*/
public function Main()
{
initAway3d();
drawExample();
}
/**
* a quick example of BitmapData and Bitmap usage
*/
private function drawExample():void
{
// create an instance of the img1 object on the stage to copy
var img:MovieClip = new img1();
addChild(img);
// create a BitmapData object with the following parameters: width, height, transparent, color
var bmpData:BitmapData = new BitmapData(img.width, img.height, true, 0x000000);
// draws a copy of the img MovieClip in to the BitmapData
bmpData.draw(img);
// adds a Bitmap to the stage with the BitmapData (copy of the img1) information to display
var bmp:Bitmap = new Bitmap(bmpData);
bmp.y = img.height;
addChild(bmp);
}
|
Глядя на код drawExample() , первые две строки просто добавляют объект img1 на stage , это изображение, которое мы сделаем из копии.
После этого мы создаем объект BitmapData со следующими параметрами:
-
width, ширина, чтобы сделатьBitmapData -
height, высота, чтобы сделатьBitmapData -
transparent, должен лиBitmapDataсодержать прозрачные пиксели -
color, цвет фона
Поскольку мы знаем ширину и высоту из img1 мы установили их напрямую, так как нам понадобится прозрачность, мы устанавливаем следующий параметр в значение true и, наконец, мы указываем 0x000000 или черный в качестве цвета фона, так как он будет выглядеть прозрачным, пока мы не заполним Это.
Шаг 6: растровые изображения и BitmapData продолжение
Продолжая, теперь у нас есть настроенный объект BitmapData , у нас есть несколько доступных нам опций, мы могли бы, например, перебирать пиксель за пикселем и копировать изображение (мы будем использовать что-то подобное позже в уроке), или мы могли бы используйте метод draw() .
Метод draw() принимает MovieClip или Sprite в качестве параметра и копирует всю информацию о пикселях из объекта в BitmapData .
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
/**
* a quick example of BitmapData and Bitmap usage
*/
private function drawExample():void
{
// create an instance of the img1 object on the stage to copy
var img:MovieClip = new img1();
addChild(img);
// create a BitmapData object with the following parameters: width, height, transparent, color
var bmpData:BitmapData = new BitmapData(img.width, img.height, true, 0x000000);
// draws a copy of the img MovieClip in to the BitmapData
bmpData.draw(img);
// adds a Bitmap to the stage with the BitmapData (copy of the img1) information to display
var bmp:Bitmap = new Bitmap(bmpData);
bmp.y = img.height;
addChild(bmp);
}
|
После этого следующие несколько строк создают объект Bitmap с информацией о пикселях BitmapData в качестве параметра, который затем перемещается ниже исходного img MovieClip и добавляется на stage .
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
/**
* a quick example of BitmapData and Bitmap usage
*/
private function drawExample():void
{
// create an instance of the img1 object on the stage to copy
var img:MovieClip = new img1();
addChild(img);
// create a BitmapData object with the following parameters: width, height, transparent, color
var bmpData:BitmapData = new BitmapData(img.width, img.height, true, 0x000000);
// draws a copy of the img MovieClip in to the BitmapData
bmpData.draw(img);
// adds a Bitmap to the stage with the BitmapData (copy of the img1) information to display
var bmp:Bitmap = new Bitmap(bmpData);
bmp.y = img.height;
addChild(bmp);
}
|
При настройке аспекта Bitmap не требуется много настроек, просто отображается BitmapData, все волшебство заключается в BitmapData . Теперь при тестировании мы должны получить следующее:

Шаг 7: Чтение информации о пикселях
Теперь у нас есть содержимое внутри объекта BitmapData вещи начинают становиться интересными, поскольку мы можем начать манипулировать изображениями с помощью getPixel32() и setPixel32() .
Начиная с getPixel32() drawExample() код drawExample() сверху на следующее:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
/**
* a quick example of BitmapData and Bitmap usage
*/
private function drawExample():void
{
// create an instance of the img1 object on the stage to copy
var img:MovieClip = new img1();
addChild(img);
// create a BitmapData object with the following parameters: width, height, transparent, color
var bmpData:BitmapData = new BitmapData(img.width, img.height, true, 0x000000);
// draws a copy of the img MovieClip in to the BitmapData
bmpData.draw(img);
// adds a Bitmap to the stage with the BitmapData (copy of the img1) information to display
var bmp:Bitmap = new Bitmap(bmpData);
bmp.y = img.height;
addChild(bmp);
// read pixel information from the BitmapData
var pixelInformation:uint = bmpData.getPixel32(5, 0);
trace(pixelInformation, pixelInformation.toString(16));
}
|
Изучив код, мы создали обычную переменную uint и присвоили ей значение пикселя в bmpData по 5 пикселей по горизонтали и 0 пикселей по вертикали. Помните, что значения начинаются с 0 так:

Зная, что мы решили получить информацию о пикселях для 5,0, это сделало бы его черным пикселем в верхней строке и достаточно уверенным выходным 4278190080 ff000000 Flash: 4278190080 ff000000
setPixel32 это может показаться неправильным, но setPixel32 считывает альфа-значение пикселя (тогда как setPixel просто читает цвет). Обычно мы работаем с шестнадцатеричными значениями для цветов, таких как FFFFFF или 000000 поэтому мы можем сказать Flash toString(16) чтобы получить шестнадцатеричное значение:

Шаг 8: Рисование пикселей
Теперь мы знаем, как считывать информацию о пикселях, рисование пикселей в BitmapData очень похоже, только на этот раз мы используем setPixel32() для рисования пикселей в BitmapData, и мы также добавим цикл for для рисования некоторых пикселей.
Сначала измените код на следующее:
|
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
|
/**
* a quick example of BitmapData and Bitmap usage
*/
private function drawExample():void
{
// create an instance of the img1 object on the stage to copy
var img:MovieClip = new img1();
addChild(img);
// create a BitmapData object with the following parameters: width, height, transparent, color
var bmpData:BitmapData = new BitmapData(img.width, img.height, true, 0x000000);
// draws a copy of the img MovieClip in to the BitmapData
bmpData.draw(img);
// adds a Bitmap to the stage with the BitmapData (copy of the img1) information to display
var bmp:Bitmap = new Bitmap(bmpData);
bmp.y = img.height;
addChild(bmp);
// read pixel information from the BitmapData
var pixelInformation:uint = bmpData.getPixel32(5, 0);
trace(pixelInformation, pixelInformation.toString(16));
// write pixel information to the BitmapData
var color:uint = 0xffff0000;
var row:uint = 0;
var column:uint = 0;
for(row; row < bmpData.height; row++)
{
bmpData.setPixel32(column, row, color);
column++;
if(column > bmpData.width)
{
column = 0;
}
}
}
|
Новый код начинается с создания обычной переменной uint именем color которой мы храним 0xffff0000 : ff полностью прозрачный, ff полностью красный, 00 нет зеленого, 00 нет синего.
Затем создаются два счетчика для строк и столбцов (строки — это линия горизонтальных пикселей, столбцы — это линия вертикальных пикселей). Затем эти счетчики помещаются в цикл for который каждый раз увеличивает значение строки и счетчика, поэтому при смешивании с setPixel32() он будет рисовать диагональную линию:

Шаг 9: Класс PixelObject3D
На этом шаге мы собираемся представить класс PixelObject3D.as . Чтобы сэкономить немного времени, возьмите копию класса из папки Step 8 в исходном zip- Main.fla и Main.as ее в папку src кроме Main.fla и Main.as
Как только вы это сделаете, давайте взглянем на это, прежде чем мы начнем добавлять код для создания 3D-объектов из пикселей.
|
1
2
3
4
5
|
// properties
protected var _bitmapData:BitmapData = null;
public var _scaleFactor:Number = 1;
protected var _width:Number = 0;
protected var _height:Number = 0;
|
У нас есть несколько защищенных переменных в верхней части класса, одна для BitmapData и три Numbers для ширины, высоты и масштаба объекта.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
|
/**
* constructor
*/
public function PixelObject3D() {}
/**
* begins the creation process
*/
public function createFromMovieClip(mc:MovieClip):void
{
}
|
За ними следует пустой конструктор класса и метод, с которым мы будем работать, createFromMovieClip() . Вы заметите, что этот метод принимает параметр типа MovieClip , так что вы уже можете догадаться, что мы передадим ему MovieClip и он вернет нам его трехмерное представление. Когда это закончено, то есть!
Шаг 10: экземпляр класса PixelObject3D
Хотя класс PixelObject3D.as самом деле ничего не делает, давайте добавим его экземпляр в класс Main.as чтобы мы могли видеть изменения на экране по ходу.
Начиная с добавления приватной переменной:
|
1
2
3
4
5
6
7
|
// basic Away3D properties
protected var scene:Scene3D;
protected var camera:TargetCamera3D;
protected var view:View3D;
// the Pixel3DObject
protected var po3d:PixelObject3D;
|
После этого добавьте в конструктор вызов createPixelObect3D() .
|
1
2
3
4
5
6
7
8
9
|
/**
* constructor
*/
public function Main()
{
initAway3d();
drawExample();
createPixelObect3D();
}
|
Наконец добавьте следующую функцию в файл Main.as Это создаст экземпляр класса PixelObject3D , вызовет метод createFromMovieClip() и передаст ему новый MovieClip , img1 мы использовали ранее.
Последняя строка, на которую следует обратить внимание: мы добавляем класс PixelObject3D качестве дочернего элемента сцены, поскольку это 3D-объект, а не Stage .
|
01
02
03
04
05
06
07
08
09
10
|
/**
* creates a PixelObject3D
*/
private function createPixelObect3D():void
{
po3d = new PixelObject3D();
po3d.createFromMovieClip(new img1());
scene.addChild(po3d);
}
|
Шаг 11: создать от MovieClip (mc: MovieClip)
Зная, что нам передали MovieClip мы хотим воссоздать с помощью этого метода, первое, что стоит в нашей повестке дня, — это сделать его копию с использованием BitmapData точно так же, как мы делали раньше. Затем мы можем использовать данные пикселей, чтобы начать создавать трехмерные объекты.
Как и прежде, мы собираемся создать объект BitmapData и нарисовать объект mc MovieClip :
|
01
02
03
04
05
06
07
08
09
10
11
12
13
|
/**
* begins the creation process
*/
public function createFromMovieClip(mc:MovieClip):void
{
// store references and create the bitmapdata
_bitmapData = new BitmapData(mc.width, mc.height, true, 0x000000);
_bitmapData.draw(mc);
// set width / height
_width = mc.width * (2 * _scaleFactor);
_height = mc.height * (2 * _scaleFactor);
}
|
Мы также устанавливаем переменные _width и _height соответствии с шириной и высотой mc и умножаем это на переменную _scaleFactor , что позволяет нам увеличивать или уменьшать размер трехмерных пикселей, если мы хотим. Подробнее об этом позже.
Шаг 12: создать от MovieClip (mc: MovieClip)
Помните, что BitmapData — это только информация о пикселях, и без добавления BitmapData в растровое изображение мы не сможем его увидеть, но мы все равно можем читать и записывать его. Это идеально для нас, так как мы собираемся использовать этот шаг, чтобы начать цикл по пикселям BitmapData и разделить значения красного, зеленого, синего и альфа.
createFromMovieClip() ваш createFromMovieClip() чтобы он соответствовал этому:
|
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
|
/**
* begins the creation process
*/
public function createFromMovieClip(mc:MovieClip):void
{
// store references and create the bitmapdata
_bitmapData = new BitmapData(mc.width, mc.height, true, 0x000000);
_bitmapData.draw(mc);
// set width / height
_width = mc.width * (2 * _scaleFactor);
_height = mc.height * (2 * _scaleFactor);
// pixel information
var pixelValue:uint = 0;
var red:uint = 0;
var green:uint = 0;
var blue:uint = 0;
var alpha:uint = 0;
// loop through each pixel horizontally
for (var i:int = 0; i < mc.width; i++)
{
pixelValue = _bitmapData.getPixel32(i, 0);
alpha = pixelValue >> 24 & 0xFF;
red = pixelValue >> 16 & 0xFF;
green = pixelValue >> 8 & 0xFF;
blue = pixelValue & 0xFF;
trace(«alpha:» + alpha + » red:» + red + » green:» + green + » blue:» + blue);
}
}
|
Здесь мы установили несколько переменных для значений цвета и альфа, затем запустили цикл for на основе ширины mc's .
Этот цикл for устанавливает переменную pixelValue в значение текущего пикселя, используя метод getPixel32() который мы использовали ранее, но на этот раз заметим, что мы использовали 0 для второго параметра, который является y , поэтому мы собираемся обрабатывать только первая горизонтальная линия пикселей.
После этого есть некоторая довольно сложная математика, известная как битовая маскировка и сдвиг, чтобы сэкономить немного времени, вы можете предположить, что каждый из цветов извлекается из переменной pixelValue а затем выводить ее для просмотра с помощью trace() . Если вы хотите больше узнать о побитовых операторах, сдвиговых битах и маскировании, вы можете найти отличный пост на веб-сайте Polygonal Labs .
То, что вы должны увидеть, это вывод целой связки значений 0 но обратите внимание на две строки alpha:255 , это два черных пикселя вверху руки.

Шаг 13: Создание 3D-объектов из значений пикселей
Фу, в этих последних нескольких шагах было довольно много логики! Теперь у нас есть все основы, давайте начнем использовать информацию о пикселях, которую мы получили ранее, чтобы создать 3D-шедевр… почти.
Если вы уже использовали Away3D или Papervision 3D до того, как освоите этот шаг, мы начнем создавать 3D-кубы и применять к ним материалы. Для каждого пикселя, который имеет альфа-значение 255 (непрозрачный), мы берем его цвет и создаем материал на основе цвета для применения к 3D-кубу. Ниже приведен код, который запускает это:
|
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
|
/**
* begins the creation process
*/
public function createFromMovieClip(mc:MovieClip):void
{
// store references and create the bitmapdata
_bitmapData = new BitmapData(mc.width, mc.height, true, 0x000000);
_bitmapData.draw(mc);
// set width / height
_width = mc.width * (2 * _scaleFactor);
_height = mc.height * (2 * _scaleFactor);
// pixel information
var pixelValue:uint = 0;
var red:uint = 0;
var green:uint = 0;
var blue:uint = 0;
var alpha:uint = 0;
// loop through each pixel horizontally
for (var i:int = 0; i < mc.width; i++)
{
pixelValue = _bitmapData.getPixel32(i, 0);
alpha = pixelValue >> 24 & 0xFF;
red = pixelValue >> 16 & 0xFF;
green = pixelValue >> 8 & 0xFF;
blue = pixelValue & 0xFF;
// if pixel is opaque
if(alpha == 255)
{
// create a regular hex color string ie FFFFFF or 000000
var color:String = red.toString(16) + green.toString(16) + blue.toString(16);
if(color == «000») color = «000000»;
trace(«#» + color);
// create a material from the color and apply to a 3D cube
var material:Material = new ColorMaterial(color);
var cube:Cube = new Cube({material:material, width:2 * _scaleFactor, height:2 * _scaleFactor, depth:2 * _scaleFactor});
// position the cube from a — value so registration/transformation point is always center
cube.x = 0 — (_width/2) + cube.width * i;
this.addChild(cube);
}
}
}
|
В приведенном выше коде мы использовали red , green и blue переменные и создали обычный шестнадцатеричный цвет, который можно увидеть в результате выполнения trace() .
Затем шестнадцатеричная цветовая переменная color используется для создания ColorMaterial с Away3D, который представляет собой обычный материал, основанный на цвете, который можно применять к трехмерным объектам.
После этого мы создаем объект Cube и указываем material который будет material объектом, мы создали линию перед ним. Также стоит отметить, что мы установили width , height и depth (помните, что мы сейчас работаем в трех измерениях!) В значение, в два раза _scaleValue переменной _scaleValue , это позволяет нам _scaleValue кубы путем изменение _scaleValue .
Наконец, мы помещаем Cube в ноль минус половину ширины mc умноженную for счетчик циклов i for i , это делает точку регистрации или преобразования готового трехмерного объекта в центре. Затем он добавляется как ребенок, и при тестировании вы увидите два маленьких черных 3D- Cube .
Шаг 14: Строки и столбцы
Теперь два 3D-куба великолепны, и все, но мы действительно хотим, чтобы вся фигура руки была в 3D-кубах. Мы уже используем цикл for чтобы перебрать все пиксели в первой строке, но как нам получить его, чтобы перебрать оставшиеся строки пикселей?
Вы догадались, еще один цикл!
|
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
|
/**
* begins the creation process
*/
public function createFromMovieClip(mc:MovieClip):void
{
// store references and create the bitmapdata
_bitmapData = new BitmapData(mc.width, mc.height, true, 0x000000);
_bitmapData.draw(mc);
// set width / height
_width = mc.width * (2 * _scaleFactor);
_height = mc.height * (2 * _scaleFactor);
// pixel information
var pixelValue:uint = 0;
var red:uint = 0;
var green:uint = 0;
var blue:uint = 0;
var alpha:uint = 0;
// loop through each row of pixels
for (var j:int = 0; j < mc.height; j++)
{
// loop through each pixel horizontally
for (var i:int = 0; i < mc.width; i++)
{
pixelValue = _bitmapData.getPixel32(i, j);
alpha = pixelValue >> 24 & 0xFF;
red = pixelValue >> 16 & 0xFF;
green = pixelValue >> 8 & 0xFF;
blue = pixelValue & 0xFF;
// if pixel is opaque
if(alpha == 255)
{
// create a regular hex color string ie FFFFFF or 000000
var color:String = red.toString(16) + green.toString(16) + blue.toString(16);
if(color == «000») color = «000000»;
trace(«#» + color);
// create a material from the color and apply to a 3D cube
var material:Material = new ColorMaterial(color);
var cube:Cube = new Cube({material:material, width:2 * _scaleFactor, height:2 * _scaleFactor, depth:2 * _scaleFactor});
// position the cube from a — value so registration/transformation point is always center
cube.x = 0 — (_width/2) + cube.width * i;
cube.y = (_height/2) + -cube.height * j;
this.addChild(cube);
}
}
}
}
|
На этот раз мы действительно изменили только три вещи, новый цикл for который на этот раз имеет j в качестве счетчика. В getPixel32() теперь добавлена переменная j в качестве параметра y и, наконец, Cube расположен вертикально с помощью счетчика j .
Это в значительной степени завершает основную логику, теперь она будет проходить по горизонтали, считывать значения пикселей, создавать ColorMaterial и Cube и позиционировать их соответственно. Как только он достигает конца горизонтальной линии, из-за нового цикла for он переходит к следующему пикселю вниз и снова проходит по горизонтали, пока изображение не будет завершено. Посмотрите сами, протестировав фильм:

Шаг 15: в 3-е измерение
Теперь у нас есть все эти 3D объекты, но они выглядят очень 2D, поэтому мы собираемся добавить немного движения и заставить весь объект вращаться.
Для этого нам нужно вернуться к файлу Main.as и найти метод renderLoop() . Помните, что Away3D потребуется визуализировать (или рисовать) 3D-изображение в каждом кадре, поэтому мы можем добавить несколько простых вращений в наш PixelObject3D чтобы увидеть, как вращаются все дочерние Cubes :
|
1
2
3
4
5
6
7
8
|
/**
* the render loop
*/
private function renderLoop(event:Event):void
{
pObject3D.rotationZ++;
view.render();
}
|
Не стесняйтесь экспериментировать с rotationX , rotationY и rotationZ здесь, просто не забудьте сбросить его обратно в код выше, прежде чем продолжить. Вы также можете добавить в create3DObject() чтобы лучше центрировать и выровнять Cubes по камере.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
/**
* creates a 3D pixel object from a MovieClip
*/
public function create3DObject():void
{
pObject3D = new PixelObject3D();
pObject3D.createFromMovieClip(new img1());
pObject3D.x = 80;
pObject3D.y = -55;
pObject3D.rotationX = -5;
scene.addChild(pObject3D);
}
|
Шаг 16: взрыв PixelObject3D
Теперь это больше похоже на то, что мы можем наконец увидеть вращающийся трехмерный пиксельный объект. Мы можем начать настраивать это и добавить разнесенный вид, просто редактируя значение z Cubes при их создании.
Вернитесь к классу PixelObject3d.as и найдите строки, в которых мы PixelObject3d.as Cube x и y и добавьте следующее:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
// if pixel is opaque
if(alpha == 255)
{
// create a regular hex color string ie FFFFFF or 000000
var color:String = red.toString(16) + green.toString(16) + blue.toString(16);
if(color == «000») color = «000000»;
trace(«#» + color);
// create a material from the color and apply to a 3D cube
var material:Material = new ColorMaterial(color);
var cube:Cube = new Cube({material:material, width:2 * _scaleFactor, height:2 * _scaleFactor, depth:2 * _scaleFactor});
// position the cube from a — value so registration/transformation point is always center
cube.x = 0 — (_width/2) + cube.width * i;
cube.y = (_height/2) + -cube.height * j;
cube.z = -25 + (Math.random() * 50);
this.addChild(cube);
}
|
Это переместит каждый Cube на произвольную глубину от -25 до положительной 25 и создаст хороший эффект взрыва:
Шаг 17: Масштабирование
Так как PixelObject3D немного мал на экране, мы собираемся немного изменить масштаб. Мы можем сделать это быстро, _scaleValue переменную PixelObject3D.as классе PixelObject3D.as и увеличив ее до 1,5.
|
01
02
03
04
05
06
07
08
09
10
11
12
|
/**
* creates a 3D object from a MovieClip
*
* @author Anton Mills
*/
public class PixelObject3D extends ObjectContainer3D
{
// properties
protected var _bitmapData:BitmapData = null;
public var _scaleFactor:Number = 1.5;
protected var _width:Number = 0;
protected var _height:Number = 0;
|
Шаг 18: Различные изображения
Использовать класс PixelObject3D для создания других изображений легко, просто импортируйте изображение, которое вы хотите обработать, во Flash. Затем преобразуйте его в мувиклип, как обычно, на этот раз img2 ему имя класса img2 например:

Теперь вы можете изменить Main.as чтобы использовать новый объект img2 с одним небольшим изменением:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
/**
* creates a 3D pixel object from a MovieClip
*/
public function create3DObject():void
{
pObject3D = new PixelObject3D();
pObject3D.createFromMovieClip(new img2());
pObject3D.x = 80;
pObject3D.y = -55;
pObject3D.rotationX = -5;
scene.addChild(pObject3D);
}
|
Шаг 19: несколько объектов
Вы можете использовать их столько, сколько захотите, просто убедитесь, что вы добавили их в сцену Away3D, и их может быть несколько. В этом примере я удалил свойство z которое мы использовали в шаге 16 для эффекта взрыва.
Main.as с другим PixelObject3D добавил:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
/**
* A tutorial aimed at introducing ActionScript 3’s BitmapData
* and how to use the BitmapData information to create a 3D
* pixel shape using Away3D.
*
* @author Anton Mills
*/
public class Main extends MovieClip
{
// basic Away3D properties
protected var scene:Scene3D;
protected var camera:TargetCamera3D;
protected var view:View3D;
protected var pObject3D:PixelObject3D;
protected var pObject3D2:PixelObject3D;
|
Затем создайте еще один экземпляр:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
/**
* creates a 3D pixel object from a MovieClip
*/
public function create3DObject():void
{
pObject3D = new PixelObject3D();
pObject3D.createFromMovieClip(new img2());
pObject3D.x = 40;
pObject3D.y = -55;
pObject3D.rotationX = -5;
scene.addChild(pObject3D);
pObject3D2 = new PixelObject3D();
pObject3D2.createFromMovieClip(new img1());
pObject3D2.x = 115;
pObject3D2.y = -55;
pObject3D2.rotationX = -5;
scene.addChild(pObject3D2);
}
|
И, наконец, поверните его в цикле рендеринга Away3D:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
|
/**
* the render loop
*/
private function renderLoop(event:Event):void
{
pObject3D.rotationY++;
pObject3D2.rotationY—;
pObject3D2.rotationZ—;
pObject3D2.rotationX++;
view.render();
}
|
Шаг 20: фин.
Осталось только протестировать фильм и насладиться великолепием 2D-пикселей, преобразованных в 3D-объекты. Теперь, что вы можете сделать с BitmapData в вашем следующем приложении или игре?
Вывод
В этом руководстве мы рассмотрели различные элементы, но в первую очередь сосредоточились на использовании BitmapData например на рисовании MovieClips в BitmapData , используя setPixel32() для рисования отдельных пикселей, отображения BitmapData с использованием Bitmap и чтения значений пикселей с использованием getPixel32() .
Мы также рассмотрели некоторую цветовую математику, получив шестнадцатеричные цвета и даже отдельные значения альфа, красного, зеленого и синего, используя toString(16) . Наконец, мы написали небольшой цикл для создания 3D- Cubes используя значения пикселей, которые мы прочитали, фу!
Существует так много возможностей, когда вы работаете на уровне пикселей, и с небольшим воображением и экспериментированием вы можете создавать действительно классные приложения и игры! Спасибо за ваше время, надеюсь, вам понравился этот урок.