ZX-Ревю 1995 №4 1995 г.

Читатель-читателю - Графика вашего компьютера.


ЧИТАТЕЛЬ- ЧИТАТЕЛЮ

Графика вашего компьютера © Вадим Бодров, г. Уфа, 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)

20 21 22

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

GO

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

RANDOMIZE USR

2-SAVE SPRITES

INVERSE 1;"0-MODE

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), а также материалы из книг ИНФОРКОМа "ЭЛЕМЕНТАРНАЯ ГРАФИКА" и "ПРИКЛАДНАЯ ГРАФИКА".

к к к

LOOP 2

LOOP 1

ОПЕЧАТКИ

Многие читатели сообщают об ошибках в книге "Прикладная графика". Н.Малинин из Ростова-на-Дону приводит исправленный вариант процедуры печати шаблона 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




СОДЕРЖАНИЕ:


  Оставте Ваш отзыв:

  НИК/ИМЯ
  ПОЧТА (шифруется)
  КОД



Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
От авторов - Вступление. Содержание.
"333 глаз" - Стоит задуматься и о третьем глазе.
Музыка - Песня ALL MY LOVING (П.Маккаpтни) отpажает уже влияние бpитанского фольклоpа на твоpчество БИТЛЗ.
Ликбез - полный дизассемблер ПЗУ (часть 29).
Living on IRC - Посвящается стойким фанатам Спектрума.

В этот день...   28 марта