Навигация
Главная
Поиск
Форум
FAQ's
Ссылки
Карта сайта
Чат программистов

Статьи
-Delphi
-C/C++
-Turbo Pascal
-Assembler
-Java/JS
-PHP
-Perl
-DHTML
-Prolog
-GPSS
-Сайтостроительство
-CMS: PHP Fusion
-Инвестирование

Файлы
-Для программистов
-Компонеты для Delphi
-Исходники на Delphi
-Исходники на C/C++
-Книги по Delphi
-Книги по С/С++
-Книги по JAVA/JS
-Книги по Basic/VB/.NET
-Книги по PHP/MySQL
-Книги по Assembler
-PHP Fusion MOD'ы
-by Kest
Professional Download System
Реклама
Услуги

Автоматическое добавление статей на сайты на Wordpress, Joomla, DLE
Заказать продвижение сайта
Программа для рисования блок-схем
Инженерный калькулятор онлайн
Таблица сложения онлайн
Популярные статьи
OpenGL и Delphi... 65535
Форум на вашем ... 65535
21 ошибка прогр... 65535
HACK F.A.Q 65535
Бип из системно... 65535
Гостевая книга ... 65535
Invision Power ... 65535
Пример работы с... 65535
Содержание сайт... 65535
ТЕХНОЛОГИИ ДОСТ... 65535
Организация зап... 65535
Вызов хранимых ... 65535
Создание отчето... 65535
Имитационное мо... 65535
Программируемая... 65535
Эмулятор микроп... 65535
Подключение Mic... 65535
Создание потоко... 65535
Приложение «Про... 65535
Оператор выбора... 65535
Реклама
Сейчас на сайте
Гостей: 10
На сайте нет зарегистрированных пользователей

Пользователей: 13,368
новичок: Goosprin
Новости
Реклама
Выполняем курсовые и лабораторные по разным языкам программирования
Подробнее - курсовые и лабораторные на заказ
Delphi, Turbo Pascal, Assembler, C, C++, C#, Visual Basic, Java, GPSS, Prolog, 3D MAX, Компас 3D
Заказать программу для Windows Mobile, Symbian

Расчет обратной матрицы на Delphi + Пояснительная записка
Принадлежит ли точка пересечению двух окружностей на Turbo Pascal + Отче...
Моделирование ЭВМ на GPSS (три класса заданий) + Пояснительная записка

Основы спрайтовой анимации
Основы спрайтовой анимации
Сергей Андрианов

11.09.2001



Довольно часто в конференциях Fidonet, посвященных программированию и разработке компьютерных игр, встречаются вопросы по спрайтовой анимации. Начинающие программисты тоже, наверное, хотели бы почитать что-нибудь на эту тему, а еще лучше — просто посмотреть, как действует подобная простенькая программа. Может ли быть что-то более интересное для школьника, чем самому написать компьютерную игру.

На уроках информатики или факультативных занятиях, где рассматриваемый материал выходит за рамки школьной программы, учащимся, как правило, предлагали работать с процедурами модуля Graph. Для учебных целей или создания статической графики это, возможно, и неплохой вариант, но вот для анимированной он явно не годится из-за экранного режима и набора процедур модуля Graph. Для анимации 16-цветные режимы не слишком подходят, так как требуют довольно сложной структуры видеопамяти, а также постоянного обращения к регистрам видеоадаптера, что значительно замедляет работу. Поэтому для нашего примера мы не будем пользоваться ни модулем Graph, ни стандартными для Borland Pascal видеорежимами.

Итак, примем режим 256 цветов и разрешение 320x200 точек. Этот стандартный видеорежим — самый простой с точки зрения организации видеопамяти. В данном случае она представляет собой большой байтовый массив размером 320x200 точек, где каждый байт соответствует определенной точке. Таким образом, точка с координатами (x, y) находится в видеопамяти со смещением x + 320y. Для удобства опишем экран как двумерный массив, любой байт которого может принимать 256 различных значений, так что на экране одновременно может появляться до 256 цветов, причем всякому значению байта соответствует свой цвет, определяемый регистрами палитры. Значит, записывая байт в установленное место видеопамяти, мы «зажигаем» точку.

Так как стандартные драйверы экрана не поддерживают выбранный нами режим, установим его напрямую через VideoBIOS. Кроме того, не подключены графические драйверы, а потому нет и стандартных функций, позволяющих рисовать точку, линию, круг, прямоугольник, — правда, точку можно изобразить через тот же VideoBIOS, но делается это очень медленно. Впрочем, в спрайтовой анимации такие функции и не нужны, жаль только, что пропадают те из них, которые обеспечивают вывод текста. В принципе можно воспользоваться и поддерживающими 256 цветов библиотеками (к сожалению, в стандартную поставку Вorland/Turbo Рascal они не входят), однако они годятся лишь для вывода текста или расчерчивания рамок. В конце концов, вывод текста — отдельный разговор, и к нему мы еще вернемся.
Теперь о спрайтах

Встречаются и такие тексты программ, где рисунки спрайтов вводятся в массив числовых констант прямо с клавиатуры. Один курсор мыши создать так, конечно, можно, а вот спрайт размером, скажем, 128x128 точек — весьма проблематично. Таким образом, для изготовления спрайтов следует пользоваться не текстовым, а графическим редактором. Самое простое — изучить формат и «читать» спрайты из них. Но сперва давайте побыстрее получим первый результат. Для этого поступим следующим образом: возьмем редактор Paint, зададим размер изображения 20x20 точек (пункты «Рисунок•Атрибуты») и нарисуем что-нибудь на белом фоне, а потом в файл с именем sprt01.bmp запишем это изображение, причем обязательно в режиме 256 цветов, иначе это будет неправильно воспринято нашей программой. Первые 1078 байт полученного файла займет заголовок, содержащий информацию о размерах изображения, используемых цветах и т. д. Сначала размер изображения мы зададим в программе жестко, а цвета будем игнорировать.

Вывод на экран

Перед тем как выводить спрайт, надо сохранить находящееся под ним изображение, чтобы фон не испортился, когда спрайт «уйдет». Поэтому считаем информацию с того места экрана, куда будет помещен спрайт. Непосредственно перед выводом спрайта восстановим изображение, а затем снова сохраним фон из нового места, куда будет помещен спрайт.

Реальные спрайты редко имеют прямоугольную форму, поэтому выводить следует только отдельные точки считанного изображения, включив для этого понятие «прозрачный цвет». В данном случае мы выбираем белый цвет с кодом 255 ($FF). При выводе спрайта рисуются лишь те точки, код которых не равен 255 (для «прозрачного цвета» можно взять любое значение: 0, 5, 31 — как вам будет удобно).

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

Текст созданной нами программы см. в листинге. Чтобы описать спрайт, определяем запись SpriteType. Для прямого доступа к видеопамяти используем массив Mem, а для вызова функции VideoBIOS — процедуру intr. Итак, что же получилось?
Цвета вышли не такие, какие нам хотелось бы. Что делать? По умолчанию в среде DOS и в Windows установлены различные палитры. Чтобы цвета были такими, какими нужно, следует прочитать заголовок BMP-файла, взять из него данные по цветам и записать их в регистры палитры.
Изображение спрайта получилось перевернутым. Так уж устроено, что на экране ось Y идет сверху вниз, а в BMP-файле — снизу вверх. Думаю, исправить это не составит большого труда.
Если сделать спрайт большего размера, то возникает мелькание в верхней части экрана. Чтение данных из видеопамяти происходит долго, поэтому этого лучше просто избегать. (Подробнее обо всем см. в следующих номерах журнала.)

Кстати, попробуйте отключить (закомментировать) ожидание обратного хода и посмотрите, что из этого получится.

На приведенном здесь примере показано, как перемещать спрайт по экрану. Кроме того, чередуя несколько фаз (кадров) изображения, можно заставить спрайт «махать руками», «топать ногами» и т. п., даже находясь в одном месте экрана. Для этого нужно либо сопоставить файл каждому кадру, либо поместить все кадры в один файл (последнее предпочтительнее, но требует большей работы), а затем по очереди выводить изображение спрайта из того или иного кадра на экран (в буфер).

Краткий глоссарий

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

Видеорежимы. Есть несколько режимов работы видеоконтроллера, различающихся способом отображения на экран содержимого видеопамяти. Они, в свою очередь, подразделяются на текстовые и графические. При текстовых экран разбивается на знакоместа (обычно размером 9x16 точек), а в видеопамять вписываются коды символов. По коду видеоконтроллер берет и выводит на экран готовую «картинку» символа. Нарисовать произвольное изображение в текстовом режиме нельзя, и потому приходится довольствоваться лишь заранее определенным набором символов. При графических режимах можно управлять каждой точкой экрана, но для этого требуется гораздо больший объем видеопамяти, да и работа займет много времени.

Графические режимы могут различаться разрешением (320x200, 640x480, 800x600 точек и др.) и числом цветов (2, 4, 16, 256, 65 тыс., 16 млн.).

Обратный ход кадровой развертки. При отображении картинки на мониторе луч в ЭЛТ последовательно пробегает по всем строчкам сверху вниз, а затем выключается и возвращается в начало экрана. Данный процесс и называется обратным ходом кадровой развертки; он происходит периодически (70 раз в секунду в режиме 320x200 точек и 256 цветов). В это время изображение на дисплее не формируется, и потому в видеопамяти можно делать изменения, не опасаясь, что они приведут к появлению помех на экране.

Спрайт (sprite) — небольшое изображение, свободно перемещающееся по монитору. В первоначальном смысле слова этот термин применялся только для аппаратно выводимых изображений. Собственно, лишь один настоящий спрайт можно встретить на IBM PC — аппаратный курсор мыши. При архитектуре х86 под спрайтом принято понимать программно выводимое изображение, которое может иметь сложную форму и передвигаться поверх фона, не затирая его.

VideoBIOS. BIOS — базовая система ввода-вывода, обеспечивающая проведение элементарных операций по обслуживанию периферии ПК: дисковых накопителей, клавиатуры, монитора и др. Она представляет собой микросхему ПЗУ, находящуюся на системной плате компьютера. VideoBIOS — расположенная на видеоконтроллере часть BIOS, выполняющая базовые функции по работе с монитором.

Листинг. Программа работы со спрайтами
program Sprite;
{простейшая демонстрация работы со спрайтами}
uses
dos, {для работы с прерыванием VideoBIOS}
crt; {для работы с клавиатурой}
const
Xsize = 20; {размеры спрайта, точек}
Ysize = 20;
TransparentColor = $FF; {"прозрачный" цвет}
type
SpriteArrayType = array[0..Ysize-1,0..Xsize-1]of byte;
{массив равный по размеру спрайту}
SpriteType = record
x,y : word; {текущие координаты спрайта}
dx,dy : integer; {приращения координат спрайта}
Img : ^SpriteArrayType;
{для массива с изображением спрайта}
Back : ^SpriteArrayType;
{для массива, хранящего фон под спрайтом}
end;
ScreenType = array[0..199,0..319]of byte;
{для экрана}
var
Sprt : SpriteType; {спрайт}
r : registers; {для вызова прерывания BIOS}
Scr : ^ScreenType; {экран}

procedure GetBuffer;
{сохранение фона под спрайтом в буфере}
var
i,j : word; {переменные цикла}
begin
for j := 0 to Ysize-1 do
for i := 0 to Xsize-1 do
with Sprt do
Back^[j,i] := Scr^[j+y,i+x];
end;

procedure PutBuffer; {восстановление фона}
var
i,j : word; {переменные цикла}
begin
for j := 0 to Ysize-1 do
for i := 0 to Xsize-1 do
with Sprt do
Scr^[j+y,i+x] := Back^[j,i];
end;

procedure PutSprite; {вывод спрайта на экран}
var
i,j : word; {переменные цикла}
begin
for j := 0 to Ysize-1 do
for i := 0 to Xsize-1 do
with Sprt do
if Img^[j,i] <> TransparentColor then
{ставим только точки,}
{цвет которых отличается от "прозрачного"}
Scr^[j+y,i+x] := Img^[j,i];
end;

procedure PutBackground; {создание фона на экране}
var
i,j : word; {переменные цикла}
begin
for j := 0 to 199 do
for i := 0 to 319 do
Scr^[j,i] := lo(i+j*8);
end;

procedure CreateSprite(s:string; x,y,dx,dy:integer);
{"создание" спрайта}
var
f : file; {файл с изображением спрайта}
begin
getmem(Sprt.Img,sizeof(SpriteArrayType));
{выделяем память для спрайта}
getmem(Sprt.Back,sizeof(SpriteArrayType));
{выделяем память для буфера}
assign(f,s); {bmp-файл размерами Xsize на Ysize}
reset(f,1); {открываем файл со спрайтом}
seek(f,1078); {пропускаем заголовок}
blockread(f,Sprt.Img^,Xsize*Ysize);
{читаем изображение}
close(f);
Sprt.x := x;
Sprt.y := y; { задаем начальные значения }
Sprt.dx := dx; { координат и приращений }
Sprt.dy := dy;
end;

procedure DestroySprite; {"уничтожение" спрайта}
begin
{ возвращаем память }
freemem(Sprt.Back,sizeof(SpriteArrayType));
freemem(Sprt.Img,sizeof(SpriteArrayType));
end;

procedure CalcSpritePosition; {вычисление координат}
begin {спрайта и их приращений}
{по достижении границы экрана делаем,}
{ чтобы спрайт "отразился" от нее}
with Sprt do begin
if (x + Xsize + dx) >= 319 then
dx := -dx; {вычисляем новые приращения}
if (x + dx) <= 0 then
dx := -dx; {реализующие "отражение"}
if (y + Ysize + dy) >= 199 then
dy := -dy; {спрайта от стенок}
if (y + dy) <= 0 then
dy := -dy;
x := x+dx; { вычисляем новые }
y := y+dy; { координаты спрайта }
end;
end;

begin
CreateSprite('sprt01.bmp',0,0,1,1);
r.ax := $13; { устанавливаем режим }
intr($10,r); { 320х200х256 цветов }
Scr := ptr(SegA000,0); {адрес видеопамяти}
PutBackGround; {рисуем фон}
GetBuffer; {сохраняем фон под спрайтом}
PutSprite; {и рисуем на его месте спрайт}
repeat {теперь спрайт будет двигаться по экрану}
{до тех пор, пока мы не нажмем на клавишу}
PutBuffer; {восстанавливаем фон}
CalcSpritePosition;
GetBuffer; {сохраняем фон}
PutSprite; {рисуем спрайт}
while (port[$3da] and 8) = 0 do;
{ожидаем обратный ход луча кадровой развертки}
until keypressed;
readkey; {чистим буфер клавиатуры}
r.ax := $3;
intr($10,r); {возвращаемся в текстовый режим}
DestroySprite;
end.


Опубликовал Kest October 31 2008 20:21:24 · 0 Комментариев · 13076 Прочтений · Для печати

• Не нашли ответ на свой вопрос? Тогда задайте вопрос в комментариях или на форуме! •


Комментарии
Нет комментариев.
Добавить комментарий
Имя:



smiley smiley smiley smiley smiley smiley smiley smiley smiley
Запретить смайлики в комментариях

Введите проверочный код:* =
Рейтинги
Рейтинг доступен только для пользователей.

Пожалуйста, залогиньтесь или зарегистрируйтесь для голосования.

Нет данных для оценки.
Гость
Имя

Пароль



Вы не зарегистрированны?
Нажмите здесь для регистрации.

Забыли пароль?
Запросите новый здесь.
Поделиться ссылкой
Фолловь меня в Твиттере! • Смотрите канал о путешествияхКак приготовить мидии в тайланде?
Загрузки
Новые загрузки
iChat v.7.0 Final...
iComm v.6.1 - выв...
Visual Studio 200...
CodeGear RAD Stud...
Шаблон для новост...

Случайные загрузки
Советы по Delphi
ATComponents
Открытие Cd-ROM'a...
AdBlaster v2.5 - ...
index.php + мод ...
Animation Effect ...
Доступа к БД Fire...
Error mod
CoolHints2k
Assembler. Учебни...
Архив программ
HtmlLerz PRO
Иллюстрированный ...
AboutSystem
Разработка клиент...
Карта сайта
Berg
Пример OpenGL гра...
Основы программир...
TelBook

Топ загрузок
Приложение Клие... 100774
Delphi 7 Enterp... 97833
Converter AMR<-... 20268
GPSS World Stud... 17014
Borland C++Buil... 14191
Borland Delphi ... 10291
Turbo Pascal fo... 7373
Калькулятор [Ис... 5984
Visual Studio 2... 5207
Microsoft SQL S... 3661
Случайные статьи
Подпрограмма Input...
Создаем многопоточ...
Классы профилей Ca...
Рост в женском пре...
RESET (СБРОСИТЬ)
Система SVR4/MP и ...
Задано натуральное...
Модуль CRT. Управл...
Дублирование по с...
Атака на отказ чер...
Процедур согласова...
Внедрение решения
Этап 2 - перенос о...
Информация о топол...
Правила для поиюче...
Язык С: операции н...
Расцепляйте модели...
Atari 5200 SuperSy...
AVL-деревья
Методы оптимизации...
Оптимизация кода
Игровые автоматы В...
Пример: приведем с...
ЦЕЛЬ: ХРАНЕНИЕ ИЗО...
Константы основных...
Статистика



Друзья сайта
Программы, игры


Полезно
В какую объединенную сеть входит классовая сеть? Суммирование маршрутов Занимают ли таблицы память маршрутизатора?