Вывод спрайтов на экран с маской.
© Сергей Сурков, г. Саянск, Иркутская область, 1994.
В книге "Прикладная графика" ИНФОРКОМ затронул одну из самых важных проблем, возникающих при написании игровых программ - это вывод или печать шаблона изображения на экран. В этом издании предложены два способа печати. Это печать командой LD, непосредственно выводя шаблон поверх фонового изображения и печать с помощью команды XOR, смешивая шаблон и фоновую картинку. Оба способа имеют каждый свои недостатки, заметные при качественной графике фонового изображения. В первом случае шаблон "выкусывает" прямоугольник фона в зависимости от своего формата, а во втором - при наложении на фон шаблона происходит частичное искажение последнего.
Тем не менее, существует способ вывода шаблона на экран, который не искажает фоновую картинку и выводимый шаблон. При использовании этого способа, выводимый на экран шаблон, попадая на изображение фона, отделяется от последнего "оболочкой" шириной в один пиксел. Чтобы нагляднее это представить, достаточно взглянуть на главного героя известной игры DIZZY.
Прежде, чем переходить к описанию метода, необходимо сказать несколько слов о формате хранения шаблона и так называемой маски, имеющей следующий вид:
1. Размеры маски те же, что и шаблон.
2. Изображение маски должно из себя представлять инвертированный силуэт шаблона с отступом во все стороны в одну точку.
Шаблон и маску необходимо подготовить в графическом редакторе или генераторе спрайтов и упаковать их в такой формат:


Принцип действия программы в деталях отличается от описанного. Сделано это для ускорения процедуры. Программа выбирает байт окна экрана, накладывает на него
Обратите внимание на то, что шаблон и маска хранятся в несколько отличном от предложенного "Прикладной графикой" формате - шаблон и маска хранятся в виде последовательности линий изображения, а не знакомест.
Теперь о сути метода. Прежде всего, используя команду AND процессора необходимо наложить маску на то окно экрана, где будет отпечатан шаблон. В результате получится окно с пустым силуэтом шаблона и неискаженной фоновой картинкой по краям силуэта (см. рисунок).
Затем осталось только впечатать шаблон в силуэт. Это позволяет сделать команда OR (см. рисунок).
соответствующий байт маски, затем - байт шаблона, заносит полученное в буфер и переходит к следующему байту. После обработки всего окна программа выводит содержимое буфера на экран.
ORG 25000
COORD DEFW 0 /Координаты окна.
SPRITE DEFW 0 /Адрес начала маски и шаблона.
SRE DEFW 0 /Размер маски (шаблона), который
/программа выбирает из /информации о печатаемом шаблоне. BUFFER DEFW 0 /Адрес буфера, куда копируется окно.
Первая часть программы - расчёт адреса по координатам. Подробное описание расчёта можно найти в первой книге сериала "Персональный компьютер ZX-SPECTRUM. Элементарная графика".
процессора
|
LD |
DE, (COORD) | ||
|
LD |
A, E | ||
|
AND |
#18 | ||
|
OR |
#40 | ||
|
LD |
H, A | ||
|
LD |
A, E | ||
|
AND |
#7 | ||
|
OR |
A | ||
|
RRA | |||
|
RRA | |||
|
RRA | |||
|
RRA | |||
|
ADD |
A, D | ||
|
LD |
L, A | ||
|
PUSH |
IX |
На стеке запоминаются индексные | |
|
PUSH |
IY |
регистры, это необходимо для | |
|
успешного возврата в BASIC. | |||
|
PUSH |
HL |
2 раза на стеке запоминается | |
|
PUSH |
HL |
адрес в экране, рассчитанный в | |
|
предыдущей части программы. | |||
|
LD |
HL,(SPRITE) | ||
|
INC |
HL |
HL устанавливается на байт | |
|
INC |
HL |
высоты. | |
|
LD |
A,(HL) |
Высоту - в SIZE. | |
|
LD |
(SIZE),A | ||
|
INC |
HL |
HL устанавливается на байт длины. | |
|
LD |
A,(HL) |
; |
Длину - в (SIZE+1). |
|
LD |
(SIZE+1),A | ||
|
LD |
HL,(SPRITE) | ||
|
LD |
E,(HL) | ||
|
INC |
HL |
; |
HL настраивается на начало |
|
LD |
D,(HL) |
; |
шаблона. |
|
DEC |
HL | ||
|
ADD |
HL, DE | ||
|
PUSH |
HL |
; |
Это аналог команды LD IX,HL, |
|
POP |
IX |
; |
которой нет в системе команд |
|
LD |
HL,(SPRITE) | ||
|
LD |
DE, L |
; |
Здесь DE настраивается на |
|
ADD |
HL, DE |
; |
начало маски. |
|
EX |
DE, HL | ||
|
LD |
IY, (BUFFER) | ||
|
POP |
HL |
К этому моменту регистры настраиваются таким образом: DE - адрес начала маски, HL -адрес в экране, IX - адрес начала шаблона, IY -адрес начала буфера.
Следующая часть программы обрабатывает окно и помещает его в буфер.
|
LD |
A, (SIZE) |
; В - счетчик | |
|
LD |
B, A |
; рядов. | |
|
STR1 |
PUSH |
BC | |
|
PUSH |
HL | ||
|
LD |
B, 8 |
; В - счётчик линий в ряду. | |
|
PUSH |
HL | ||
|
LD |
A, (SIZE+1) |
; В регистре В устанавливается | |
|
LD |
B, A |
; счетчик столбцов. | |
|
COL1 |
LD |
A,(HL) |
; Выбран байт из окна. |
|
EX |
DE, HL |
; Накладывается байт маски на | |
|
AND |
(HL) |
; байт окна. | |
|
EX |
DE, HL | ||
|
OR |
(IX+O) |
; Накладывается байт шаблона. | |
|
LD |
(IY+O),A |
; Полученный байт засылается в буфер. | |
|
INC |
HL |
; Переход к следующим байтам | |
|
INC |
DE |
; окна экрана, маски, шаблона | |
|
INC |
IX |
; и буфера. | |
|
INC |
IY | ||
|
DJNZ |
COL1 |
; Конец цикла по столбцам. | |
|
POP |
HL | ||
|
POP |
BC | ||
|
INC |
H |
; Переход на следующую линию. | |
|
DJNZ |
LINE1 |
; Конец цикла по линиям. | |
|
POP |
HL | ||
|
POP |
BC | ||
|
LD |
A, #20 |
; Переход на следующий | |
|
ADD |
A, L |
; ряд. | |
|
LD |
L, A | ||
|
JR |
NC,PASS1 |
; Корректировка номера | |
|
LD |
A, 8 |
; сегмента. | |
|
ADD |
A, H | ||
|
LD |
H, A | ||
|
PASS1 |
DJNZ |
STR1 |
; Конец цикла по рядам. |
|
Итак, |
в буфере сейчас окно с впечатанным в него шаблоном, осталось только вывести его | ||
|
на экран. | |||
|
LD |
DE,(BUFFER) | ||
|
POP |
HL |
; в HL - адрес в экране | |
|
LD |
A, (SIZE) |
; В - счетчик рядов | |
|
LD |
B, A | ||
|
STR2 |
PUSH |
BC | |
|
PUSH |
HL | ||
|
LD |
B, 8 | ||
|
LINE2 |
PUSH |
BC |
; В - счётчик линий |
|
PUSH |
HL | ||
|
LD |
A, (SIZE+1) |
; В - счетчик | |
|
LD |
B, A |
; столбцов | |
|
COL2 |
LD |
A, (DE) |
; пересылается байт буфера в байт |
|
LD |
(HL),A |
; экрана | |
|
INC |
DE |
; переход к следующим байтам | |
|
INC |
HL | ||
|
DJNZ |
COL-2 |
; конец цикла по столбцам | |
|
POP |
HL | ||
|
POP BC | |||
|
INC H | |||
|
DJNZ LINE2 |
; |
переход на следующую строку | |
|
POP HL |
; |
конец цикла по линиям | |
|
POP BC | |||
|
LD A,32 |
; |
переход на следующий ряд | |
|
ADD A, L | |||
|
LD L, A | |||
|
JR NC, PASS2 |
; |
корректировка | |
|
LD A,8 |
; |
номера | |
|
ADD A, M |
; |
сегмента | |
|
LD H, A | |||
|
PASS2 |
DJNZ STR2 |
; |
конец цикла по рядам |
|
POP IY |
; |
индексные регистры | |
|
POP IX |
; |
восстанавливаются со стека | |
|
RET |
; |
возврат |
В заключение, хотелось бы отметить, что такой способ вывода шаблона на экран все же медленнее других, и, поэтому, он вряд ли подойдет для "стрелялок" с большим количеством стремительно движущихся объектов, но это им и не нужно - графика таких игр редко бывает настолько качественна, что нельзя обойтись другими способами печати.