Март 2011
Руководство по actionscript. часть 5, стр. 015
Private function renderListener (e:Event):void {
// Вызываем метод draw( ). если изменения, внесенные в данную фигуру.
// не были отображены на экране.
// Если событие для визуализации было запрошено другим объектом. // но данный объект не изменялся, он не будет перерисован, if (hasChanged( )) { draw( );
}
}
}
}
В листинге 25.2 представлен класс Ellipse — подкласс класса BasicShape. Обратите внимание, что специфический код, предназначенный для рисования эллипса, содержится в методе drawShape ( ). Более того, изменение размеров объекта Ellipse не приводит к немедленной перерисовке эллипса. Вместо этого, когда вызывается метод set Si ze ( ), объект вызывает метод setChanged ( ), сообщая о том, что данный объект должен быть перерисован на этапе следующей визуализации экрана, осуществляемой средой выполнения Flash.
Листинг 25.2. Класс Ellipse
package org. moock. drawing { // Представляет эллипс, который может быть нарисован на экране public class Ellipse extends BasicShape { // Ширина и высота эллипса
protected var w:Number; protected var h:Number;
// Конструктор
public function Ellipse (width:Number = 100. height:Number = 100) { super( );
setSize(width. height);
}
// Процедура рисования эллипса override protected function drawShape ( ):void { graphics. drawEllipse(0, 0. w. h);
}
// Устанавливает ширину и высоту эллипса
public function setSize (newWidth:Number. newHeight:Number):void { w = newWidth; h = newHeight;
// Поскольку установка ширины и высоты эллипса вызывает изменение его // формы, он должен быть перерисован на этапе следующей визуализации // экрана. setChangedC );
}
}
}
В листинге 25.3 представлен класс Pol ygon — еще один подкласс класса Bas i cShape. С помощью класса Polygon можно нарисовать любую многогранную фигуру. Он выступает в роли суперкласса для определенных типов многоугольников, например Rectangle и Star. Как и Ellipse, класс Polygon предоставляет свою собственную специфическую процедуру рисования в методе drawShape ( ). Всякий раз, когда задаются точки объекта Polygon (через метод setPoints ( ) ), вызывается метод setChanged ( ), сообщающий о том, что данный объект должен быть перерисован на этапе следующей визуализации экрана, осуществляемой средой выполнения Flash.
Руководство по actionscript. часть 5, стр. 016
Листинг 25.3. Класс Polygon
package org. moock. drawing { // Представляет многоугольник, который может быть нарисован на экране public class Polygon extends BasicShape { // Точки многоугольника.
// Чтобы сократить потребление памяти, точки хранятся в виде двух
// массивов целочисленных значений, а не в виде одного массива объектов
// f1 ash. geom. Point.
private var xpoints:Array;
private var ypoints:Array;
// Конструктор
public function Polygon (xpoints:Array = null. ypoints:Array = null) { super( );
setPointsCxpoints, ypoints);
}
// Процедура рисования многоугольника
override protected function drawShape ( ):void {
// Рисуем линии в каждую точку многоугольника
graphics. moveTo(xpoints[0]. ypoints[0]);
for (var i:int = 1; i < xpoints.length; i++) { graphics.lineto(xpoints[i]. ypoints[i]);
}
// Замыкаем фигуру, возвращаясь в первую точку graphics. lineTo(xpoints[0]. ypoints[0]);
}
// Присваивает точки многоугольника
public function setPoints (newXPoints:Array. newYPoints:Array):void { if (newXPoints == null || newYPoints == null) { return;
}
if (newXPoints. length!= newYPoints. length) { throw new Error(«setPoints( ) requires a matching » + «number of x and у points»);
}
xpoints = newXPoints; ypoints = newYPoints;
// Поскольку присваивание новых точек многоугольника вызывает // изменение его формы, он должен быть перерисован на этапе // следующей визуализации экрана. setChanged( );
}
}
}
В листинге 25.4 представлен класс Rectangle — подкласс класса Polygon. По структуре он похож на класс Ellipse, однако использует процедуру рисования из метода экземпляра drawShape ( ) класса Polygon, а не реализует собственную.
Руководство по actionscript. часть 5, стр. 017
Листинг 25.4. Класс Rectangle
package org. moock. drawing { // Представляет прямоугольник, который может быть нарисован на экране public class Rectangle extends Polygon {
// Ширина и высота прямоугольника
protected var w:Number;
protected var h:Number;
// Конструктор
public function Rectangle (width:Number = 100. height:Number = 100) { super( );
setSize(width, height);
}
// Устанавливает ширину и высоту многоугольника
public function setSize (newWidth: Number, newHeight «.Number): void {
w = newWidth:
h = newHeight:
// Переводим ширину и высоту в точки многоугольника setPoints([0.w. w.0].[0.0.h, h]);
}
}
}
В листинге 25.5 представлен последний класс из библиотеки: Star, еще один подкласс класса Polygon. Как и Rectangle, класс Star использует метод экземпляра drawShape ( ) класса Polygon для отображения своего контура. Визуальные характеристики каждого объекта Star задаются через метод setStar( ).
Руководство по actionscript. часть 5, стр. 018
Листинг 25.5. Класс Star
package org. moock. drawing { // Представляет фигуру звезды, которая может быть нарисована на экране public class Star extends Polygon { // Конструктор
public function Star (numTips:int.
innerRadius:Number, outerRadius:Number, angle-.Number = 0) {
super( );
setStar(numTips, innerRadius. outerRadius, angle):
}
// Устанавливает физические характеристики звезды.
// За основу взяты методы рисования Рика Эвинга (Ric Ewing) для языка
// ActionScript 1.0. доступные по адресу:
// http://www. adobe. com/devnet/flash/articles/adv_draw_methods. html
// numTips Количество концов (должно быть 3 или больше)
// innerRadius Радиус основания концов
// outerRadius Радиус вершин концов
// angle Начальный угол в градусах (по умолчанию 0)
public function setStar (numTips:int.
Руководство по actionscript. часть 5, стр. 019
InnerRadius:Number, outerRadius:Number, angle:Number = 0):void { // Вычисляем точки многоугольника-звезды if (numTips > 2) { // Инициализируем переменные var pointsX:Array = []; var pointsY:Array = []; var centerX:Number = outerRadius: var centerY:Number = outerRadius;
var step-.Number, half Step: Number,
startAngle-.Number, dx:Number, dy:Number; // Вычисляем расстояние между концами step = (Math. PI*2)/numTips; halfStep = step/2;
// Вычисляем начальный угол, в радианах startAngle = (angle/180)*Math. PI: // Задаем начальную точку
pointsX[0] = centerX+(Math. cos(startAngle)*outerRadius); pointsY[0] = centerY-(Math. sin(startAngle)*outerRadius); // Добавляем оставшиеся точки for (var i:int=l; i <= numtips; i++) {
dx = centerX+Math. cos(startAngle+(step*i)-halfStep)*innerRadi us;
dy = centerY-Math. si n(startAngle+(step*i)-halfStep)*innerRadi us:
pointsX. push(dx);
pointsY. push(dy);
dx = centerX+Math. cos(startAngle+(step*i))*outerRadius; dy = centerY-Math. sin(startAngle+(step*i))*outerRadius; pointsX. push(dx); pointsY. push(dy);
}
// Сохраняем вычисленные точки звезды setPoints(pointsX, pointsY);
}
}
}
}
Наконец, в листинге 25.6 представлен класс ShapeRandomizer, который демонстрирует использование библиотеки классов фигур из пяти предыдущих примеров. Метод-конструктор класса ShapeRandomizer создает четыре фигуры. Щелчок кнопкой мыши на сцене случайным образом изменяет штриховку, заливку и контуры данных фигур.
Руководство по actionscript. часть 5, стр. 020
Листинг 25.6. Класс ShapeRandomizer
package { import flash. display. Sprite; import flash. events. MouseEvent;
import org. moock. drawing.*;
// Демонстрация использования библиотеки org. moock. drawing.
// Создает случайные фигуры, когда пользователь
// щелкает кнопкой мыши на сцене.
public class ShapeRandomizer extends Sprite {
// Фигуры
private var rect:Rectangle; private var ell:El 1ipse; private var poly:Polygon; private var star:Star; // Конструктор
public function ShapeRandomizer ( ) { // Создаем прямоугольник rect = new Rectanglе(50. 100): rect. setStrokeSty1e(1, OxFFOOOO); rect. setFillStyle(OxOOOOFF);
// Создаем эллипс
ell = new Ellipse(250. 50);
ell. setStrokeStyle(2, OxFFFFOO);
ell. setFi11 Sty1e(0xED994F):
// Создаем треугольник (то есть трехгранный объект Polygon) poly = new Polygon([0. 50, 100], [50, 0. 50]); poly. setStrokeStyle(4. 0×333333); poly. setFilIStyle(OxOOFFOO);
// Создаем звезду
star = new Star(5, 30, 80);
star. setStrokeStyle(4, 0×666666);
star. setFillStyle(OxFFOOOO);
// Добавляем фигуры в список отображения
addChiId(rect);
addChild(ell);
addChild(poly);
addChild(star);
// Регистрируем приемник для событий // щелчка кнопкой мыши
stage. addEventLi stener(MouseEvent. MOUSEJDOWN, mouseDownLi stener);
}
// Приемник событий, вызываемый в тот момент, когда пользователь щелкает // в области отображения среды выполнения Flash Player private function mouseDownListener (e:MouseEvent)-.void {
// Изменяем фигуры случайным образом
rect. width = randomd. 300);
rect. height = randomd, 300);
rect. setStrokeStyle(random(l. 10), random(0, OxFFFFFF)); rect. setFillStyle(random(0, OxFFFFFF), Math. random( ));
ell. width = randomd, 300); ell. height = randomd. 300);
ell. setStrokeStyle(randomd. 10). random(0. OxFFFFFF)); el 1.setFi11Style(random(0. OxFFFFFF), Math. random( ));
poly. setPoints(.
Руководство по actionscript. часть 5, стр. 021
[randomd. 300), randomd. 300), randomd. 300)]); poly. setStrokeStyle(randomd. 10). random(0. OxFFFFFF)); poly. setFillStyle(random(0, OxFFFFFF). Math. random( )); star. setStar(random(3. 15), randomdO. 20). random(30. 80));
star. setStrokeStylе(randomd, 10). random(0. OxFFFFFF)); star. setFillStyle(random(0. OxFFFFFF), Math. randomC ));
}
// Возвращает число в диапазоне от minVal до maxVal включительно public function random (minVal:int, maxVal:int):int { return minVal + Math. floor(Math. random( ) * (maxVal + 1 — minVal));
}
}
}
На рис. 25.6 продемонстрирован набор случайных фигур, созданных классом ShapeRandomizer.
Рис. 25.6. Фигуры, созданные классом ShapeRandomizer
От линий к пикселам
В этой главе вы узнали, как создавать векторное графическое содержимое и управлять им. В следующей главе мы рассмотрим методики создания и управления растровым графическим содержимым.
Руководство по actionscript. часть 5, стр. 022
I Дополнительную информацию по векторной графике можно найти в документации по [%: 4 ^ классу Graphics в справочнике по языку ActionScript корпорации Adobe.
ГЛАВА 26
Программирование растровой графики
В терминах программирования растровое изображение — это изображение, которое хранится в растровом формате данных. Растровый формат данных представляет изображение в виде прямоугольной сетки пикселов, в которой каждому пикселу присваивается число, обозначающее его цвет.
Например, если изображение, ширина и высота которого составляют 16 пикселов, представить в растровом формате данных, то оно будет сохранено в виде списка, состоящего из 256 чисел, каждое из которых обозначает конкретный цвет. Этот пример проиллюстрирован на рис. 26.1 — изображение размером 16 х 16 пикселов увеличено с целью отображения его отдельных пикселов. В правой части рисунка указаны позиции в таблице и значения цвета для трех выбранных в изображении пикселов. Обратите внимание, что позиции в таблице начинаются с нуля, поэтому координатой левого верхнего пиксела является (0; 0), а правого нижнего-(15; 15).
X Y Значение цвета
14 2 4294967295
X Y Значение цвета
11 8 4294901760
X Y Значение цвета
12 14 4286015078
Исходное изображение
Увеличенное изображение для показа пикселов
Координаты и значения цвета выбранных пикселов
Рис. 26.1. Пример растрового изображения
В этой главе мы рассмотрим ряд распространенных методик, связанных с программированием растровой графики. Тем не менее имейте в виду, что исчерпывающему описанию программирования растровой графики в языке ActionScript могла бы быть посвящена целая книга. /
В качестве источника информации для дальнейшего изучения можно использовать справочник по языку ActionScript корпорации Adobe.
Руководство по actionscript. часть 5, стр. 023
Классы BitmapData и Bitmap
В языке ActionScript класс BitmapData представляет данные изображения в растровом формате наподобие того, которое показано на рис. 26.1. Каждый экземпляр класса BitmapData содержит список значений цвета пикселов и переменные экземпляра width и height, которые управляют размещением этих пикселов на экране. С помощью класса BitmapData мы можем создать данные для совершенно нового растрового изображения или просмотреть и изменить данные любого существующего растрового изображения, включая растровые изображения, загружаемые извне.
Класс BitmapData предоставляет широкий набор инструментов для установки или получения значения цвета некоторого пиксела или группы пикселов, а также для создания распространенных графических эффектов, например эффекта размытия или падающей тени. Как мы увидим далее, класс BitmapData может быть использован даже для создания анимированных эффектов и определения столкновений на основе растровых изображений. Для работы с большей частью инструментов класса BitmapData мы должны получить представление о формате, используемом языком ActionScript для описания значения цвета пиксела, который рассматривается в следующем разделе.
Как видно из названия, объект BitmapData сам по себе не является изображением; он лишь хранит представляющие изображение данные в растровом формате. Чтобы создать реальное, отображаемое на экране изображение, используя информацию, хранящуюся в объекте BitmapData, мы должны соединить этот объект с экземпляром класса Bitmap, как описано далее в разд. «Создание нового растрового изображения». Класс Bitmap является потомком класса DisplayOb j ect, осуществляющим отображение объекта BitmapData на экране.
-
^ I При работе с растровыми изображениями класс Bitmap используется для управления А. щ изображением как отображаемым объектом, а класс BitmapData — для управления нижележащими пиксельными данными изображения.
Благодаря разделению представления изображения (класс Bitmap) и хранилища данных (класс BitmapData), архитектура растровых изображений языка ActionScript позволяет нескольким различным объектам Bitmap одновременно отображать один и тот же объект BitmapData, при этом каждый объект Bitmap может иметь собственные визуальные характеристики (то есть различный масштаб, угол поворота, обрезку, фильтры, преобразования и прозрачность).
Перед тем как познакомиться с методикой создания нового растрового изображения, бегло рассмотрим способ представления цветов в языке ActionScript.
Значения цвета пикселов
В языке ActionScript значения цвета пикселов, формирующих растровые изображения, сохраняются в виде 32-битных беззнаковых целых чисел, обеспечивая огром-
ный диапазон из 4 294 967 296 возможных значений цветов. Каждое конкретное значение цвета в объекте BitmapData концептуально состоит из четырех отдельных значений, которые представляют четыре различных компонента цвета — Alpha (Альфа) (то есть прозрачность), Red (Красный), Green (Зеленый) и Blue (Синий). Эти четыре компонента называются цветовыми каналами. Величина каждого канала в любом цвете варьируется от 0 до 255. Соответственно в двоичном виде каждый канал занимает 8 из 32 бит значения цвета, как показано далее:
? Alpha — биты 24-31 (самый старший байт);
? Red-биты 16-23;
? Green — биты 8-15;
? Blue — биты 0-7.
Руководство по actionscript. часть 5, стр. 024
Чем выше значение канала Red, Green или Blue, тем больший вклад вносит каждый цвет в результирующий цвет. Если значения всех трех каналов RGB равны, будет получен оттенок серого цвета; если значения всех каналов равны 0, будет получен черный цвет; если значения всех каналов равны 255, будет получен белый цвет. Данный 32-битный формат цвета позволяет задать 16 777 216 возможных цветов, при этом каждый цвет может иметь отдельный уровень канала Alpha, находящийся в диапазоне от 0 (прозрачный) до 255 (непрозрачный).
Например, чистый красный цвет описывается следующими значениями каналов:
Alpha: 255, Red: 255, Green: 0, Blue: О
Эти значения соответствуют следующим установкам битов в 32-битном беззнаковом целочисленном значении цвета (пробелы определяют границы четырех байтов):
11111111 11111111 00000000 00000000
В десятичном виде предыдущее целочисленное значение будет выглядеть следующим образом:
4294901760
Безусловно, когда значение цвета представлено в виде одного десятичного числа, уровни различных каналов в этом значении цвета неочевидны. В связи с этим значения цвета пикселов для удобочитаемости обычно записываются в шестна-дцатеричном виде: OxAARRGGBB, где АА, RR, GG и ВВ — это двухразрядные шестна-дцатеричные числа, представляющие каналы Alpha, Red, Green и Blue. Например, предыдущее значение для чисто красного цвета (А:255, R:255, G:0, В:0) в шестна-дцатеричном виде записывается следующим образом:
0xFFFF0000 // Гораздо проще читать!
Для сравнения на рис. 26.2 представлено изображение, заимствованное из рис. 26.1, но на этот раз значения цвета трех выбранных пикселов разбиты на соответствующие цветовые каналы, записанные в шестнадцатеричном виде.
*^ 1 Пример перевода чисел в шесгнадцатеричную систему счисления можно найти по адресу
4
http://www. moock. org/asdg/technotes/basePrimer.