Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Листинг 17.4. Оптимизированная подпрограмма (BLIT.ASM).






ideal

model compact, с

p286

dataseg

VIEW_WIDTH equ 320

VIEW_HEIGHT equ 100

TRANSPARENT equ 0

global MemBuf: dword

.codeseg

public OpaqueBIt public TransparentBIt

;

; Эта процедура копирует битовую карту в MemBuf. Кроме этого, она

; может скроллировать левую и правую части битового образа

; в зависимости от значения ScrollSplit;

proc OpaqueBlt

ARG Bitmap: dword, StartY: word, Height: word, ScrollSplit: word

USES si, di

les di, [MemBuf]; получить указатель на буфер памяти

mov ax, [StartY]; получить начальную Y-координату

mov bx, ax; скопировать

sal ax, 6; умножить на 64

sal bx, 8; умножить на 256

add ax, bx; результат равен умножению на 320

add di, ax; вычислить смещение внутри MemBuf

mov bx, [Height]; получить высоту битовой карты

mov dx, [ScrollSplit]; получить длину правой половины

push ds; сохранить сегмент данных

lds si, [Bitmap]; получить полный указатель на битовую карту

mov ax, VIEW_WIDTH; получить ширину экрана

sub ax, dx; вычислить длину левой половины

cld; обрабатывать данные от младших адресов к старшим

@@lоор01: add di, dx; вычислить начальную позицию

mov сх, ах; получить длину левой половины

shr cx, 1; разделить на 2 (поскольку выводим по 2 байта):

rep movsw; нарисовать правую половину карты

jnc short @@skip01; пропустить, если выполнено

movsb; дорисовать последний пиксель

@@skip01:

sub di, VIEW_WIDTH; получить ширину выводимого окна

mov cx, dx; получить длину правой половины

shr сх, 1; разделить на 2

rep movsw; нарисовать правую половину карты

jnc short @@skip02; пропустить, если выполнено

movsb; перейти к последнему пикселю

@@skip02:

add di, ax; получить ширину следующей строки вывода

dec bx; уменьшить счетчик столбцов

jnz short @@loop01; повторить

pop ds; восстановить сегмент данных

ret; завершить

endp OpaqueBlt

;

; Эта процедура копирует битовую карту в MemBuf. Функция не рисует

; пиксель, если его цвет равен " прозрачному"

;

proc TransparentBIt

ARG Bitmap: dword, StartY: word, Height: word, ScrollSplit: word USES si, di

les di, [MemBuf]; получить указатель на память

mov ax, [StartY]; получить начальную Y-координату

mov ex, ax; получить копию

sal ax, б; умножить на 64

sal ex, 8; умножить 256

add ax, ex; результат эквивалентен умножению на 320

add di, ax; прибавить смещение к MemBuf

mov dx, [ScrollSplit]; получить ширину левой половины

; изображения

mov bx, VIEW_WIDTH; общая ширина изображений

sub bx, dx; вычислить ширину правой половины

push ds; сохрани, ть сегмент, данных

lds si, [Bitmap]; получить полный указатель на битовый образ

@@lоор01;

add di, dx; вычислить начальную позицию экрана

mov сх, Ьх; получить ширину правой половины;

; Нарисовать правую половину;

@@lоор02;

mov аl, [si]; получить пиксель карты

inc si; следующий пиксель

cmp al, TRANSPARENT; " прозрачный"?

je short @@skip01;...пропустить, если да

mov [es: di], al; иначе, нарисовать его

@@skip01:

inc di; указать на следующий байт MemBuf

dec ex; уменьшить счетчик

jnz short @@loop02

sub di, VIEW_WIDTH; получить ширину выводимого окна

mov cx, dx; получить ширину правой половины

; Нарисовать левую половину

@@lоор03:

mov ai, [si]; получить пиксель карты

inc si; следующий пиксель

cmp al, TRANSPARENT; " прозрачный"?

je short @@skip02;...пропустить, если да

mov [es: di], al; иначе, нарисовать его

@@skip02;

inc di; перейти к следующему байту видеобуфера

dec ex; уменьшить счетчик

jnz short @@loop03; повторить цикл, пока не сделаем все

add di, bx; добавить значение ширины правой

части изображения

dec [Height]; уменьшить счетчик колонок

jnz short @@loop01; повторить еще раз

pop ds; восстановить сегмент данных

ret; закончить

endp TransparentBlt

end

Смещение мозаичных изображений

Одной из проблем, возникающей при выводе повторяющегося смещаемого изображения, является большой объем памяти, требуемый для размещения битовых карт. Практически, размер никакого отдельного изображения в D0b не может превышать 64К. Этого достаточно для изображений площадью 320х200 или 640х100 пикселей (как я уже говорил, в режиме 13h каждый пиксель занимает один байт). Но даже если бы вам и представилась возможность иметь изображения больших размеров, вы все равно очень скоро исчерпали бы память, поскольку в вашем распоряжении имеется максимум 640К.

Не волнуйтесь: мы не будем здесь углубляться в изучение 16-битного кода, расширенной памяти или сегментации. Скажу только, что ограничения использования памяти неизменно сопутствуют старому доброму реальному режиму работы микропроцессора. Когда-нибудь это может измениться, но сейчас мы вынуждены примириться с таким положением вещей.

Существует довольно умное решение проблемы недостатка памяти — это применение мозаичных изображений. Вместо использования цельного образа, вы создаете виртуальную битовую карту, составленную из множества меньших картинок, как. из кирпичиков. Эти «кирпичики» могут быть рассмотрены как блоки здания, из которых составляется большее изображение. В основе этого технического приема лежит составление специальной справочной таблицы. Обычно она представляет собой массив, содержащий данные о расположении маленьких частей внутри большого виртуального изображения. Справочная таблица не требует много памяти (приблизительно один или два байта на элемент) и поэтому может иметь практически любую протяженность.

Представьте себе смещающееся виртуальное изображение, состоящее из 5400х12 «кирпичиков», каждый из которых имеет размер всего 16х16 пикселей. Это означает, что площадь виртуального изображения составит 86400х192 пикселя, что намного больше, максимальных допустимых размеров любого отдельного изображения.

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

По практическим соображениям кирпичики должны иметь ширину, равную степени числа 2. То есть их размер по горизонтали должен составлять 2, 4, 16 и так далее вплоть до 320 пикселей в режиме 13h. Важность этих ограничений вы поймете позже.

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

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

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

Это свойство несколько упрощает построение мозаичного изображения. Таким образом, этот процесс состоит из трех шагов:

1. Рисование первого (возможно, не полностью выведенного) «кирпичика»;

2. Рисование нескольких (полностью выведенных) «кирпичиков»;

3. Рисование последнего (возможно, не полностью выведенного) «кирпичика».

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

Программа из Листинга 17.6 (TILES.С) демонстрирует моделирование мозаичных слоев. Самые ближние слои состоят из нескольких «кирпичиков». Определение виртуального изображения сохранено в файле TILEMAP.DAT, который представляет собой обычный ASCII-файл и обрабатывается во время инициализации. Цифры в файле представляют собой закодированные имена PCX-файлов. Обратите внимание, что код 0 зарезервирован для «прозрачного кирпичика». Рисунок 17.3 показывает небольшой пример мозаичного изображения.

Важным отличием между этой программой и демонстрационной программой двойного параллакса в Листинге 17.3 является добавление функции DrawTile().

Эта подпрограмма изображает «кирпичик» в указанном месте экрана. Два аргумента offset и width определяют соответственно начальный столбец и ширину для вывода не полностью помещающихся на экране «кирпичиков».

Для частично выведенных кирпичиков:

§ offset -первый столбец, в котором будет нарисован «кирпичик»;

§ width - некоторое значение меньше ширины «кирпичика».

Для полностью выведенных «кирпичиков»:

§ offset - 0;

§ width - определяет ширину «кирпичика».

Программа из Листинга 17.6 также использует курсорные клавиши для управления движением и клавишу Esc для выхода. В демонстрационной программе на переднем плане появляется стена дома, составленная из отдельных «кирпичиков», а за ней видны хорошо известная горная гряда и линия неба на самом дальнем плане. Выполняется эта программа немного медленнее из-за использования в ней функции вывода мозаичного изображения, но только на пару кадров в секунду. Листинг 17.5 содержит файл заголовка для программы Построения мозаичного изображения, представленной в Листинге 17.6. В заголовке определены константы и прототипы функций для демонстрационной Программы.






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.