|
Отчёт по лабораторной работе ВК. L3-спрайтовая анимация. Лекция спрайтовая анимация
Лекция 3. СПРАЙТОВАЯ АНИМАЦИЯ
Основной недостаток графической системы недалекого прошлого: невозможность получения динамического изменения реалистичного изображения в реальном времени. В зависимости от реалистичности и мощности техники требуется от нескольких минут до нескольких часов на рендеринг (как процесс получения 2D-картинки из 3D-описания) одного изображения-кадра (и до сих пор в Голливуде для идеальной реалистичности).
П роблему решили следующим образом:
подготовка кадров заранее (фреймов). прокрутка подготовленных кадров – анимация.
1. Кадровая анимация (fli, avi, mov и т.д.). Клипы.
Изображение развернуто в растр, плавность и динамичность изображения (min 15 кадров/с).
Недостатки:
1. 1920х1080х3байта = 6Мб, 5 сек, 75*6Мб > 450Мб – требуется много памяти
2. медленный вывод на экран, т.к. обновляется весь кадр. 2. Спрайтовая анимация.
Спрайт – изображение только динамически изменяющегося объекта в одной из фаз движения на однородном фоне (черном или белом или прозрачном).
Фон – неизменная при смене кадров часть всего изображения.
Для формирования спрайта выделяется прямоугольник, охватывающий изображение объекта (одинакового размера для всех спрайтов).
На каждом шаге необходимо: 1. восстановить фон на старом месте спрайта; 2. рассчитать новое место спрайта и сохранить фон; 3. вывести спрайт в рассчитанное место.
При подготовке спрайтов решаются следующие вопросы:
1. Сколько всего необходимо спрайтов?
2. Как часто нужно выводить спрайты?
3. В какие места экрана выводить?
4. Методика анимации.
П редварительные расчеты
N ‑ min 2 спрайта, но лучше 4..8
спр – частота вывода спрайтов (>=15 к/сек для плавности отображения)
t – общее время перемещения
t*спр – число позиций вывода
X = Xк – Xo => шаг X = X/( t*спр)
Y = Yк – Yo => шаг Y = Y/( t*спр)
Шаг должен быть не меньше одного пикселя, чем хуже разрешение и ниже скорость вывода спрайтов, тем больше вероятность прерывистого движения.
В каждом цикле координаты рассчитываются по следующим формулам:
Xi+1 = Xi + шаг X
Yi+1 = Yi + шаг Y
Фазы движения спрайта (n mod N)+1 должны охватывать элементарное действие:
Tф – промежуток времени от начальной фазы движения до конечной.
спрTф – число фаз движения (могут циклически повторяться). Методы анимации.
1. Общий метод.
В каждой позиции:
Восстанавливаем общий фон под спрайтом на старом месте. Рассчитываем новое место спрайта и запоминаем общий фон. Выводим спрайта на новое место (только пикселы изображения спрайта).
Ф он самого спрайта должен быть прозрачным. Для этого цвет фона выбирают такой, которого нет на самом спрайте, иначе неизбежны "дырки" в изображении. Обычно используют цвет с нулевым кодом (черный). При выводе проверяем наличие пикселя-нуля, если есть – не выводим. Процедура вывода получается сложная и медленная (нет аппаратной поддержки в видеоадаптере сравнения).
2 . Отсечение фона маской спрайта.
О тдельно подготавливается (рисуется в граф. редакторе) спрайт и отдельно маска. И спрайт и маска должны иметь одинаковый размер. Маска (черная тень изображения на белом фоне) нужна для того, чтобы при выводе спрайта не затирался общий фон и можно было использовать в спрайте все цвета. Спрайт обязательно должен быть на черном (прозрачном) фоне. Процедура вывода использует аппаратную поддержку блочных функций AND и XOR и получается проще и быстрее.
Этапы:
Восстанавливаем общий фон на старое место под спрайтом. Рассчитываем новое место спрайта и запоминаем фон. Накладываем на новое место маску спрайта (операция AND). Н акладываем на новое место сам спрайт (операция XOR).
3. Простая XOR-анимация.
Свойство обратимости:
Свойство прозрачности 0:
Этапы:
Восстанавливаем общий фона XOR-выводом спрайта на старое место. Рассчитываем новое место спрайта и XOR-выводим спрайт.
Если фон черный (код 0), то спрайт отображается нормально, если сложный, то происходит наложение цветов ‑ сквозь спрайт просвечивается цветоинверсный фон. Общий недостаток анимации ‑ мерцание.
Мерцание изображения – это общий недостаток вышеперечисленных методов анимации, когда часть времени изображение спрайта на экране отсутствует (между 1 и 3 этапами): восстанавливается общий фон под спрайтом ‑ tнет.
М етоды подавления мерцания (tнет.->0):
Перекрытие спрайтов. Синхронизация с растровой разверткой. Промежуточный буфер в ОЗУ. Работа с несколькими страницами.
1. Перекрытие спрайтов.
В изображение каждого спрайт вводится дополнительное поле, полностью перекрывающее предыдущий спрайт на старом месте отображения.
Недостаток: число спрайтов должно быть равно числу мест вывода для сохранения общего фона.
Алгоритм сводится к одному действию:
1. Рассчитываем новое место спрайта и выводим его, одновременно этим затирая спрайт на старом месте фоном, НО требуется предварительная подготовка спрайтов с актуальным фоном.
Ожидание конца обратного хода луча по кадру:
Mov dx, 3DAh
Wait_end:
In al, dx
Test al, 8
Jnz Wait_end
Ожидание начала обратного хода луча по кадру:
Wait_begin:
In al, dx
Test al, 8
Jz Wait_begin На Pascal
While (port[$3DA] and 8)<>0 do ;
While (port[$3DA] and 8)=0 do ;
2. Синхронизация с растровой разверткой.
О братный ход кадровой развертки. При отображении картинки на мониторе луч в ЭЛТ последовательно пробегает по всем строчкам сверху вниз, а затем выключается и возвращается в начало экрана. Данный процесс и называется обратным ходом кадровой развертки; он происходит периодически (70-100 раз/сек с паузой 20% на обратный ход). В это время изображение на дисплее не формируется, и потому в видеопамяти можно делать изменения, не опасаясь, что они приведут к появлению помех на экране.
1/100*0.2*3ГГц=6МГц (млн. команд ЦП на цикл) 3 . Промежуточный буфер в ОЗУ
Копирование общего блока (старое место + новое место спрайта) из видеобуфера в ОЗУ. Восстановление фона на старое место (копирование ОЗУ-ОЗУ). Взятие копии фона из нового места (копирование ОЗУ-ОЗУ). Наложение маски в ОЗУ. Наложение спрайта в ОЗУ. Вывод общего блока из ОЗУ в видеобуфер.
0 ВАВА…
1 АВАВ… 2
3
4 . Работа с несколькими страницами видеопамяти
Обычно используют две страницы видеопамяти. Одна является видимой (В) и отображается на экране монитора, другая – активная страница (А), в ней производится отрисовка следующего кадра.
Как только следующий кадр подготовлен, страницы меняются местами (это осуществляется аппаратно за один такт), т.е. активная (с новым кадром) становится видимой, а видимая – активной и теперь в ней можно формировать новый кадр.
Графическая библиотека BGI+ среды Delphi Работа с графикой в Delphi (или С++Builder) предполагает обращение к канве - свойству Canvas компонентов. Canvas Delphi это холст, который позволяет программисту иметь доступ к каждой своей точке (пикселу), и словно художнику отображать то, что требуется (BGI+ как надстройка над GDI+ Windows).
В работе с графикой в Delphi в распоряжении программиста находятся не только канва (холст, полотно - свойство Canvas Delphi компонентов), но и карандаш (свойство Pen), и кисть (свойство Brush) того компонента или объекта, на котором предполагается рисовать. У карандаша Pen и кисти Brush можно менять цвет (свойство Color) и стиль (свойство Style), а у карандаша еще и толщину (Width) и т.п. Доступ к шрифтам предоставляет свойство канвы Font. Эти инструменты позволяют отображать как текст, так и достаточно сложные графики математического и инженерного содержания, а также рисунки. Кроме этого, работа с графикой позволяет использовать в Delphi такие ресурсы Windows как графические и видеофайлы.
Конечно, не все компоненты в Delphi имеют эти свойства. На вкладке Additional расположен специализированный компонент TImage, специально предназначенный для рисования, но также свойство Canvas имеют, например, такие компоненты как ListBox, ComboBox, StringGrid, а также и сама Форма, которая размещает наши компоненты! Кроме этого «рисовать» можно на TPaintBox и на невидимом объекте TBitMap – контейнере (буфере в ОЗУ) рисунков.
Основное свойство такого объекта как Canvas Delphi - Pixels[i, j] типа TColor, то есть это двумерный массив точек (пикселов), задаваемых своим цветом. Рисование на канве происходит в момент присвоения какой-либо точке канвы заданного цвета. Каждому пикселу может быть присвоен любой доступный для Windows цвет. Например, выполнение оператора
Image1.Canvas.Pixels[100, 200]:=clRed;
приведёт к рисованию красной точки с координатами [100, 200]. Узнать цвет пиксела можно обратным присвоением:
Color:=Image1.Canvas.Pixels[100, 200];
Тип TColor определён как длинное целое (LongInt). Его четыре байта содержат информацию о долях синего (B), зелёного (G), и красного (R) цветов. В 16-ричной системе это выглядит так: $00BBGGRR. Доля каждого цвета может меняться от 0 до 255. Поэтому, например, чтобы отобразить максимально красную точку, ей нужно присвоить цвет $000000FF.
Для вывода текста (шрифтом Font) используется метод:
TextOut(X, Y: Integer; const Text: WideString); ‑ производит вывод строки Text начиная с (X, Y) - левого верхнего пиксела текста.
Сперва необходимо чётко уяснить, что координата (0,0) это верхний левый угол экрана. То есть значения по оси y увеличиваются вниз экрана. Соответственно, координата (0, 50) означает, что мы просто отступили на 50 пикселей от верха экрана.
Самое главное, что надо знать при рисовании линий и фигур, это различие между пером (Pen) и кистью (Brush). Всё очень просто: перо (Pen) используется при рисовании линий или рамок, а кисть (Brush) для заполнения фигуры.
Ниже приведены две функции, которые используются для рисования линий и обе принадлежат TCanvas: Имя
| Описание
| Пример
| MoveTo
| Перемещает точку начала рисования линии в указанные координаты x и y
| Canvas.MoveTo(50, 100);
| LineTo
| Рисует линию начиная с текущей позиции (см. MoveTo) до указанных координат x и y.
| Canvas.LineTo(50, 100);
| Эффект перемещения точки начала рисования линии так же достигается при помощи установки своства PenPos в канвасе... например, "Canvas.PenPos.x := 20;", "Canvas.PenPos.y := 50", или "Canvas.PenPos := Point(20,50);".
По умолчанию, точка начала рисования установлена в (0,0), то есть, если сразу вызвать "Canvas.LineTo(100,100);" то будет нарисована линия из точки (0,0) в точку (100, 100). Точка начала рисования автоматически переместится в (100, 100), то есть, если выполнить команду "Canvas.LineTo(200, 100);", то следующая линия будет нарисована из точки (100, 100) в (200, 100). Поэтому, если мы хотим рисовать линии несоединённые друг с другом, то придётся воспользоваться методом MoveTo.
Линия, нарисованная при помощи LineTo использует текущее перо канваса (типа TPen). Основные свойства пера, это ширина - "Canvas.Pen.Width := 4;" (при помощи которого можно задавать различную ширину линий), и цвет "Canvas.Pen.Color := clLime;".
Для рисования фигур, в TCanvas предусмотрены, например, следующие функции: ИМЯ
| ОПИСАНИЕ
| ПРИМЕР
| Ellipse
| Рисует элипс, вписанный в невидимый квадрат с координатами верхнего левого угла и правого нижнего. Если координаты х и y у углов будут совпадать, то получится круг.
| Canvas.Ellipse(0,0,50,50);
| FillRect
| Заполняет прямоугольник цветом текущей кисти (brush), но никак не за пределами него.
| Canvas.FillRect( Bounds(0,0,100,100));
| FloodFill
| Заполняет данную область цветом текущей кисти, до тех пор пока не будет достигнут край.
| Canvas.FloodFill(10, 10, clBlack, fsBorder);
| Rectangle
| Рисует прямоугольник (или квадрат), заполненный цветом текущей кисти и обрамлённый цветом текущего пера
| Canvas.Rectangle( Bounds(20, 20, 50, 50));
| RoundRect
| Тоже, что и Rectangle, но с загруглёнными углами.
| Canvas.RoundRect( 20, 20, 50, 50, 3, 3);
|
{ Пример на Delphi 7.0 } unit Unit1; interface uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls; type
TForm1 = class(TForm)
Image1: TImage;
CheckBox1: TCheckBox;
Timer1: TTimer;
procedure CheckBox1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end; var
Form1: TForm1; implementation {$R *.dfm} procedure TForm1.CheckBox1Click(Sender: TObject);
begin
Timer1.Enabled:=CheckBox1.Checked;
end; VAR TB: TBitMap;
xx,yy,dx,sn,c35 :integer; procedure TForm1.FormCreate(Sender: TObject);
begin TB:=TBitmap.create;
TB.LoadFromFile('runner.bmp'); //10 по 35х35 пикселей
TB.Transparent:=true;
xx:=0; dx:=1; yy:=100; sn:=0; c35:=35;
end; procedure TForm1.Timer1Timer(Sender: TObject);
var i,j :integer; cc:tcolor;
begin //отрисовка
Image1.Picture.LoadFromFile('fon.bmp'); //320x200
//Image1.Canvas.Draw(xx,yy,TB); //альтернативные функции
//Image1.Canvas.BrushCopy(Rect(xx,yy,xx+35,yy+35),TB,Rect(0,Sn,35,Sn+35),clWhite);
for j:=Sn to Sn+c35-1 do
for i:=0 to TB.Width-1 do begin
if dx<0 then cc:=TB.Canvas.Pixels[c35-1-i,j] else cc:=TB.Canvas.Pixels[i,j];
if cc<>TB.Canvas.Pixels[0,0] then
Image1.Canvas.Pixels[xx+i,yy+j-Sn]:=cc; end;{}
xx:=xx+dx; if (xx<0)or(xx>320-c35) then dx:=-dx;
yy:=yy+Round(sin(xx/20)*dx);
Sn:=Sn+c35; if Sn>= TB.Height then Sn:=0;
end; end.
Графическая библиотека FrameWork.NET MS Visual Studio
В среде С++/С# поддерживается множественное наследование (в отличие от Delphi, где холст+карандаш+кисть+шрифт+художник – это один объект) и поэтому объекты для поддержания растровой и векторной графики не объединены изначально и требуют явных ссылок друг на друга, т.е. нужно отдельно создавать объект карандаш-Pen и кисть-Brush и художника-Graphics и связать его с холстом (например, PictureBox). Идеология FrameWork.NET описана в п.2.
В языках С++/C# существует целая библиотека для создания графики "System.Drawing". Она автоматически подключается при создании проекта.
Самое главное изменение, которое может ввести в тупик новичка, ‑ это кодировка цвета: здесь для него используется 4 байта ARGB, т.е. введен альфа-канал (прозрачность) и, самое непонятное, он должен быть 255 (больше 0), чтобы пиксель рисовался! Если у вас не рисуется пиксель делайте: Pix |= 0xFF000000; может и поможет.
Прямой доступ к пикселям есть в классе BitMap через методы
Status GetPixel(INT x, INT y, Color* color);
Status SetPixel(INT x, INT y, const Color& color);
Эти методы очень медленные, можно использовать групповые методы:
Status LockBits(IN const Rect* recx, IN UINT flags, IN PixelFormat format, OUT BitmapData* lockedBitmapData)
Status UnlockBits();
Прозрачность цвета при копировании делается методом:
MakeTransparent(const Color& color);
Пример, где по нажатию кнопки на форме файл «music.bmp» отображается в PictureBox1 только красной компонентой цвета RGB:
private void Button1_Click(System.Object sender, System.EventArgs e)
{ try { // Retrieve the image.
image1 = new Bitmap(@"C:\My Music\music.bmp", true);
int x, y; // Loop through the images pixels to reset color.
for(x=0; x
{ for(y=0; y
{ Color pixelColor = image1.GetPixel(x, y);
Color newColor = Color.FromArgb(pixelColor.R, 0, 0);
image1.SetPixel(x, y, newColor);
} }
// Set the PictureBox to display the image.
PictureBox1.Image = image1;
// Display the pixel format in Label1.
Label1.Text = "Pixel format: "+image1.PixelFormat.ToString();
} catch(ArgumentException)
{ MessageBox.Show("File not found.");
} }0> |
|
|