ЧИТАТЕЛЬ- ЧИТАТЕЛЮ
Графика вашего компьютера © Вадим Бодров, г. Уфа, 1995.
1.
Среди читателей "ZX-РЕВЮ" обязательно должен существовать довольно большой процент начинающих программистов. Это те люди, которые еще недостаточно освоили программирование, но горят желанием написать что-нибудь свое. Например, задумал человек написать RPG (хотя бы на Бейсике), но ему не хватает опыта для создания звуковых или видео-эффектов, вывода графических изображений... Если из-за этих "мелочей" он отложит свою идею до следующего раза, то потом уже вряд ли к ней вернется. К счастью большинство не останавливается на этих проблемах и идет дальше, пытаясь найти им свои собственные решения. Все это прекрасно, но здесь есть одно "но" - зачем изобретать велосипед, если уже существует множество способов и алгоритмов, которые были разработаны за долгие годы существования SPECCY! В свое время я и сам занимался подобными "изобретениями", хотя стоит отметить, что это пошло мне только на пользу.
Сейчас очень много полезной информации по классическим алгоритмам на АССЕМБЛЕРе можно найти на страницах журнала, который Вы держите в руках. Достаточно взглянуть хотя бы на такие разделы, как "ЭТЮДЫ", "ЧИТАТЕЛЬ-ЧИТАТЕЛЮ", "ПРОФЕССИОНАЛЬНЫЙ ПОДХОД" и др. Известно, что главным вопросом для начинающих программистов является МАШИННАЯ ГРАФИКА. Море информации по данному вопросу можно найти в книгах ИНФОРКОМа из сериала о графике для ZX-SPECTRUM, но мало кто из начинающих программистов знает, что создавать спрайты и выводить их на экран можно вообще не используя АССЕМБЛЕР. Я говорю о блочной графике, сущность которой заключается в простом печатании блоков размером 8X8, используя только оператор PRINT. Изображение на экране Вашего компьютера строится именно из таких вот элементарных "квадратиков" размером в один стандартный символ. Этот способ напоминает использование UDG-символов, но имеет больше возможностей для использования.
Для тех, кто еще смутно понимает достоинства данного метода, я предлагаю набрать и запустить БЕЙСИК-программу EXAMPLE. Пусть Вас не смущает её длина, так как основной объем занимают DATA-строки, в которых находится информация о пикселях спрайтов блочной графики. Данный факт отнюдь не означает, что и Вашей программе данные о спрайтах тоже должны храниться подобным образом. Все операции по созданию и хранению набора спрайтов возьмет на себя программа SIMPLY SCAN, но о ней мы поговорим позже.
1 REM EXAMPLE
2 DATA 1,1,0,0,0,0,12 4,254,255,147,0,0,0,0,0,0,0,0,3,3,3,7,55,247,247,243,0,17,8 5,17,255,255,12 5,131,239,12 8,12 8,12 8,192,216,222,222,158,3,0,0,0,1,1,3,3,255,254,0,0, 199,69,239,239,12 8,0,0,0,0,0,12 8,12 8
3 DATA 0,0,0,0,0,0,0,1,0,0,0,0,0,12 4,254,255,0,0,0,0,0,0,0,0,1,3,99,243,247,119, 7,7,147,17,85,17,255,255,12 5,131,0,12 8,140,158,222,220,192,192,3,3,0,0,1,1,3,3,239,25 5,254,0,199,69,239,239,12 8,12 8,0,0,0,0,12 8,12 8
4 DATA 0,0,0,0,0,1,3,3,0,0,0,0,248,2 52,254,242,0,0,0,0,0,0,0,0,7,7,7,15,15,15,7, 7,227,235,227,241,254,223,239,247,0,0,0,12 8,12 8,0,0,0,7,1,0,7,15,15,7,1,248,2 52,0,16, 59,255,222,220,0,0,0,0,0,0,0,0
5 DATA 0,0,0,0,1,3,3,7,0,0,0,248,2 52,254,242,22 7,0,0,0,0,0,0,0,0,7,7,15,15,15,7, 7,7,235,227,255,183,12 3,12 0,12 3,183,0,0,12 8,12 8,12 8,0,0,0,1,0,0,1,1,1,1,0,204,0,0,176 ,2 52,246,246,0,0,0,0,0,0,0,0,0
6 DATA 0,0,0,0,1,3,3,7,0,0,0,248,2 52,254,242,22 7,0,0,0,0,0,0,0,0,7,7,12,11,7,7,7 ,0,235,227,12 7,255,215,184,12 7,255,0,0,12 8,12 8,12 8,0,0,0,1,0,7,15,15,7,1,0,2 52,0,16,5 9,255,222,220,0,0,0,0,0,0,0,0,0
7 DATA 0,2,7,71,215,255,191,12 7,184,81,240,12 5,250,117,242,244,52,106,214,233,15 4,254,249,255,221,12 7,167,222,45,159,137,4,105,181,43,214,73,161,64,32,187,255,255,23 1,186,4,26
8 RESTORE : FOR i=30006 TO 30406: READ a: POKE i,a: NEXT i
9 LET DX=3: LET DY=3: LET SZ=DX*DY*8: LET a$="": FOR i=32 TO (31+SZ/8): LET a$=a$+CHR$ i: NEXT i
10 INK 6: BRIGHT 0: PAPER 0: BORDER 0: CLS : LET adr=30000
11 LET n=5: LET y=18: OVER 1: FOR x=1 TO 3 0 STEP 3: GO SUB 19: NEXT x: OVER 0
12 BRIGHT 1: LET y=15: LET x=1: INK 7
13 FOR I=1 TO 20: PLOT INK (RND*4+3);(RND*255),(RND*75+100): NEXT I: GO SUB 18
14 LET n=2: GO SUB 19: BEEP .005,50: PAUSE 4: LET x=x+1: LET n=3: GO SUB 19: BEEP .005,50: PAUSE 4: LET x=x+1: LET n=4: GO SUB 19: BEEP .005,50: PAUSE 4: LET x=x+1: IF (x/7)=INT (x/7) THEN GO SUB 18
15 IF x>26 THEN GO SUB 18: STOP
16 GO TO 14
17 STOP
18 FOR i=1 TO 10: LET n=0: GO SUB 19: LET n=1: GO SUB 19: NEXT i: RETURN
19 LET k=n*sz+adr: LET k1=INT (k/256): POKE 23606,(K-K1*256): POKE 23607,(k1-1)
20 LET m=1: FOR w=y TO y+dy-1: PRINT AT w,x-1;"©";a$(m TO m+dx-1);: LET m=m+dx: NEXT w: POKE 23606,0: POKE 23607,60: RETURN
Если Вы не поленились и набрали приведенную выше программу, то можете запустить её прямой командой RUN, и перед Вами предстанет один из самых популярных компьютерных героев. Его перемещения по экрану пока ещё нельзя назвать элегантными, но это уже что-то. Для ускорения работы программы, откомпилируйте её TOBOS-ом, и результат Вас не разочарует - резвости нашего персонажа позавидует даже его фирменный брат.
Строки 2-7 содержат информацию о спрайтах, которая в строке 8 копируется в ОЗУ с адреса 30000 по адрес 30431. Так как размер каждого из шести спрайтов равен 3х3 знакоместа, то общий объем блока равен 6*3*3*8=432 байта. Для краткости в блоке DATA-строк опущены нули, которые располагаются в его начале и в конце. Я советую Вам выгрузить полученный набор спрайтов на ленту, командой SAVE "exam.BLK" CODE 30000,432 он нам ещё пригодится. В строке 9 устанавливаются значения переменных для подпрограммы вывода. Строки 11-18 осуществляют анимацию. Главным блоком программы являются строки 19-20. Здесь расположена сама подпрограмма вывода спрайта на экран. Ее действие основано на простом впечатывании оператором PRINT последовательности символов: пробел,!,",#,$, %,& и т.д. Если при этом в системной переменной CHARS установлен адрес расположения спрайта в ОЗУ, но на экране мы увидим желаемое изображение. Расчетом и установкой нужных параметров в CHARS тоже занимается данная подпрограмма. Знак "©" в операторе PRINT играет роль пробела, т.к. его изображение не определено в строках DATA.
Из-за этого, кстати, могут наблюдаться помехи в виде дорисовки спрайтов в том случае, если память Вашего компьютера не очищена, а такое очень вероятно, если Вы работаете в TR-DOS через "boot". Поэтому все же можно порекомендовать зарезервировать место для пробела - надо-то всего 8 байтов. Зато в будущем голова не будет болеть. Сдвиньте CHARS на 8 байтов и печатайте "значащие" символы спрайта не с кода 32 ("пробел"), а с кода 33 ("!"). А вместо кода 127 ("копирайт") традиционно используйте "пробел".
шестнадцатеричный дамп кодового блока "exam.BLK". |
|
|
7530 |
00 |
00 |
00 |
00 |
00 |
00 |
01 |
01 |
A7 |
7538 |
00 |
00 |
00 |
00 |
7C |
FE |
FF |
93 |
B9 |
7540 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
B5 |
7548 |
03 |
03 |
03 |
07 |
37 |
F7 |
F7 |
F3 |
E5 |
7550 |
11 |
55 |
11 |
FF |
FF |
7D |
83 |
EF |
29 |
7558 |
80 |
80 |
80 |
C0 |
D8 |
DE |
DE |
9E |
3F |
7560 |
03 |
00 |
00 |
00 |
01 |
01 |
03 |
03 |
E0 |
7568 |
FF |
FE |
00 |
00 |
C7 |
45 |
EF |
EF |
C4 |
7570 |
80 |
00 |
00 |
00 |
00 |
00 |
80 |
80 |
65 |
7578 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
01 |
EE |
7580 |
00 |
00 |
00 |
00 |
00 |
7C |
FE |
FF |
6E |
7588 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
FD |
7590 |
01 |
03 |
63 |
F3 |
F7 |
77 |
07 |
07 |
DB |
7598 |
93 |
11 |
55 |
11 |
FF |
FF |
7D |
83 |
15 |
7 5A0 |
00 |
80 |
8C |
9E |
DE |
DC |
C0 |
C0 |
F9 |
7 5A8 |
03 |
03 |
00 |
00 |
01 |
01 |
03 |
03 |
2B |
75B0 |
EF |
FF |
FE |
00 |
C7 |
45 |
EF |
EF |
FB |
75B8 |
80 |
80 |
00 |
00 |
00 |
00 |
80 |
80 |
2D |
75C0 |
00 |
00 |
00 |
00 |
00 |
01 |
03 |
03 |
3C |
75C8 |
00 |
00 |
00 |
00 |
F8 |
FC |
FE |
F2 |
21 |
75D0 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
45 |
75D8 |
07 |
07 |
07 |
0F |
0F |
0F |
07 |
07 |
9D |
75E0 |
E3 |
EB |
E3 |
F1 |
FE |
DF |
EF |
F7 |
BA |
75E8 |
00 |
00 |
00 |
80 |
80 |
00 |
00 |
00 |
5D |
75F0 |
07 |
01 |
00 |
07 |
0F |
0F |
07 |
01 |
9A |
75F8 |
F8 |
FC |
00 |
10 |
3B |
FF |
DE |
DC |
65 |
7600 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
76 |
7608 |
00 |
00 |
00 |
00 |
01 |
03 |
03 |
07 |
8C |
7610 |
00 |
00 |
00 |
F8 |
FC |
FE |
F2 |
E3 |
4D |
7618 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
8E |
7620 |
07 |
07 |
0F |
0F |
0F |
07 |
07 |
07 |
E6 |
7628 |
EB |
E3 |
FF |
B7 |
7B |
78 |
7B |
B7 |
47 |
7630 |
00 |
00 |
80 |
80 |
80 |
00 |
00 |
00 |
26 |
7638 |
01 |
00 |
00 |
01 |
01 |
01 |
01 |
00 |
B3 |
7640 |
CC |
00 |
00 |
B0 |
FC |
F6 |
F6 |
00 |
1A |
7648 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
BE |
7650 |
00 |
00 |
00 |
00 |
01 |
03 |
03 |
07 |
D4 |
7658 |
00 |
00 |
00 |
F8 |
FC |
FE |
F2 |
E3 |
95 |
7660 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
D6 |
7668 |
07 |
07 |
0C |
0B |
07 |
07 |
07 |
00 |
18 |
7670 |
EB |
E3 |
7F |
FF |
D7 |
B8 |
7F |
FF |
3F |
7678 |
00 |
00 |
80 |
80 |
80 |
00 |
00 |
00 |
6E |
7680 |
01 |
00 |
07 |
0F |
0F |
07 |
01 |
00 |
24 |
7688 |
FC |
00 |
10 |
3B |
FF |
DE |
DC |
00 |
FE |
7690 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
06 |
7698 |
00 |
02 |
07 |
47 |
D7 |
FF |
BF |
7F |
72 |
7 6A0 |
B8 |
51 |
F0 |
7D |
FA |
75 |
F2 |
F4 |
E1 |
7 6A8 |
34 |
6A |
D6 |
E9 |
9A |
FE |
F9 |
FF |
0B |
76B0 |
DD |
7F |
A7 |
DE |
2D |
9F |
89 |
04 |
60 |
76B8 |
69 |
B5 |
2B |
D6 |
49 |
A1 |
40 |
20 |
97 |
76C0 |
BB |
FF |
FF |
E7 |
BA |
04 |
1A |
00 |
AE |
76C8 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
3E |
76D0 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
46 |
76D8 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
4E |
Создание набора спрайтов поручим специальной программе SIMPLY SCAN. Она позволяет загружать рисунки с диска (магнитофона) и вырезать из нее спрайты, размер которых должен быть постоянным (для каждого отдельного спрайта) и задаваться в начале программы (X SIZE, Y SIZE), но еще перед этим необходимо задать адрес начала расположения набора спрайтов в ОЗУ. Полученный блок можно сохранить на магнитном носителе и использовать в собственных программах.
1 BORDER 7: PAPER 7: INK 0: CLEAR 29999: PRINT "SIMPLY SCAN"'"(C) Vadim Bodrov, Ufa, 91/95"'"SPECIAL FOR ~ZX-REVIEW~"
2 INPUT "SPRITE ADDRESS ? ";ADR: IF ADR<30000 OR ADR>65527 THEN GO TO 2
3 INPUT "X SIZE OF SPRITE ? ";DX
4 INPUT "Y SIZE OF SPRITE ? ";DY
5 LET HMS=0: LET CADR=ADR: LET SZ=DX*DY*8
6 INK 8: BRIGHT 8: PAPER 8: FLASH 8: LET X=0: LET Y=0: GO SUB 17
7 PRINT AT Y,X; OVER 1;"80V ";: GO SUB 15: IF A$="1" THEN GO TO 6
8 PRINT AT Y,X; OVER 1;"80V ";
9 IF A$="0" AND CADR+DX*DY*8<=65535 THEN FOR K=Y TO Y+DY-1: LET SADR=16384+2048*INT (K/8)+32*(K-8*INT (K/8)): FOR N=X TO X+DX-1: FOR M=0 TO 1792 STEP 256: POKE CADR,PEEK (SADR+M+N): POKE (SADR+M+N),255: LET CADR=CADR+1: NEXT M: NEXT N: NEXT K: LET HMS=HMS+1: GO TO 7
10 LET X=X+(A$="7" AND X<31)-(A$="6" AND X>0): LET Y=Y+(A$="8" AND Y<21)-(A$="9" AND Y>0)
11 IF A$="2" AND HMS>0 THEN GO SUB 19: RUN
12 GO TO 7
13 PRINT #1;AT 0,0;"1-LOAD SCREEN 2-SAVE SPRITES"; INVERSE 1;;"0-PUT SPRITE SINCLAIR2-MOVE";
14 RETURN
15 PAUSE 1: LET A$=INKEY$: IF A$="" THEN GO TO 15
16 BEEP .1,10: RETURN
17 INPUT "NAME OF SCREEN ? ";N$: CLS : RANDOMIZE USR 15619: REM : LOAD N$ CODE 16384
18 GO SUB 13: RETURN
19 CLS : PRINT "START SPRITE ADDRESS: ";ADR
2 0 PRINT '"LENGHT OF SET SPRITES: ";CADR-ADR
21 PRINT '"TOTAL NUMBER OF SPRITES: ";HMS
22 PRINT '"SIZE OF STANDARD SPRITE: ";DX;"X";DY
23 INPUT "NAME OF SET SPRITES? ";N$: RANDOMIZE USR 15619: REM : SAVE N$ CODE ADR,(CADR-ADR)
24 PRINT '"MORE (Y/N) ? ": GO SUB 15: IF A$="N" OR A$="n" THEN STOP
Замечу, что такую раскладку спрайтов можно наблюдать и в фирменных программах (HEART BROKEN, AVENGER, RANARAMA, JET SET WILLY, STALINGRAD...). Надо лишь помнить, что размеры спрайтов должны быть ограничены размерами доступного символьного набора, т.е. DX*DY<= 96.
Проверка столкновения спрайтов производится очень просто. Предположим, что Вам нужно проверить, находится ли спрайт с номером N в заданном знакоместе X,Y. Для этого нужно рассчитать значение системной переменной CHARS, соответствующее проверяемому спрайту. Это делается следующим образом: LET K=ADR+SZ*N: LET K1=INT(K/256): POKE 23606,(K-K1*256): POKE 23607,(K1-6)
Здесь ADR - начало области информации о спрайтах; SZ=DX*DY*8 размер стандартного спрайта в байтах; N - номер проверяемого спрайта.
Теперь остается только дать команду БЕЙСИКа: LET A$=SCREEN$ (Y,X+1). Если значение переменной A$ будет равно символу "!", то значит, искомый спрайт действительно содержится в данном знакоместе.
Анимация может проводиться и с накладкой изображений на фон. Это осуществляется печатью в режиме OVER 1 (аналогично логической операции XOR).
2.
Метод вывода графической информации на экран средствами стандартного БЕЙСИКа, который был описан в предыдущей главе практически не годится для создания игр класса ARCADE и ACTION (но справедливости ради замечу, что в игре "PRESIDENT'S GUARD" использован именно этот приём). Зато его прекрасно можно использовать в играх TEXT ADVENTURE и R.P.G.
Медлительность вывода спрайтов данным способом объясняется медлительностью работы самого оператора PRINT. Ну а что, если поручить печать спрайтов АССЕМБЛЕРу, и вызывать полученную подпрограмму прямо из БЕЙСИКа. Самым гибким и оригинальным способом для этого является применение метода передачи параметров из БЕЙСИКа в АССЕМБЛЕР при помощи функции, определяемой пользователем (DEF FN...). Исчерпывающее описание такого подхода можно найти в книге ИНФОРКОМа под названием "ЭЛЕМЕНТАРНАЯ ГРАФИКА". Теперь попробуем использовать его применительно к нашим задачам.
1 |
; BLOCK OUTPUT |
|
47 |
|
SLA |
E |
2 |
; V. BODROV (C) 1995 |
|
48 |
|
SLA |
E |
3 |
; SPECIAL |
FOR INFORCOM |
49 |
LOOP0 |
ADD |
HL,DE |
4 |
|
|
|
50 |
|
DJNZ |
LOOP0 |
5 |
; DEF FN B |
(X,Y,N,O) |
|
51 |
|
POP |
BC |
6 |
; |
|
=USR 65394 |
52 |
|
DJNZ |
LOOP5 |
7 |
|
ORG |
65394 |
53 |
PASS |
PUSH |
HL |
8 |
|
ENT |
$ |
54 |
|
POP |
IX |
9 |
|
LD |
HL,(#5C0B) |
55 |
|
LD |
DE, (COORDS |
10 |
|
LD |
BC,#0004 |
56 |
|
LD |
A, (DY) |
11 |
|
ADD |
HL, BC |
57 |
|
LD |
B, A |
12 |
|
LD |
D, (HL) |
58 |
LOOP1 |
PUSH |
BC |
13 |
|
LD |
BC,#0008 |
59 |
|
LD |
A, E |
14 |
|
ADD |
HL, BC |
60 |
|
AND |
#18 |
15 |
|
LD |
E, (HL) |
61 |
|
ADD |
A, #40 |
16 |
|
LD |
(COORDS) , DE |
62 |
|
LD |
H, A |
17 |
|
ADD |
HL, BC |
63 |
|
LD |
A, E |
18 |
|
LD |
A, (HL) |
64 |
|
AND |
7 |
19 |
|
ADD |
HL, BC |
65 |
|
RRCA |
|
20 |
|
LD |
B, A |
66 |
|
RRCA |
|
21 |
|
XOR |
A |
67 |
|
RRCA |
|
22 |
|
LD |
(OPER),A |
68 |
|
ADD |
A, D |
23 |
|
LD |
A, (HL) |
69 |
|
LD |
L, A |
24 |
|
CP |
1 |
70 |
|
LD |
A, (DX) |
25 |
|
JR |
NZ,PASS1 |
71 |
|
LD |
B, A |
26 |
|
LD |
A, #B6 |
72 |
LOOP2 |
PUSH |
BC |
27 |
|
JR |
PASS0 |
73 |
|
LD |
B, 8 |
28 |
PASS1 |
CP |
2 |
74 |
|
PUSH |
HL |
29 |
|
JR |
NZ,PASS2 |
75 |
LOOP3 |
LD |
A,(IX) |
30 |
|
LD |
A, #AE |
76 |
OPER |
NOP |
|
31 |
|
JR |
PASS0 |
77 |
|
LD |
(HL),A |
32 |
PASS2 |
CP |
3 |
78 |
|
INC |
IX |
33 |
|
JR |
NZ,PASS3 |
79 |
|
INC |
H |
34 |
|
LD |
A, #A6 |
80 |
|
DJNZ |
LOOP3 |
35 |
PASS0 |
LD |
(OPER),A |
81 |
|
POP |
HL |
36 |
PASS3 |
LD |
HL,(ADDR) |
82 |
|
INC |
HL |
37 |
|
INC |
B |
83 |
|
POP |
BC |
38 |
|
DEC |
B |
84 |
|
DJNZ |
LOOP2 |
39 |
|
JR |
Z , PASS |
85 |
|
INC |
E |
40 |
LOOP5 |
PUSH |
BC |
86 |
|
POP |
BC |
41 |
|
LD |
D, 0 |
87 |
|
DJNZ |
LOOP1 |
42 |
|
LD |
A, (DY) |
88 |
|
RET |
|
43 |
|
LD |
E, A |
89 |
ADDR |
DEFW |
30000 |
44 |
|
LD |
A, (DX) |
90 |
DY |
DEFB |
3 |
45 |
|
LD |
B, A |
91 |
DX |
DEFB |
3 |
46 |
|
SLA |
E |
92 |
COORDS |
DEFW |
00000 |
Обращение к вышеописанной процедуре осуществляется командой БЕЙСИКа RANDOMIZE FN B(X,Y,N,O), но сначала её нужно описать следующим образом: DEF FN B(X,Y,N,O)=USR 65394. Здесь параметры X и Y -координаты левого верхнего угла позиции печати спрайта, N - номер спрайта. Параметр O может принимать значения: 0 - для простой печати спрайта на экране, 1 - для печати по OR, 2 - для печати по XOR и 3 - для печати по AND, всё же остальные значения параметра O игнорируются и он принимается равным нулю. Для работы с процедурой BLOCK OUT Вам ещё понадобится ввести в ячейки 65529 и 65530 адрес расположения набора спрайтов в ОЗУ, а в ячейки 65531 и 65532 размеры стандартного спрайта (DX и DY - соответственно).
Шестнадцатеричный дамп процедуры (файл "out.BLK"):
0: PAPER 0: BORDER 0: CLS POKE 65530,INT (adr/256) LET y=18: LET o=2: FOR x=1 TO 30 STEP LET y=15: LET x=1 : INK 7: RANDOMIZE
LET adr=30000: POKE 65529,adr-
3: GO SUB 15 : NEXT x FN W(0,15,32,3,71,0)
FF72 |
2A |
0B |
5C |
01 |
04 |
00 |
09 |
56 |
66 |
FF7A |
01 |
08 |
00 |
09 |
5E |
ED |
53 |
FD |
26 |
FF82 |
FF |
09 |
7E |
09 |
47 |
AF |
32 |
E8 |
20 |
FF8A |
FF |
7E |
FE |
01 |
20 |
04 |
3E |
B6 |
1D |
FF92 |
18 |
0E |
FE |
02 |
20 |
04 |
3E |
AE |
C7 |
FF9A |
18 |
06 |
FE |
03 |
20 |
05 |
3E |
A6 |
C1 |
FFA2 |
32 |
E8 |
FF |
2A |
F9 |
FF |
04 |
05 |
E5 |
FFAA |
28 |
17 |
C5 |
16 |
00 |
3A |
FB |
FF |
F7 |
FFB2 |
5F |
3A |
FC |
FF |
47 |
CB |
23 |
CB |
45 |
FFBA |
23 |
CB |
23 |
19 |
10 |
FD |
C1 |
10 |
C1 |
FFC2 |
E9 |
E5 |
DD |
E1 |
ED |
5B |
FD |
FF |
91 |
FFCA |
3A |
FB |
FF |
47 |
C5 |
7B |
E6 |
18 |
82 |
FFD2 |
C6 |
40 |
67 |
7B |
E6 |
07 |
0F |
0F |
C4 |
FFDA |
0F |
82 |
6F |
3A |
FC |
FF |
47 |
C5 |
1A |
FFE2 |
06 |
08 |
E5 |
DD |
7E |
00 |
00 |
77 |
A6 |
FFEA |
DD |
23 |
24 |
10 |
F6 |
E1 |
23 |
C1 |
D8 |
FFF2 |
10 |
ED |
1C |
C1 |
10 |
D6 |
C9 |
30 |
AA |
FFFA |
75 |
03 |
03 |
00 |
00 |
00 |
F3 |
AF |
16 |
Выгрузите на магнитный носитель коды процедуры командой SAVE "out.BLK" CODE 65394,141. Теперь наберите программу "EXAMPLE2" и запустите её командой RUN. Для её работы Вы должны иметь два файла: "exam.BLK" CODE и "out.BLK" CODE. Результаты работы этой программы на порядок выше, чем результаты работы "EXAMPLE".
Основным недостатком такого метода вывода спрайтов является то, что спрайты будут выводиться цветом, установленным на экране, команда же БЕЙСИКа INK не будет влиять на цвет спрайтов. Зато скорость печати и отсутствие ограничений на размеры спрайтов несомненно являются достоинствами этого метода.
1 REM EXAMPLE 2
2 DEF FN b(X,Y,N,O)=USR 65394: DEF FN w(X,Y,L,H,C,I)=USR 65278
3 CLEAR 29999: RANDOMIZE USR 15619: REM : LOAD "exam.BLK"CODE
4 RANDOMIZE USR 15619: REM : LOAD "out.BLK"CODE
5 LET DX=3: LET DY=3: POKE 65531,DX: POKE 65532,DY: RANDOMIZE USR 15619: REM : LOAD "win.BLK" CODE
6 INK 6: BRIGHT (256*INT (adr/256)):
7 LET n=5:
8 BRIGHT 1
9 FOR I=1 TO 20: PLOT INK (RND*4+3);(RND*255),(RND*75+100): NEXT I: GO SUB 14
10 LET n=2: GO SUB 15: BEEP .005,50: PAUSE 4: GO SUB 15: LET x=x+1: LET n=3: GO SUB 15: BEEP .005,50: PAUSE 4: GO SUB 15: LET x=x+1: LET n=4: GO SUB 15: BEEP .005,50: PAUSE 4: GO SUB 15: LET x=x+1: IF (x/7)=INT (x/7) THEN GO SUB 14
11 IF x>26 THEN GO SUB 14: GO SUB 15: STOP
12 GO TO 10
13 STOP
14 LET O=0: FOR i=1 TO 10: LET n=0: GO SUB 15: PAUSE 2: LET n=1: GO SUB 15: PAUSE 2: NEXT i: LET O=2: GO SUB 15: RETURN
15 RANDOMIZE FN b(x,y,n,o): RETURN
Для запуска этой программы Вам понадобится ещё одна полезная процедура - WINDOW ATTR, с помощью которой можно изменять атрибуты любого окна экрана. Объявление её из БЕЙСИКа производится командой DEF FN W (X,Y,L,H,C,I)=USR 65278. Здесь X и Y - координаты левого верхнего угла, L и H- соответственно длина и ширина окна в знакоместах, C - значение атрибута, которым оно будет заполнено. При значении параметра I равном нулю, изменятся только атрибуты заданного окна, если же оно отлично от нуля, то вся графическая информация в окне будет стерта.
1 ; WINDOW ATTR 5 ; DEF FN W(X,Y,L,H,C,I)
2 ; VADIM BODROV (C) 1995 6 ; =USR 65278
3 ; SPECIAL FOR INFORCOM 7 ORG 65278
4 ; 8 ENT $
9 |
|
LD |
HL,(#5C0B) |
49 |
DX |
DEFB |
0 |
10 |
|
LD |
BC,#0004 |
50 |
DY |
DEFB |
0 |
11 |
|
ADD |
HL, BC |
51 |
ATTR |
DEFB |
0 |
12 |
|
LD |
D, (HL) |
52 |
PROC |
LD |
A,E |
13 |
|
LD |
BC,#0008 |
53 |
|
AND |
#18 |
14 |
|
ADD |
HL, BC |
54 |
|
RRCA |
|
15 |
|
LD |
E, (HL) |
55 |
|
RRCA |
|
16 |
|
ADD |
HL, BC |
56 |
|
RRCA |
|
17 |
|
LD |
A, (HL) |
57 |
|
OR |
#58 |
18 |
|
LD |
(DX) , A |
58 |
|
LD |
H, A |
19 |
|
ADD |
HL, BC |
59 |
|
LD |
A, E |
20 |
|
LD |
A, (HL) |
60 |
|
AND |
#07 |
21 |
|
LD |
(DY),A |
61 |
|
RRCA |
|
22 |
|
ADD |
HL, BC |
62 |
|
RRCA |
|
23 |
|
LD |
A, (HL) |
63 |
|
RRCA |
|
24 |
|
LD |
(ATTR) , A |
64 |
|
ADD |
A, D |
25 |
|
LD |
A, #C9 |
65 |
|
LD |
L, A |
26 |
|
LD |
(CLW),A |
66 |
|
LD |
A,(ATTR) |
27 |
|
ADD |
HL, BC |
67 |
|
LD |
(HL),A |
28 |
|
LD |
A, (HL) |
68 |
CLW |
RET |
|
29 |
|
CP |
0 |
69 |
|
PUSH |
BC |
30 |
|
JR |
Z, PASS |
70 |
|
LD |
B, 8 |
31 |
|
XOR |
A |
71 |
|
LD |
A, E |
32 |
|
LD |
(CLW),A |
72 |
|
AND |
#18 |
33 |
PASS |
LD |
A,(DY) |
73 |
|
ADD |
A, #40 |
34 |
|
LD |
B, A |
74 |
|
LD |
H, A |
35 |
LOOP1 |
PUSH |
BC |
75 |
|
LD |
A, E |
36 |
|
LD |
A, (DX) |
76 |
|
AND |
#07 |
37 |
|
LD |
B, A |
77 |
|
RRCA |
|
38 |
|
PUSH |
DE |
78 |
|
RRCA |
|
39 |
LOOP2 |
PUSH |
BC |
79 |
|
RRCA |
|
40 |
|
CALL |
PROC |
80 |
|
ADD |
A, D |
41 |
|
INC |
D |
81 |
|
LD |
L, A |
42 |
|
POP |
BC |
82 |
|
XOR |
A |
43 |
|
DJNZ |
LOOP2 |
83 |
LOOP3 |
LD |
(HL),A |
44 |
|
POP |
DE |
84 |
|
INC |
H |
45 |
|
POP |
BC |
85 |
|
DJNZ |
LOOP3 |
46 |
|
INC |
E |
86 |
|
POP |
BC |
47 |
|
DJNZ |
LOOP1 |
87 |
|
RET |
|
48 |
|
RET |
|
|
|
|
|
FEFE |
2A |
0B |
5C |
01 |
04 |
00 |
09 |
56 |
F1 |
FF06 |
01 |
08 |
00 |
09 |
5E |
09 |
7E |
32 |
2E |
FF0E |
41 |
FF |
09 |
7E |
32 |
42 |
FF |
09 |
50 |
FF16 |
7E |
32 |
43 |
FF |
3E |
C9 |
32 |
59 |
99 |
FF1E |
FF |
09 |
7E |
FE |
00 |
28 |
04 |
AF |
7C |
FF2 6 |
32 |
59 |
FF |
3A |
42 |
FF |
47 |
C5 |
36 |
FF2E |
3A |
41 |
FF |
47 |
D5 |
C5 |
CD |
44 |
99 |
FF36 |
FF |
14 |
C1 |
10 |
F8 |
D1 |
C1 |
1C |
BF |
FF3E |
10 |
ED |
C9 |
00 |
00 |
00 |
7B |
E6 |
64 |
FF4 6 |
18 |
0F |
0F |
0F |
F6 |
58 |
67 |
7B |
BA |
FF4E |
E6 |
07 |
0F |
0F |
0F |
82 |
6F |
3A |
92 |
FF56 |
43 |
FF |
77 |
C9 |
C5 |
06 |
08 |
7B |
25 |
FF5E |
E6 |
18 |
C6 |
40 |
67 |
7B |
E6 |
07 |
30 |
FF66 |
0F |
0F |
0F |
82 |
6F |
AF |
77 |
24 |
CD |
FF6E |
10 |
FC |
C1 |
C9 |
00 |
00 |
00 |
00 |
03 |
Процедура WINDOW ATTR выгружается на магнитофон командой SAVE "win.BLK" CODE 65276,116. Обращение к ней из БЕЙСИКа производится командой:
RANDOMIZE FN W (X,Y,L,H,C,I).
3.
Во многих фирменных программах вывод спрайтов на экран осуществляется с точностью до пикселя. Совершенно очевидно, что концепция блочной графики здесь полностью неприемлема. Вот тут-то мы с Вами вплотную подошли к растровой (пиксельной) графике, но и тут тоже существует два классических подхода. Первый из них заключается в копировании изображения на экран побайтно (линия за линией), а второй - в копировании попиксельно.
1 ; |
SPRITE OUTPUT 1 |
|
43 |
|
JR |
PASS |
2 ; |
V. BODROV (C) 1995 |
|
44 |
PASS2 |
CP |
3 |
3 ; |
SPECIAL FOR INFORCOM |
45 |
|
JR |
NZ,PASS3 |
4 ; |
|
|
46 |
|
LD |
A, #A6 |
5 ; |
DEF FN L(X,Y,L,H,A, |
O) |
47 |
PASS |
LD |
(OPER),A |
6 ; |
|
=USR 65153 |
48 |
PASS3 |
LD |
IX,(ADDR) |
7 |
ORG |
65153 |
49 |
|
LD |
A, (DY) |
8 |
ENT |
$ |
50 |
|
LD |
B, A |
9 |
LD |
HL,(#5C0B) |
51 |
LOOP1 |
PUSH |
BC |
10 |
LD |
BC,#0004 |
52 |
|
LD |
A, E |
11 |
ADD |
HL, BC |
53 |
|
AND |
7 |
12 |
LD |
D, (HL) |
54 |
|
LD |
C, A |
13 |
LD |
BC,#0008 |
55 |
|
LD |
A, E |
14 |
ADD |
HL, BC |
56 |
|
SRL |
A |
15 |
LD |
E, (HL) |
57 |
|
SRL |
A |
16 |
LD |
A, #BF |
58 |
|
SRL |
A |
17 |
SUB |
E |
59 |
|
AND |
#18 |
18 |
LD |
E, A |
60 |
|
ADD |
A, #40 |
19 |
ADD |
HL, BC |
61 |
|
OR |
C |
20 |
LD |
A, (HL) |
62 |
|
LD |
H, A |
21 |
LD |
(DX) , A |
63 |
|
LD |
A, E |
22 |
ADD |
HL, BC |
64 |
|
AND |
#38 |
23 |
LD |
A, (HL) |
65 |
|
RLCA |
|
24 |
LD |
(DY),A |
66 |
|
RLCA |
|
25 |
ADD |
HL, BC |
67 |
|
ADD |
A, D |
26 |
LD |
A, (HL) |
68 |
|
LD |
L, A |
27 |
LD |
(ADDR),A |
69 |
|
LD |
A, (DX) |
28 |
INC |
HL |
70 |
|
LD |
B, A |
29 |
LD |
A, (HL) |
71 |
LOOP |
LD |
A,(IX) |
30 |
DEC |
HL |
72 |
OPER |
NOP |
|
31 |
LD |
(ADDR+1),A |
73 |
|
LD |
(HL),A |
32 |
ADD |
HL, BC |
74 |
|
INC |
IX |
33 |
XOR |
A |
75 |
|
INC |
HL |
34 |
LD |
(OPER),A |
76 |
|
DJNZ |
LOOP |
35 |
LD |
A, (HL) |
77 |
|
INC |
E |
36 |
CP |
1 |
78 |
|
POP |
BC |
37 |
JR |
NZ,PASS1 |
79 |
|
DJNZ |
LOOP1 |
38 |
LD |
A, #B6 |
80 |
|
RET |
|
39 |
JR |
PASS |
81 |
ADDR |
DEFW |
00000 |
40 |
PASS1 CP |
2 |
82 |
DY |
DEFB |
0 |
41 |
JR |
NZ,PASS2 |
83 |
DX |
DEFB |
0 |
42 |
LD |
A, #AE |
|
|
|
|
Программа SPRITE OUTPUT 1 копирует спрайт в экран с произвольными координатами X и Y, причём значение X задаётся в знакоместах, а Y - в пикселях от 0 до 191. За начало координат взят левый нижний угол экрана. Эта процедура описывается тем же оператором БЕЙСИКа DEF FN, и делается это так: DEF FN L (X,Y,L,H,A,O) = USR 65153. Параметры X,Y и O Вам уже известны, L - длинна спрайта в знакоместах, H - высота спрайта в пикселях и A -адрес начала данного спрайта в ОЗУ. Такая раскладка вводимых параметров напоминает оператор GET из GW-BASIC (IBM) или MEGA-BASIC (ZX-SPECTRUM).
Шестнадцатеричный дамп процедуры (файл "out1.PIX"):
FE81 |
2A |
0B |
5C |
01 |
04 |
00 |
09 |
56 |
74 |
FE89 |
01 |
08 |
00 |
09 |
5E |
3E |
BF |
93 |
87 |
FE91 |
5F |
09 |
7E |
32 |
FD |
FE |
09 |
7E |
29 |
FE99 |
32 |
FC |
FE |
09 |
7E |
32 |
FA |
FE |
74 |
FEA1 |
23 |
7E |
2B |
32 |
FB |
FE |
09 |
AF |
4E |
FEA9 |
32 |
EE |
FE |
7E |
FE |
01 |
20 |
04 |
66 |
FEB1 |
3E |
B6 |
18 |
0E |
FE |
02 |
20 |
04 |
ED |
FEB9 |
3E |
AE |
18 |
06 |
FE |
03 |
20 |
05 |
E7 |
FEC1 |
3E |
A6 |
32 |
EE |
FE |
DD |
2A |
FA |
C2 |
FEC9 |
FE |
3A |
FC |
FE |
47 |
C5 |
7B |
E6 |
66 |
FED1 |
07 |
4F |
7B |
CB |
3F |
CB |
3F |
CB |
7F |
FED9 |
3F |
E6 |
18 |
C6 |
40 |
B1 |
67 |
7B |
AD |
FEE1 |
E6 |
38 |
07 |
07 |
82 |
6F |
3A |
FD |
33 |
FEE9 |
FE |
47 |
DD |
7E |
00 |
00 |
77 |
DD |
DB |
FEF1 |
23 |
23 |
10 |
F6 |
1C |
C1 |
10 |
D5 |
FD |
FEF9 |
C9 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
C0 |
Выгрузите коды этой процедуры на магнитофон командой SAVE "outl.PIX" CODE 65153,125. Не всех может удовлетворить то, что нельзя задавать координату вывода X с точностью до пикселя. Для них есть и другой алгоритм.
1 |
; SPRITE |
OUTPUT 2 |
|
53 |
PUSH |
AF |
2 |
; V. BODROV (C) 1995 |
|
54 PLOT |
LD |
A,D |
3 |
; SPECIAL |
FOR INFORCOM |
55 |
AND |
7 |
4 |
|
|
|
56 |
LD |
(LIXA+2),A |
5 |
; DEF FN |
M(X,Y,L,H,A, |
O) |
57 |
LD |
A, #BF |
6 |
; |
|
=USR 65005 |
58 |
SUB |
E |
7 |
|
ORG |
65005 |
59 |
LD |
C, A |
8 |
|
ENT |
$ |
60 |
AND |
#38 |
9 |
|
LD |
HL,(#5C0B) |
61 |
RLCA |
|
10 |
|
LD |
BC,#0004 |
62 |
RLCA |
|
11 |
|
ADD |
HL, BC |
63 |
SRL |
D |
12 |
|
LD |
D, (HL) |
64 |
SRL |
D |
13 |
|
LD |
BC,#0008 |
65 |
SRL |
D |
14 |
|
ADD |
HL, BC |
66 |
ADD |
A, D |
15 |
|
LD |
E, (HL) |
67 |
LD |
L, A |
16 |
|
ADD |
HL, BC |
68 |
LD |
A, C |
17 |
|
LD |
A, (HL) |
69 |
RRCA |
|
18 |
|
LD |
(DXY+2),A |
70 |
RRCA |
|
19 |
|
ADD |
HL, BC |
71 |
RRCA |
|
20 |
|
LD |
A, (HL) |
72 |
AND |
#18 |
21 |
|
LD |
(DXY+1),A |
73 |
XOR |
C |
22 |
|
ADD |
HL, BC |
74 |
AND |
#F8 |
23 |
|
LD |
A, (HL) |
75 |
XOR |
C |
24 |
|
LD |
(ADDR),A |
76 |
ADD |
A, #40 |
25 |
|
INC |
HL |
77 |
LD |
H, A |
26 |
|
LD |
A, (HL) |
7 8 LIXA |
LD |
A,(IX+0) |
27 |
|
DEC |
HL |
79 OPER |
NOP |
|
28 |
|
LD |
(ADDR+1) , A |
80 |
LD |
(HL),A |
29 |
|
ADD |
HL, BC |
81 CONT |
POP |
AF |
30 |
|
LD |
A, #B6 |
82 |
POP |
DE |
31 |
|
LD |
(OPER),A |
83 PASS1 |
INC |
D |
32 |
|
LD |
A, (HL) |
84 |
DJNZ |
LOOP1 |
33 |
|
CP |
1 |
85 |
POP |
HL |
34 |
|
JR |
NZ,PASS |
86 |
INC |
HL |
35 |
|
LD |
A, #AE |
87 |
POP |
BC |
36 |
|
JR |
PASS2 |
88 |
DJNZ |
LOOP2 |
37 |
PASS |
CP |
2 |
89 |
POP |
DE |
38 |
|
JR |
NZ,PASS3 |
90 |
POP |
BC |
39 |
|
LD |
A, #A6 |
91 |
DEC |
E |
40 |
PASS2 |
LD |
(OPER),A |
92 |
DEC |
C |
41 |
PASS3 |
LD |
HL,(ADDR) |
93 |
JR |
NZ, LOOP |
42 |
DXY |
LD |
BC,0000 |
94 |
RET |
|
43 |
|
LD |
IX,BYTE |
95 BYTE |
DEFB |
128 |
44 |
LOOP |
PUSH |
BC |
96 |
DEFB |
64 |
45 |
|
PUSH |
DE |
97 |
DEFB |
32 |
46 |
LOOP2 |
PUSH |
BC |
98 |
DEFB |
16 |
47 |
|
LD |
A, (HL) |
99 |
DEFB |
8 |
48 |
|
LD |
B, 8 |
100 |
DEFB |
4 |
49 |
|
PUSH |
HL |
101 |
DEFB |
2 |
50 |
LOOP1 |
SLA |
A |
102 |
DEFB |
1 |
51 |
|
JR |
NC,PASS1 |
103 ADDR |
DEFW |
0000 |
52 |
|
PUSH |
DE |
|
|
|
В процедуре SPRITE OUTPUT 2 устранен недостаток, которым страдает SPRITE OUTPUT 1. Описывается она из БЕЙСИКа следующим образом: DEF FN M (X,Y,L,H,O) = USR 60005. Только здесь параметр X задается в пикселях (0-255), а параметр O может иметь значения от 0 до 2, эти значения соответствуют логическим операциям OR, XOR и AND. Аналогичная процедура есть в книге ИНФОРКОМа "ПРИКЛАДНАЯ ГРАФИКА", но, к сожалению, в ней есть опечатки и она просто откажется у Вас работать. К тому же в ней для печати точек используется процедура ПЗУ PLOT_SUB (#22E5), которая работает слишком медленно. В этой книге приводится и другой вариант печати точек на экране - альтернативная процедура PLOT, но и её быстродействие годится только для применения в учебных целях. Исходя из этого мне пришлось написать собственную процедуру PLOT. Алгоритм её трудночитаем, но скорость работы вполне приемлема. Я не буду описывать его работу, так как поставил перед собой немного другую цель - ВЫВОД СПРАЙТОВ ИЗ СТАНДАРТНОГО БЕЙСИКа.
ый дамп процедуры (файл |
"out2.PIX"): |
|
|
|
|
FDED |
2A |
0B |
5C |
01 |
04 |
00 |
09 |
56 |
DF |
FDF5 |
01 |
08 |
00 |
09 |
5E |
09 |
7E |
32 |
1B |
FDFD |
2C |
FE |
09 |
7E |
32 |
2B |
FE |
09 |
0F |
FE05 |
7E |
32 |
7F |
FE |
23 |
7E |
2B |
32 |
2E |
FE0D |
80 |
FE |
09 |
3E |
B6 |
32 |
64 |
FE |
1A |
FE15 |
7E |
FE |
01 |
20 |
04 |
3E |
AE |
18 |
B8 |
FE1D |
06 |
FE |
02 |
20 |
05 |
3E |
A6 |
32 |
5C |
FE2 5 |
64 |
FE |
2A |
7F |
FE |
01 |
00 |
00 |
2D |
FE2D |
DD |
21 |
77 |
FE |
C5 |
D5 |
C5 |
7E |
7B |
FE35 |
06 |
08 |
E5 |
CB |
27 |
30 |
2C |
D5 |
49 |
FE3D |
F5 |
7A |
E6 |
07 |
32 |
63 |
FE |
3E |
68 |
FE45 |
BF |
93 |
4F |
E6 |
38 |
07 |
07 |
CB |
DB |
FE4D |
3A |
CB |
3A |
CB |
3A |
82 |
6F |
79 |
F9 |
FE55 |
0F |
0F |
0F |
E6 |
18 |
A9 |
E6 |
F8 |
05 |
FE5D |
A9 |
C6 |
40 |
67 |
DD |
7E |
00 |
00 |
CC |
FE65 |
77 |
F1 |
D1 |
14 |
10 |
CD |
E1 |
23 |
91 |
FE6D |
C1 |
10 |
C3 |
D1 |
C1 |
1D |
0D |
20 |
DB |
FE75 |
BB |
C9 |
80 |
40 |
20 |
10 |
08 |
04 |
F3 |
FE7D |
02 |
01 |
00 |
00 |
00 |
00 |
00 |
00 |
7E |
Процедура SPRITE OUTPUT 2 выгружается на магнитофон командой SAVE "out2.PIX" CODE 65005,148.
Теперь нужно подумать о том, как сгенерировать набор спрайтов, формат которого подойдет для применения его в процедурах SPRITE OUTPUT 1 и SPRITE OUTPUT 2. Для этого нам понадобятся сканирующая программа на БЕЙСИКе - SCAN 1/2 и процедура в кодах, которая будет осуществлять собственно сам процесс копирования спрайтов с экрана в ОЗУ СПЕКТРУМа. Назовем её SPRITE INPUT 1/2. Объявляется она оператором DEF FN N (X,Y,L,H,A). Работа данной процедуры и все параметры, используемые в ней аналогичны SPRITE OUTPUT 1, той лишь разницей, что спрайт копируется из экрана в ОЗУ, а не наоборот.
1 ; |
SPRITE |
INPUT 1/2 |
|
34 |
|
LD |
B, A |
2 ; |
V. BODROV (C) 1995 |
|
35 |
LOOP1 |
PUSH |
BC |
3 ; |
SPECIAL |
FOR INFORCOM |
36 |
|
LD |
A, E |
4 ; |
|
|
|
37 |
|
AND |
7 |
5 ; |
DEF FN |
N(X,Y,L,H,A) |
|
38 |
|
LD |
C, A |
6 ; |
|
|
=USR 64912 |
39 |
|
LD |
A, E |
7 |
|
ORG |
64912 |
40 |
|
SRL |
A |
8 |
|
ENT |
$ |
41 |
|
SRL |
A |
9 |
|
LD |
HL,(#5C0B) |
42 |
|
SRL |
A |
10 |
|
LD |
BC,#0004 |
43 |
|
AND |
#18 |
11 |
|
ADD |
HL, BC |
44 |
|
ADD |
A, #40 |
12 |
|
LD |
D, (HL) |
45 |
|
OR |
C |
13 |
|
LD |
BC,#0008 |
46 |
|
LD |
H, A |
14 |
|
ADD |
HL, BC |
47 |
|
LD |
A, E |
15 |
|
LD |
E, (HL) |
48 |
|
AND |
#38 |
16 |
|
LD |
A, #BF |
49 |
|
RLCA |
|
17 |
|
SUB |
E |
50 |
|
RLCA |
|
18 |
|
LD |
E, A |
51 |
|
ADD |
A, D |
19 |
|
ADD |
HL, BC |
52 |
|
LD |
L, A |
20 |
|
LD |
A, (HL) |
53 |
|
LD |
A, (DX) |
21 |
|
LD |
(DX) , A |
54 |
|
LD |
B, A |
22 |
|
ADD |
HL, BC |
55 |
LOOP |
LD |
A,(HL) |
23 |
|
LD |
A, (HL) |
56 |
|
LD |
(IX),A |
24 |
|
LD |
(DY),A |
57 |
|
INC |
IX |
25 |
|
ADD |
HL, BC |
58 |
|
INC |
HL |
26 |
|
LD |
A, (HL) |
59 |
|
DJNZ |
LOOP |
27 |
|
LD |
(ADDR),A |
60 |
|
INC |
E |
28 |
|
INC |
HL |
61 |
|
POP |
BC |
29 |
|
LD |
A, (HL) |
62 |
|
DJNZ |
LOOP1 |
30 |
|
DEC |
HL |
63 |
|
RET |
|
31 |
|
LD |
(ADDR+1),A |
64 |
ADDR |
DEFW |
00000 |
32 |
|
LD |
IX,(ADDR) |
65 |
DY |
DEFB |
0 |
33 |
|
LD |
A, (DY) |
66 |
DX |
DEFB |
0 |
FD90 |
2A |
0B |
5C |
01 |
04 |
00 |
09 |
56 |
82 |
FD98 |
01 |
08 |
00 |
09 |
5E |
3E |
BF |
93 |
95 |
FDA0 |
5F |
09 |
7E |
32 |
EC |
FD |
09 |
7E |
25 |
FDA8 |
32 |
EB |
FD |
09 |
7E |
32 |
E9 |
FD |
5E |
FDB0 |
23 |
7E |
2B |
32 |
EA |
FD |
DD |
2A |
99 |
FDB8 |
E9 |
FD |
3A |
EB |
FD |
47 |
C5 |
7B |
44 |
FDC0 |
E6 |
07 |
4F |
7B |
CB |
3F |
CB |
3F |
88 |
FDC8 |
CB |
3F |
E6 |
18 |
C6 |
40 |
B1 |
67 |
EB |
FDD0 |
7B |
E6 |
38 |
07 |
07 |
82 |
6F |
3A |
9F |
FDD8 |
EC |
FD |
47 |
7E |
DD |
77 |
00 |
DD |
B4 |
FDE0 |
23 |
23 |
10 |
F7 |
1C |
C1 |
10 |
D6 |
ED |
FDE8 |
C9 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
AE |
SPRITE INPUT 1/2 командой SAVE |
"in12.PIX" |
CODE |
64912,93. |
Программа SCAN 1/2 осуществляет удобный интерфейс для создания набора спрайтов и выгрузки его на магнитный носитель. Управление перемещением рамки на экране выполняется клавишами 6, 7, 8 и 9, для перемещения по координате Y с шагом в одно знакоместо используйте нажатие клавиши соответствующего направления совместно с CAPS SHIFT. Клавиша 0 переводит программу из режима перемещения рамки в режим изменения её величины и обратно. Клавишей ENTER осуществляется ввод спрайта, заключенного в рамку в память компьютера. Рамка может иметь минимальный размер - 8X1 пиксел, а максимальный - во весь экран.
1 BORDER 1: PAPER 7: INK 0: CLEAR 29999: RANDOMIZE USR 15619: REM : LOAD "in12.PIX"CODE
2 DEF FN N(X,Y,L,H,A)=USR 64912: RANDOMIZE USR 15619: REM : LOAD "win.BLK" CODE
3 DEF FN W(X,Y,L,H,C,I)=USR 65278: CLS : PRINT "SCAN 1/2"'"(C) Vadim Bodrov, Ufa, 95"'"SPECIAL FOR ~ZX-REVIEW~"
4 INPUT "SPRITE ADDRESS ? ";ADR: IF ADR>64911 OR ADR<30000 THEN GO TO 4
5 LET HMS=0: LET CADR=ADR
6 OVER 1: LET X=0: LET Y=0: GO SUB 22
7 LET O=0: LET DX=1: LET DY=1
8 GO SUB 29: GO SUB 2 0
9 IF A$="1" THEN GO TO 6
10 GO SUB 29
11 IF A$="0" THEN LET O=O+1: IF O=2 THEN LET O=0
12 IF O=0 THEN GO SUB 31
13 IF O=1 THEN GO SUB 34
14 IF A$=CHR$ 13 AND CADR+DX*DY>64 911 THEN RANDOMIZE USR 3438: PRINT #1;AT 0,0;TAB 7;"NO FREE MEMORY!!!": PAUSE 0: GO TO 16
15 LET Z=Y+16: IF A$=CHR$ 13 THEN RANDOMIZE FN N(X,Z,DX,DY,CADR) 3438: PRINT #1;AT 0,0;"SPRITE #";HMS,"DX=";DX;" DY="; DY'"ADDRESS:"; CADR,"SIZE:";DX*DY: BEEP .05,10: PAUSE 0: GO SUB 18: LET CADR=CADR+DX*DY: LET HMS=HMS+1: GO TO 8
16 IF A$="2" AND HMS>0 THEN GO SUB 24: RUN
17 GO TO 8
18 PRINT #1;AT 0,0;"1-LOAD SCREEN ENTER-PUT SPRITE";
19 RETURN PAUSE 1: LET A$=INKEY$: BEEP .001,60: RETURN INPUT "NAME OF SCREEN ?
IF A$="" THEN GO TO 20 ";N$: CLS FN W(0,0,32,24,112,0)
RANDOMIZE USR 15619: REM : LOAD N$ CODE
SUB 18: RETURN PRINT "START SPRITE ADDRESS: ";ADR
'"LENGHT OF SET SPRITES: ";CADR-ADR '"TOTAL NUMBER OF SPRITES: ";HMS
"NAME OF SET SPRITES? ";N$: RANDOMIZE USR 15619: REM : SAVE N$ CODE
RANDOMIZE CLS : PRINT PRINT INPUT
16384
23
24
25
26
27
ADR,(CADR-ADR)
28 PRINT '"MORE (Y/N) ? ": GO SUB 20: IF A$="N" OR A$="n" THEN STOP
29 LET DY=DY+(DY=0): PLOT X*8,Y: DRAW DX*8-1,0: IF DY=1 THEN RETURN 3 0 DRAW 0,1-DY: DRAW 1-DX*8,0: DRAW 0,DY-1: PLOT X*8,Y: RETURN
31 LET X=X+(A$="7" AND X+DX-1<31)-(A$="6" AND X>0): LET Y=Y+(A$="9" AND Y<175)-(A$="8" AND Y-DY+1>0)
32 IF A$=CHR$ 15 OR A$=CHR$ 9 THEN LET Y=Y+8*(A$=CHR$ 15 AND Y<168)-8*(A$=CHR$ 9 AND Y-DY+1>6): LET Y=8*INT ((Y+1)/8)-(Y>0)
33 RETURN
34 LET DX=DX+(A$="7" AND DX+X<31)-(A$="6" AND DX>1): LET DY=DY+(A$="8" AND Y-DY>1)-(A$="9" AND DY>1)+(DY=0)
35 IF A$=CHR$ 15 OR A$=CHR$ 9 THEN LET DY=DY+8*(A$=CHR$ 9 AND Y-DY>0)-8*(A$=CHR$ 15 AND DY>7): LET DY=8*INT ((DY+1)/8)
36 RETURN
Касаясь вышеперечисленных методов, мне остается добавить, что все процедуры ввода/вывода не делают проверки на выход изображения за пределы экрана. Поэтому Вы сами должны следить за этим. Иначе могут произойти различные не желаемые последствия и даже зависание системы.
4.
Многие игровые программы имеют прекрасную цветную графику. Если и Вы рассчитываете использовать цветные спрайты в своих программах, то... воздержитесь от применения всего того, что узнали в предыдущих главах. Здесь нам поможет, пожалуй, самый последний классический прием вывода спрайтов. Он заключается в том, что сначала на экране печатается черно-белый спрайт, а потом на него накладываются атрибуты. Становится очевидным, что мы можем печатать спрайт с точностью до знакоместа, причем его размеры обязательно должны тоже определяться в знакоместах. Если этого не делать, то неминуемо возникнет конфликт с атрибутами в граничащих с ним знакоместах.
Формат таблицы спрайтов тоже немного изменится. Теперь для каждого спрайта будем отводить 2+DX*DY*8+DX*DY байт. Первые два байта - длина (DX) и ширина (DY) спрайта в знакоместах, DX*DY*8 черно-белая конструкция спрайта, DX*DY - атрибуты спрайта. Такой расклад очень удобен на практике, ведь Вам уже больше не надо запоминать адрес начала нужного спрайта и его размеры. В нижеприведенных процедурах введена обязательная проверка на выходы спрайта за пределы экрана (если какая-либо часть спрайта не умещается на экране, то она просто не печатается). Таким образом, мы получили две очень мощных процедуры: SPRITE OUTPUT 3 и SPRITE INPUT 3, которые работают с одним и тем же форматом спрайтов и позволяют осуществить все необходимые операции по их вводу /выводу.
1 |
; SPRITE |
OUTPUT 3 |
|
40 |
|
JR |
Z , PASS |
2 |
; V. BODROV (C) 1995 |
|
41 |
LOOP5 |
LD |
D,0 |
3 |
; SPECIAL |
FOR INFORCOM |
42 |
|
LD |
E,(IX) |
4 |
|
|
|
43 |
|
LD |
H, 0 |
5 |
; DEF FN |
O(X,Y,N,O) |
|
44 |
|
LD |
L,(IX+1) |
6 |
; |
|
=USR 64692 |
45 |
|
CALL |
#3 0A9 |
7 |
|
ORG |
64692 |
46 |
|
LD |
DE, 9 |
8 |
|
ENT |
$ |
47 |
|
CALL |
#3 0A9 |
9 |
|
DI |
|
48 |
|
INC |
HL |
10 |
|
LD |
HL, (#5C0B) |
49 |
|
INC |
HL |
11 |
|
LD |
BC,#0004 |
50 |
|
PUSH |
HL |
12 |
|
ADD |
HL, BC |
51 |
|
POP |
DE |
13 |
|
LD |
D, (HL) |
52 |
|
ADD |
IX, DE |
14 |
|
LD |
BC,#0008 |
53 |
|
DJNZ |
LOOP5 |
15 |
|
ADD |
HL, BC |
54 |
PASS |
LD |
A,(IX) |
16 |
|
LD |
E, (HL) |
55 |
|
LD |
(DX) , A |
17 |
|
PUSH |
DE |
56 |
|
INC |
IX |
18 |
|
ADD |
HL, BC |
57 |
|
LD |
A,(IX) |
19 |
|
LD |
A, (HL) |
58 |
|
LD |
(DY),A |
20 |
|
ADD |
HL, BC |
59 |
|
INC |
IX |
21 |
|
LD |
B, A |
60 |
PIXELS |
POP |
DE |
22 |
|
XOR |
A |
61 |
|
PUSH |
DE |
23 |
|
LD |
(OPER),A |
62 |
|
LD |
A, (DY) |
24 |
|
LD |
A, (HL) |
63 |
|
LD |
B, A |
25 |
|
CP |
1 |
64 |
LOOP1 |
PUSH |
BC |
26 |
|
JR |
NZ,PASS1 |
65 |
|
LD |
A, E |
27 |
|
LD |
A, #B6 |
66 |
|
AND |
#18 |
28 |
|
JR |
PASS0 |
67 |
|
ADD |
A, #40 |
29 |
PASS1 |
CP |
2 |
68 |
|
LD |
H, A |
30 |
|
JR |
NZ,PASS2 |
69 |
|
LD |
A, E |
31 |
|
LD |
A, #AE |
70 |
|
AND |
7 |
32 |
|
JR |
PASS0 |
71 |
|
RRCA |
|
33 |
PASS2 |
CP |
3 |
72 |
|
RRCA |
|
34 |
|
JR |
NZ,PASS3 |
73 |
|
RRCA |
|
35 |
|
LD |
A, #A6 |
74 |
|
ADD |
A, D |
36 |
PASS0 |
LD |
(OPER),A |
75 |
|
LD |
L, A |
37 |
PASS3 |
LD |
IX,(ADDR) |
76 |
|
LD |
B, 8 |
38 |
|
INC |
B |
77 |
LOOP2 |
PUSH |
BC |
39 |
|
DEC |
B |
78 |
|
PUSH |
HL |
79 |
LD |
|
C, D |
|
|
|
112 |
|
|
OR |
|
#58 |
80 |
LD |
|
A, (DX) |
|
|
|
113 |
|
|
LD |
|
H, A |
81 |
LD |
|
B, A |
|
|
|
114 |
|
|
LD |
|
A, E |
82 LOOP3 |
LD |
|
A,C |
|
|
|
115 |
|
|
AND |
|
#07 |
83 |
INC |
|
C |
|
|
|
116 |
|
|
RRCA |
|
84 |
CP |
|
32 |
|
|
|
117 |
|
|
RRCA |
|
85 |
JR |
|
NC,PASS4 |
|
|
118 |
|
|
RRCA |
|
86 |
LD |
|
A, E |
|
|
|
119 |
|
|
ADD |
|
A, D |
87 |
CP |
|
24 |
|
|
|
120 |
|
|
LD |
|
L, A |
88 |
JR |
|
NC,PASS4 |
|
|
121 |
|
|
LD |
|
C, D |
89 |
LD |
|
A,(IX) |
|
|
|
122 |
|
|
LD |
|
A, (DX) |
90 OPER |
NOP |
|
|
|
|
|
|
123 |
|
|
LD |
|
B, A |
91 |
LD |
|
|
(HL),A |
|
|
|
124 |
LOOP6 |
LD |
|
A,C |
92 PASS4 |
INC |
|
HL |
|
|
|
125 |
|
|
INC |
|
C |
93 |
INC |
|
IX |
|
|
|
126 |
|
|
CP |
|
32 |
94 |
DJNZ |
|
LOOP3 |
|
|
|
127 |
|
|
JR |
|
NC,PASS5 |
95 |
POP |
|
HL |
|
|
|
128 |
|
|
LD |
|
A, E |
96 |
INC |
|
H |
|
|
|
129 |
|
|
CP |
|
24 |
97 |
POP |
|
BC |
|
|
|
130 |
|
|
JR |
|
NC,PASS5 |
98 |
DJNZ |
|
LOOP2 |
|
|
|
131 |
|
|
LD |
|
A,(IX) |
99 |
POP |
|
BC |
|
|
|
132 |
|
|
LD |
|
(HL),A |
100 |
INC |
|
|
E |
|
|
|
133 |
PASS5 |
INC |
|
IX |
101 |
DJNZ |
|
LOOP1 |
|
|
|
134 |
|
|
INC |
|
HL |
102 ATTR |
POP |
|
DE |
|
|
|
135 |
|
|
DJNZ |
|
LOOP6 |
103 |
LD |
|
A, (DY) |
|
|
|
136 |
|
|
POP |
|
DE |
104 |
LD |
|
B, A |
|
|
|
137 |
|
|
INC |
|
E |
105 LOOP4 |
PUSH |
|
BC |
|
|
|
138 |
|
|
POP |
|
BC |
106 |
PUSH |
|
DE |
|
|
|
139 |
|
|
DJNZ |
|
LOOP4 |
107 |
LD |
|
A, E |
|
|
|
140 |
|
|
EI |
|
|
108 |
AND |
|
#18 |
|
|
|
141 |
|
|
RET |
|
|
109 |
RRCA |
|
|
|
|
|
|
142 |
ADDR |
|
DEFW |
30000 |
110 |
RRCA |
|
|
|
|
|
|
143 |
DY |
|
DEFB |
0 |
111 |
RRCA |
|
|
|
|
|
|
144 |
DX |
|
DEFB |
0 |
|
|
FCB4 |
|
F3 |
2A |
0B |
5C |
01 |
04 |
00 |
09 |
42 |
|
|
|
FCBC |
|
56 |
01 |
08 |
00 |
09 |
5E |
D5 |
09 |
5C |
|
|
|
FCC4 |
|
7E |
09 |
47 |
AF |
32 |
44 |
FD |
7E |
2E |
|
|
|
FCCC |
|
FE |
01 |
20 |
04 |
3E |
B6 |
18 |
0E |
05 |
|
|
|
FCD4 |
|
FE |
02 |
20 |
04 |
3E |
AE |
18 |
06 |
FE |
|
|
|
FCDC |
|
FE |
03 |
20 |
05 |
3E |
A6 |
32 |
44 |
58 |
|
|
|
FCE4 |
|
FD |
DD |
2A |
8C |
FD |
04 |
05 |
28 |
9E |
|
|
|
FCEC |
|
1B |
16 |
00 |
DD |
5E |
00 |
26 |
00 |
7A |
|
|
|
FCF4 |
|
DD |
6E |
01 |
CD |
A9 |
30 |
11 |
09 |
FC |
|
|
|
FCFC |
|
00 |
CD |
A9 |
30 |
23 |
23 |
E5 |
D1 |
9A |
|
|
|
FD04 |
|
DD |
19 |
10 |
E5 |
DD |
7E |
00 |
32 |
79 |
|
|
|
FD0C |
|
8F |
FD |
DD |
23 |
DD |
7E |
00 |
32 |
22 |
|
|
|
FD14 |
|
8E |
FD |
DD |
23 |
D1 |
D5 |
3A |
8E |
0A |
|
|
|
FD1C |
|
FD |
47 |
C5 |
7B |
E6 |
18 |
C6 |
40 |
A1 |
|
|
|
FD2 4 |
|
67 |
7B |
E6 |
07 |
0F |
0F |
0F |
82 |
9F |
|
|
|
FD2C |
|
6F |
06 |
08 |
C5 |
E5 |
4A |
3A |
8F |
63 |
|
|
|
FD34 |
|
FD |
47 |
79 |
0C |
FE |
20 |
30 |
0A |
52 |
|
|
|
FD3C |
|
7B |
FE |
18 |
30 |
05 |
DD |
7E |
00 |
5A |
|
|
|
FD44 |
|
00 |
77 |
23 |
DD |
23 |
10 |
EB |
E1 |
B7 |
|
|
|
FD4C |
|
24 |
C1 |
10 |
DF |
C1 |
1C |
10 |
CA |
D4 |
|
|
|
FD54 |
|
D1 |
3A |
8E |
FD |
47 |
C5 |
D5 |
7B |
43 |
|
|
|
FD5C |
|
E6 |
18 |
0F |
0F |
0F |
F6 |
58 |
67 |
39 |
|
|
|
FD64 |
|
7B |
E6 |
07 |
0F |
0F |
0F |
82 |
6F |
E7 |
|
|
|
FD6C |
|
4A |
3A |
8F |
FD |
47 |
79 |
0C |
FE |
43 |
|
|
|
FD74 |
|
20 |
30 |
09 |
7B |
FE |
18 |
30 |
04 |
8F |
|
|
|
FD7C |
|
DD |
7E |
00 |
77 |
DD |
23 |
23 |
10 |
7E |
|
|
|
FD84 |
|
EC |
D1 |
1C |
C1 |
10 |
CF |
FB |
C9 |
BE |
|
|
|
FD8C |
|
30 |
75 |
00 |
00 |
00 |
00 |
00 |
00 |
2E |
|
Выгрузите коды этой программы на магнитофон командой SAVE "out3.PIX" CODE 64692,220. Описать из БЕЙСИКа её можно командой: DEF FN O (X,Y,N,O) = USR 64692. Здесь X и Y - координаты верхнего левого угла спрайта в знакоместах, N - номер спрайта (0-255), параметр O - логическая операция.
1 |
; SPRITE |
INPUT |
3 |
65 |
LD |
L, A |
2 |
; V. BODROV (C) |
1995 |
66 |
LD |
B, 8 |
3 |
; SPECIAL |
FOR INFORCOM |
67 LOOP2 |
PUSH |
BC |
4 |
|
|
|
68 |
PUSH |
HL |
5 |
; DEF FN |
I(X,Y, |
L,H,N) |
69 |
LD |
C, D |
6 |
; |
|
=USR 64494 |
70 |
LD |
A, (DX) |
7 |
|
ORG |
64494 |
71 |
LD |
B, A |
8 |
|
ENT |
$ |
72 LOOP3 |
LD |
A,C |
9 |
|
DI |
|
73 |
INC |
C |
10 |
|
LD |
HL,(#5C0B) |
74 |
CP |
32 |
11 |
|
LD |
BC,#0004 |
75 |
JR |
NC,PASS4 |
12 |
|
ADD |
HL, BC |
76 |
LD |
A, E |
13 |
|
LD |
D, (HL) |
77 |
CP |
24 |
14 |
|
LD |
BC,#0008 |
78 |
JR |
NC,PASS4 |
15 |
|
ADD |
HL, BC |
79 |
LD |
A,(HL) |
16 |
|
LD |
E, (HL) |
80 |
LD |
(IX),A |
17 |
|
PUSH |
DE |
81 PASS4 |
INC |
HL |
18 |
|
ADD |
HL, BC |
82 |
INC |
IX |
19 |
|
LD |
A, (HL) |
83 |
DJNZ |
LOOP3 |
20 |
|
LD |
(DX) , A |
84 |
POP |
HL |
21 |
|
ADD |
HL, BC |
85 |
INC |
H |
22 |
|
LD |
A, (HL) |
86 |
POP |
BC |
23 |
|
LD |
(DY),A |
87 |
DJNZ |
LOOP2 |
24 |
|
ADD |
HL, BC |
88 |
POP |
BC |
25 |
|
LD |
A, (HL) |
89 |
INC |
E |
26 |
|
LD |
B, A |
90 |
DJNZ |
LOOP1 |
27 |
|
LD |
IX,(ADDR) |
91 ATTR |
POP |
DE |
28 |
|
INC |
B |
92 |
LD |
A,(DY) |
29 |
|
DEC |
B |
93 |
LD |
B, A |
30 |
|
JR |
Z , PASS |
94 LOOP4 |
PUSH |
BC |
31 |
LOOP5 |
LD |
D,0 |
95 |
PUSH |
DE |
32 |
|
LD |
E, (IX) |
96 |
LD |
A, E |
33 |
|
LD |
H, 0 |
97 |
AND |
#18 |
34 |
|
LD |
L,(IX+1) |
98 |
RRCA |
|
35 |
|
CALL |
#3 0A9 |
99 |
RRCA |
|
36 |
|
LD |
DE, 9 |
100 |
RRCA |
|
37 |
|
CALL |
#3 0A9 |
101 |
OR |
#58 |
38 |
|
INC |
HL |
102 |
LD |
H, A |
39 |
|
INC |
HL |
103 |
LD |
A, E |
40 |
|
PUSH |
HL |
104 |
AND |
#07 |
41 |
|
POP |
DE |
105 |
RRCA |
|
42 |
|
ADD |
IX, DE |
106 |
RRCA |
|
43 |
|
DJNZ |
LOOP5 |
107 |
RRCA |
|
44 |
PASS |
LD |
A,(DX) |
108 |
ADD |
A, D |
45 |
|
LD |
(IX),A |
109 |
LD |
L, A |
46 |
|
INC |
IX |
110 |
LD |
C, D |
47 |
|
LD |
A, (DY) |
111 |
LD |
A, (DX) |
48 |
|
LD |
(IX),A |
112 |
LD |
B, A |
49 |
|
INC |
IX |
113 LOOP6 |
LD |
A,C |
50 |
PIXELS |
POP |
DE |
114 |
INC |
C |
51 |
|
PUSH |
DE |
115 |
CP |
32 |
52 |
|
LD |
A, (DY) |
116 |
JR |
NC,PASS5 |
53 |
|
LD |
B, A |
117 |
LD |
A, E |
54 |
LOOP1 |
PUSH |
BC |
118 |
CP |
24 |
55 |
|
LD |
A, E |
119 |
JR |
NC,PASS5 |
56 |
|
AND |
#18 |
120 |
LD |
A,(HL) |
57 |
|
ADD |
A, #40 |
121 |
LD |
(IX),A |
58 |
|
LD |
H, A |
122 PASS5 |
INC |
IX |
59 |
|
LD |
A, E |
123 |
INC |
HL |
60 |
|
AND |
7 |
124 |
DJNZ |
LOOP6 |
61 |
|
RRCA |
|
125 |
POP |
DE |
62 |
|
RRCA |
|
126 |
INC |
E |
63 |
|
RRCA |
|
127 |
POP |
BC |
64 |
|
ADD |
A, D |
128 |
DJNZ |
LOOP4 |
129 EI 132 DY DEFB 0
130 RET 133 DX DEFB 0
131 ADDR DEFW 30000
Если первая программа осуществляет вывод спрайта на экран, то вторая производит полностью противоположенные действия, т.е. копирует спрайт с экрана в ОЗУ. Шестнадцатеричный дамп процедуры (файл "in3.PIX"):
FBEE |
F3 |
2A |
0B |
5C |
01 |
04 |
00 |
09 |
7B |
FBF6 |
56 |
01 |
08 |
00 |
09 |
5E |
D5 |
09 |
95 |
FBFE |
7E |
32 |
B3 |
FC |
09 |
7E |
32 |
B2 |
C3 |
FC06 |
FC |
09 |
7E |
47 |
DD |
2A |
B0 |
FC |
7F |
FC0E |
04 |
05 |
28 |
1B |
16 |
00 |
DD |
5E |
A7 |
FC16 |
00 |
26 |
00 |
DD |
6E |
01 |
CD |
A9 |
FA |
FC1E |
30 |
11 |
09 |
00 |
CD |
A9 |
30 |
23 |
2D |
FC2 6 |
23 |
E5 |
D1 |
DD |
19 |
10 |
E5 |
3A |
20 |
FC2E |
B3 |
FC |
DD |
77 |
00 |
DD |
23 |
3A |
67 |
FC36 |
B2 |
FC |
DD |
77 |
00 |
DD |
23 |
D1 |
05 |
FC3E |
D5 |
3A |
B2 |
FC |
47 |
C5 |
7B |
E6 |
64 |
FC4 6 |
18 |
C6 |
40 |
67 |
7B |
E6 |
07 |
0F |
3E |
FC4E |
0F |
0F |
82 |
6F |
06 |
08 |
C5 |
E5 |
11 |
FC56 |
4A |
3A |
B3 |
FC |
47 |
79 |
0C |
FE |
4F |
FC5E |
20 |
30 |
09 |
7B |
FE |
18 |
30 |
04 |
78 |
FC66 |
7E |
DD |
77 |
00 |
23 |
DD |
23 |
10 |
67 |
FC6E |
EC |
E1 |
24 |
C1 |
10 |
E0 |
C1 |
1C |
E9 |
FC7 6 |
10 |
CB |
D1 |
3A |
B2 |
FC |
47 |
C5 |
12 |
FC7E |
D5 |
7B |
E6 |
18 |
0F |
0F |
0F |
F6 |
EB |
FC86 |
58 |
67 |
7B |
E6 |
07 |
0F |
0F |
0F |
D6 |
FC8E |
82 |
6F |
4A |
3A |
B3 |
FC |
47 |
79 |
6E |
FC96 |
0C |
FE |
20 |
30 |
09 |
7B |
FE |
18 |
86 |
FC9E |
30 |
04 |
7E |
DD |
77 |
00 |
DD |
23 |
A0 |
FCA6 |
23 |
10 |
EC |
D1 |
1C |
C1 |
10 |
CF |
4E |
FCAE |
FB |
C9 |
30 |
75 |
00 |
00 |
00 |
00 |
13 |
Коды процедуры SPRITE INPUT 3 нужно выгрузить на магнитофон: SAVE "in3.PIX" CODE 64494,198. Инициализация процедуры производится после выполнения команды DEF FN I (X,Y,L,H,N). Параметры L и H - длина (DX) и ширина (DY) спрайта в знакоместах, а N - номер спрайта. При использовании этой процедуры не рекомендуется помещать новый спрайт на место старого, если их размеры не совпадают! Так если у Вас имеются уже спрайты с номерами от 0 до 10 (первый спрайт всегда должен иметь нулевой номер, второй первый и т.д.), а Вы решили заменить спрайт с номером 5 на новый, то следите, чтобы значения DX и DY у них были одинаковыми. Если же Вы этого не сделаете, и площадь нового спрайта окажется больше, чем у старого, то все спрайты с 6 по 10 будут потеряны, а при попытке их вывода на экран могут произойти непредсказуемые эффекты...
Как уже было отмечено, эти процедуры полностью автономны, но один параметр в них Вам придется менять. Таковым является адрес начала таблицы спрайтов (ADDR). Для его изменения (первоначально он равен 30000) нужно рассчитать новый адрес в двухбайтном виде и поместить его по адресам 64908, 64909 - для out3.PIX и 64689, 64690 -для in3.PIX. Пусть Вы хотите изменить этот адрес на 50000. Тогда нужно выполнить следующие команды: POKE 64908,80: POKE 64909,195 (out3.PIX) и POKE 64689,80: POKE 64690,195 (для in3.PIX), так как 80+256*195= 50000.
Программу типа SCAN 3 для создания набора спрайтов в формате процедур SPRITE OUTPUT 3 и SPRITE INPUT 3 я намеренно не привожу. Попробуйте сами написать её на БЕЙСИКЕ, используя последние две процедуры в кодах. Думаю, что для любителей БЕЙСИКа это не составит особого труда.
5.
В этой последней главе Мы немного поговорим о способе наложения спрайтов на фоновое изображение. Информации по данному вопросу более чем предостаточно. Практически все книги по графике для SPECCY обязательно освещают данный вопрос, например, "ПРИКЛАДНАЯ ГРАФИКА", описание языков "LASER BASIC" и "MEGA BASIC". Но все эти описания сходятся на том, что спрайт нужно накладывать на фоновое изображение командой логики OR (в LASER BASIC-е это команда .PTOR, у нас - значение параметра O должно быть равно единице). После такой операции мы можем видеть на экране изображение своего спрайта, сквозь который "просвечивает" изображение фона. Такой эффект практически незаметен, если Вы изобразили ракету на звездном фоне, а как быть, если это, к примеру, десантник в джунглях или машина в городе? Тут получается просто какая-то каша! Если попробовать решить этот вопрос применением логической команды XOR, то результат может быть еще хуже, так как не только останется "прозрачность" спрайта, но и вообще исчезнут те пикселы спрайта и фона, которые совпали. Здесь нам очень поможет один классический подход, который имеет несколько модификаций и называется методом МАСОК. Посмотрите на следующий рисунок:
На рисунке изображены два спрайта двигающегося человечка и два спрайта-маски этого же человечка. Спрайты-маски полностью копируют все линии контура спрайтов-изображений, но вместо самих изображений содержат "дырку" (пиксели выключены), а пустота вокруг человечка "залита" (пиксели включены). Теперь попробуйте наложить на какое-либо фоновое изображение маску первого спрайта с использованием команды AND (в процедурах из предыдущих глав параметр O должен быть равен трем), и Вы увидите, что на том месте, где напечатана маска, в фоновом изображении появилась дырка, которая полностью повторяет очертания человечка. Больше ничто не мешает впечатать в него первый спрайт, изображающий самого человечка, с помощью команды OR или XOR. Таким образом, можно избежать проблемы с наложением спрайтов на фоновое изображение - эффект "просвечивания" исчез! Подобный метод я обнаружил еще четыре года назад в программе "HEART BROKEN".
Все остальные нюансы печати и наложения спрайтов очень хорошо освещены в книге ИНФОРКОМа "ПРИКЛАДНАЯ ГРАФИКА". Я убедительно советую приобрести её всем любителям ZX-ГРАФИКИ.
Надеюсь, что изложенный мной материал поможет всем желающим пробить "неприступный" барьер МАШИННОЙ ГРАФИКИ и научиться использовать и классифицировать все основные методы работы со спрайтами. Те, кто знаком с АССЕМБЛЕРом смогут усовершенствовать и переделать "под себя" рассмотренные в этой статье процедуры, например, отассемблировать их по другим адресам и т.д., а те, кто этого сделать пока еще не может -наберут приводимые HEX-дампы и будут использовать их в собственных программах.
В данной статье были использованы программы расчета адресов в экранном файле и в файле атрибутов из раздела "ЭТЮДЫ" ^Х-РЕВЮ-94 № 3, № 6), а также материалы из книг ИНФОРКОМа "ЭЛЕМЕНТАРНАЯ ГРАФИКА" и "ПРИКЛАДНАЯ ГРАФИКА".
к к к
ОПЕЧАТКИ
Многие читатели сообщают об ошибках в книге "Прикладная графика". Н.Малинин из Ростова-на-Дону приводит исправленный вариант процедуры печати шаблона 8х8, когда координаты задаются в пикселях (см. стр. 20).
POP |
HL |
|
CALL |
#22E5 |
LD |
E,Y-коорд. |
|
POP |
AF |
LD |
C, 8 |
|
POP |
DE |
LD |
D,X-коорд. |
|
POP |
HL |
LD |
A, (HL) |
PASS |
INC |
D |
OR |
A |
|
POP |
BC |
LD |
B, 8 |
|
DJNZ |
LOOP 1 |
PUSH |
BC |
|
DEC |
C |
LD |
B, E |
|
INC |
E |
LD |
C, D |
|
INC |
HL |
RLA |
|
|
LD |
A, B |
JR |
NC,PASS |
|
OR |
C |
PUSH |
HL |
|
JR |
NZ,LOOP |
PUSH |
DE |
|
RET |
|
PUSH |
AF |
|
|
|