Отчёт по лабораторной работе ВК. L3-спрайтовая анимация. Лекция спрайтовая анимация
Скачать 171.5 Kb.
|
Лекция 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:
Эффект перемещения точки начала рисования линии так же достигается при помощи установки своства 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 предусмотрены, например, следующие функции:
{ Пример на 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> |