ПЕЧАТЬ СПРАЙТОВ
(КООРДИНАТЫ ЗАДАНЫ
В ЗНАКОМЕСТАХ)
Теперь мы с Вами рассмотрим
простейшие процедуры для печати
спрайтов. Вся их простота сос-
тоит в том, что координаты печа-
ти задаются в знакоместах. Это
самые быстрые и в то же время не
такие уж и нужные процедуры, но
мы должны их рассмотреть, пос-
кольку они дают основу для всех
процедур печати спрайтов.
Рассмотрим основную структу-
ру данной процедуры. Из чего она
должна состоять: давайте посмот-
рим на данные, которые у нас
имеются к этому моменту: это
длина и высота спрайта, его ад-
рес в блоке и координаты печати.
Первым делом нам надо получить
адрес в экране, который бы соот-
ветствовал нашим координатам пе-
чати, а вычислить нам ее помо-
жет простенькая програмка:
140.
-------------------------------------
3(C) 1994 А.А.Иванов (ZX-Ревю N3 1994)
-------------------------------------
ADR LD A,L
AND 7
RRCA
RRCA
RRCA
ADD A,H
LD H,L
LD L,A
LD A,H
AND #18
OR #40
LD H,A
RET
2
Теперь абсолютно все данные у
нас есть и нам не остается ниче-
го, кроме как напечатать спрайт
на экране. У нас есть еще нес-
колько данных - это длина и вы-
сота спрайта. Вы не задумыва-
лись над тем, какое из этих чи-
сел важнее? Сейчас самый момент
об этом подумать, поскольку от
этого зависит скорость работы
Вашей процедуры. Если Вы взгля-
нете на данную ранее схему хра-
нения спрайта, то без труда смо-
жете ответить на этот вопрос.
Итак, главной здесь является вы-
сота спрайта, при помощи ее мы и
организуем первый цикл печати.
Теперь настал момент дать всю
процедуру полностью.
140.
SETSPR LD HL,(COORD) ;Заносим в HL координаты печати.
CALL ADR ;Вычисляем адрес в экране.
LD DE,(ADRSPR) ;В DE заносим адрес данных спрайта.
LD A,(LENHGT+1);В регистр A заносим высоту спрайта.
LD B,A ;В регистре B высота спрайта в пик-
;селях.
SETSPR1 PUSH HL ;Сохраняем адрес в экране.
LD A,(LENHGT) ;В регистр A заносим длину спрайта.
LD C,A ;В регистре C длина спрайта в знако-
;местах.
SETSPR2 LD A,(DE) ;Берем байт маски/спрайта.
IZM AND (HL) ;Накладываем по AND/OR на байт экра-
;на. Это зависит от того, что мы пе-
;чатаем - маску или спрайт.
LD (HL),A ;Переписываем экран.
INC DE ;Переходим к следующему байту маски -
;спрайта
INC HL ;Переходим к соседнему знакоместу эк-
;рана.
DEC C ;Уменьшаем длину спрайта.
JR NZ,SETSPR2 ;Если длина не равна 0, продолжаем
;печатать в длину.
POP HL ;Восстанавливаем адрес в экране.
CALL DOWN ;Переходим к следующей пиксельной ли-
;нии снизу.
DJNZ SETSPR1 ;Если высота не равна 0, продолжаем
;печатать.
RET
----------------------------------------
3(C) 1995 Старков Павел (ZX-Ревю N4 1995)
----------------------------------------
DOWN INC H
LD A,H
AND #07
RET NZ
LD A,L
ADD A,#20
LD L,A
RET C
LD A,H
SUB #08
LD H,A
RET
2
Теперь давайте попробуем на-
печатать на экране спрайт с мас-
кой из игры 3D BATMAN. Посмотри-
те, как будет выглядеть данная
программа:
140.
PRINSPR LD HL,(COORD) ;Берем координаты печати.
CALL ADR ;Вычисляем адрес в экране.
PUSH HL ;Сохраняем.
LD DE,(ADRSPR);В DE адрес спрайта в памяти.
CALL SETSPR ;Накладываем маску.
POP HL ;Восстанавливаем адрес в экране.
LD A,#B6 ;Изменяем команду AND (HL) на OR (HL).
LD (IZM),A
CALL SETSPR ;Печатаем спрайт.
LD A,#A6 ;Восстанавливаем команду AND (HL).
LD (IZM),A
RET
SETSPR LD A,(LENHGT+1)
LD B,A
SETSPR1 PUSH HL
LD A,(LENHGT)
LD C,A
SETSPR2 LD A,(DE)
IZM AND (HL)
LD (HL),A
INC DE
INC HL
DEC C
JR NZ,SETSPR2
POP HL
CALL DOWN
DJNZ SETSPR1
RET
2
Как видно из этой программы,
мы спрайт печатали как бы 2 ра-
за, что работает не совсем быс-
тро и говорит не в пользу подоб-
ному формату хранения.
Теперь давайте напечатаем
спрайт к программе ELEFANT-1:
140.PRINTSPR LD HL,(COORD)
CALL ADR
LD DE,SPRDATA
LD B,HGT
SETSPR1 PUSH HL
LD C,LEN
SETSPR2 LD A,(DE) ;Берем байт маски.
AND (HL) ;Объединяем его с байтом экрана.
INC DE ;Переходим к байту спрайта.
EX DE,HL ;Временно меняем HL и DE местами, так
;как OR (DE) нет.
OR (HL) ;Печатаем байт спрайта.
EX DE,HL ;Восстанавливаем DE.
LD (HL),A ;Перерисовываем экран.
INC DE
INC HL
DEC C
JR NZ,SETSPR2
POP HL
CALL DOWN
DJNZ SETSPR1
RET
2
Это самая быстрая из всех
приведенных до этого процедур
печати и наиболее эффективная.
Хочу заострить Ваше внимание на
следующем моменте - поскольку
байт маски и байт спрайта чере-
дуются между собой, то длина
спрайта может составлять не 3
знакоместа, а 6 (здесь 6 может
появиться, если программа, со-
здающая спрайты, не учитывает
этот момент), тогда Вам следует
перед занесением длины в регистр
C уменьшить ее в два раза коман-
дой SRL A. Особенностью дан-
ной программы является то, что
спрайт на экране появляется
плавно, поскольку при печати
спрайта предыдущими (особенно
первой) программами, если спрайт
довольно велик, можно увидеть
мерцание экрана.
Ну, а теперь нам осталось на-
печатать спрайт из программы
JACK THE NIPPER-2. Здесь тоже
стоит обратить Ваше внимание на
то, что в заголовке длина может
указываться неправильно: может
быть указана общая длина маски и
спрайта, и вам придется C так же
разделить на 2, как и в предыду-
щей процедуре:
140.
PRINTSPR LD HL,(COORD)
CALL ADR
LD DE,(ADRSPR)
LD A,(LENHGT+1)
LD B,A
SETSPR1 PUSH HL
LD A,(LENHGT)
LD C,A
SETSPR2 LD A,(DE) ;Печатаем линию маски.
AND (HL)
LD (HL),A
INC DE
INC HL
DEC C
JR NZ,SETSPR2
POP HL ;Восстанавливаем адрес в экране.
PUSH HL ;Вновь сохраняем его.
LD A,(LENHGT)
LD C,A
SETSPR3 LD A,(DE) ;Печатаем линию спрайта.
OR (HL)
LD (HL),A
INC DE
INC HL
DEC C
JR NZ,SETSPR3
POP HL
CALL DOWN
DJNZ SETSPR1
RET
2
Я не стал давать подробные
комментарии к этой процедуре,
она практически дублирует вто-
рую и отличается от нее лишь
расположением структурных эле-
ментов.
Предыдущие спрайты мы печата-
ли без атрибутов; чтобы напеча-
тать атрибуты спрайтов, надо до-
бавить к этим процедурам еще од-
ну небольшую. Для второй проце-
дуры ее надо оформить в виде
подпрограммы и вызывать через
CALL в конце головной программы.
Для печати атрибутов спрайта
нам нужен адрес в экране, кото-
рый мы получили после вызова
подпрограммы ADR, для этого HL
надо сохранить дважды, а не один
раз, как в предыдущих вариантах.
Для первой процедуры перед вызо-
вом печати атрибутов восстано-
вите адрес в экране, а первую
строку с меткой SETATTR в прог-
рамме печати атрибутов уберите.
Ну, а теперь сама процедура:
140.SETATTR POP HL ;Восстанавливаем адрес в экране.
----------------------------------------
3(C) 1994 В.В.Патрахин (ZX-Ревю N6 1994)
----------------------------------------
LD A,H ;Переводим адрес в экране в адрес в
;атрибутах.
RRCA
RRCA
RRCA
AND #03
OR #58
LD H,A
----------------------------------------
LD A,(LENHGT+1)
LD B,A ;В регистре B высота в пикселях.
LD A,#04
SRL B ;Делим на 2.
JR NC,R1 ;Если нацело, переход.
LD (IZM),A ;В А код команды INC B, заносим его в
;переменную.
R1 SRL B ;Делим на #04.
JR NC,R2
LD (IZM),A
R2 SRL B ;На #08.
JR NC,IZM
LD (IZM),A
IZM NOP ;Если где-либо делилось не нацело,
;здесь будет команда INC B.
SETATTR1 PUSH HL ;Сохраняем адрес в экране.
LD A,(LENHGT)
LD C,A ;Длина спрайта (для JACK THE NIPPER-2
;надо после этой команды добавить SRL
;C, тоже и для ELEFANT-1).
SETATTR2 LD A,(DE) ;Переносим атрибуты в экран.
LD (HL),A
INC DE
INC HL
DEC C
JR NZ,SETATTR2
POP HL
PUSH DE
LD DE,#0020
ADD HL,DE
POP DE
DJNZ SETATTR1
RET
2
Для спрайтов в формате ELE-
FANT-1 и JACK NIPPER-2 длину
также стоит разделить на 2 (ес-
ли, конечно, Вам пришлось ее де-
лить при печати спрайтов).
Многие могут заметить стран-
ную конструкцию в том месте, где
мы делили высоту спрайта на 8. Я
вынужден пояснить эту ситуацию.
Если Ваш спрайт в высоту кратен
знакоместу (делится нацело на
8), то эту конструкцию можно за-
менить на три команды SRL B; но
вот в том случае, если спрайт в
высоту не кратен знакоместу, мо-
гут возникнуть спорные ситуации:
ПРИМЕР: высота составила 9
пикселей. При делении на два, мы
получим 4, на 4 - 2, на 8 - 1,
но ведь спрайт в атрибутах зани-
мает 2 знакоместа (9 линия нахо-
дится в следующем знакоместе), и
окрашены атрибутами будут только
первые 8 линий. Вот для этого и
нужна подобная конструкция.
Ну, вот мы с Вами и напечата-
ли все основные форматы спрай-
тов в знакоместах и нам стоит
перейти к печати спрайтов по
пикселям.