Вывод спрайтов на экран с маской.
© Сергей Сурков, г. Саянск, Иркутская область, 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 |
; |
возврат |
В заключение, хотелось бы отметить, что такой способ вывода шаблона на экран все же медленнее других, и, поэтому, он вряд ли подойдет для "стрелялок" с большим количеством стремительно движущихся объектов, но это им и не нужно - графика таких игр редко бывает настолько качественна, что нельзя обойтись другими способами печати.