Как написать игру для ZX Spectrum на ассемблере

       

Мультипликационная заставка



Рисунок 5.7. Мультипликационная заставка

Начнем, как и раньше, с составления блоков данных. Самое простое - это формирование блока, содержащего тексты, без которых не обходится ни одна заставка, будь она статическая или динамическая:

TEXT DEFB 22,2,9,16,6 DEFM "Welcome to the" DEFB 22,5,7,16,7 DEFM "L·I·T·T·L·E··M·A·N" DEFB 22,8,9,16,4 DEFM "0. START GAME" DEFB 22,10,9 DEFM "1. KEYBOARD" DEFB 22,12,9 DEFM "2. KEMPSTON" DEFB 22,14,9 DEFM "3. INSTRUCTIONS" DEFB 22,16,9 DEFM "4. DEFINE KEYS" DEFB 22,19,8,16,3 DEFM "Press key 0 to 4"

Поскольку с выводом текстов мы уже неоднократно сталкивались и подробно их комментировали, то не будем лишний раз заострять на этом внимание и сразу перейдем к следующему блоку. Для кодирования отдельных элементов подвижных изображений вновь воспользуемся символами UDG, определяющими отдельные фрагменты будущих спрайтов.

UDG DEFB 3,3,15,3,6,7,2,1 ; A (144) DEFB 224,224,248,224,176,240,32,19 ; B (145) DEFB 13,29,53,37,7,6,14,0 ; C (146) DEFB 208,216,200,208,240,112,48,56 ; D (147) DEFB 7,7,31,7,13,15,4,3 ; E (148) DEFB 192,192,240,192,96,224,64,128 ; F (149) DEFB 11,27,19,11,15,14,12,28 ; G (150) DEFB 176,184,172,164,224,96,112,0 ; H (151) DEFB 3,3,15,0,4,4,0,1 ; I (152) DEFB 224,224,248,0,16,16,0,192 ; J (153) DEFB 6,27,27,27,7,6,14,0 ; K (154) DEFB 176,120,248,240,240,112,48,56 ; L (155) DEFB 7,7,31,0,8,8,0,3 ; M (156) DEFB 192,192,240,0,32,32,0,128 ; N (157) DEFB 13,30,31,15,15,14,12,28 ; O (158) DEFB 96,216,216,216,224,96,112,0 ; P (159) DEFB 0,28,38,79,95,127,62,28 ; Q (160) DEFB 16,16,16,127,16,16,16,16 ; R (161) DEFB 8,8,8,254,8,8,8,8 ; S (162)

Следующий блок данных - это то, чем будет манипулировать программа, создавая на экране непрерывное движение маленьких симпатичных человечков:

SPR1 DEFB 4,0,0,7,144,0,1,7,145,1,0,4,146,1,1,4,147 SPR2 DEFB 4,0,0,7,148,0,1,7,149,1,0,4,150,1,1,4,151 SPR3 DEFB 4,0,0,7,152,0,1,7,153,1,0,4,154,1,1,4,155 SPR4 DEFB 4,0,0,7,156,0,1,7,157,1,0,4,158,1,1,4,159 SPR5 DEFB 2,0,0,6,161,0,1,6,162


Каждая из строк SPR1... SPR4 соответствует одной из фаз движения человечка, а SPR5 - фрагменту лестницы. Последний используется не только для рисования лестниц в статической картинке, но и для восстановления изображения позади бегущего человечка. Формат данных в этих блоках вам уже знаком. Он выбран точно таким же, как и в программе ПРЫГАЮЩИЙ ЧЕЛОВЕЧЕК, следовательно, для вывода всех спрайтов на экран можно воспользоваться подпрограммой PUT, которую мы уже описали. Кроме блоков данных нам понадобятся еще несколько переменных, необходимых для управления перемещением человечков по экрану:

ROW DEFB 0 ;позиция по вертикали левого человечка DIRECT DEFB 0 ;направление движения POSIT DEFB 0 ;фаза движения

Позже мы объясним смысл этих переменных более подробно.

После того, как мы разобрались с надписями и спрайтами, можно переходить к основной программе, которая, как и в большинстве игр, содержит две части: статическую и динамическую. Первая устанавливает атрибуты экрана и формирует на нем все неподвижные элементы заставки: текст, лестницы и рамки вокруг них (Рисунок  5.7). Во многих играх вместо загрузки дополнительных фонтов новый набор символов формируется программой. Например, можно предложить следующий способ получения шрифта Bold, буквы в котором имеют утолщенное начертание:

BOLD LD HL,15616 ;адрес стандартного набора символов LD DE,END ;метка конца программы; по этому ; адресу расположится новый фонт LD BC,#300 ;счетчики циклов: B = 3, C = 0 (256) PUSH DE BOLD1 LD A,(HL) ;байт из стандартного набора SRL A ; смещаем на 1 бит (пиксель) влево OR (HL) ; и объединяем с его прежним значением LD (DE),A ;помещаем в новый фонт INC HL ;переходим к следующему байту INC DE DEC C JR NZ,BOLD1 ;в общей сложности повторяем цикл DJNZ BOLD1 ; 768 раз POP HL DEC H ;уменьшаем адрес нового шрифта на 256 LD (23606),HL ; и заносим в системную ; переменную CHARS RET



После получения нового шрифта можно сформировать на экране все неподвижные части заставки:

SCREEN LD B,3 ; Рисование окон WIND LD C,3 CALL STAIRS LD C,27 CALL STAIRS INC B LD A,B CP 19 JR C,WIND ; Рисование рамок вокруг лестниц LD DE,ATRBOX LD BC,4 CALL 8252 LD BC,#1414 ;B = 20, C = 20 CALL 8933 CALL BOX LD BC,#14D4 ;B = 20, C = 212 CALL 8933 CALL BOX ; Печать текста LD DE,TEXT LD BC,UDG-TEXT JP 8252 ; Данные атрибутов рамок ATRBOX DEFB 16,7,17,1 ; Рисование фрагмента лестницы STAIRS LD A,17 RST 16 XOR A RST 16 LD HL,SPR5 JP PUT ; Рисование рамок BOX EXX PUSH HL LD BC,#8700 ;B = 135, C = 0 LD DE,#101 ;D = 1, E = 1 CALL 9402 LD BC,23 ;B = 0, C = 23 CALL 9402 LD BC,#8700 LD D,-1 CALL 9402 LD BC,23 LD E,-1 CALL 9402 POP HL EXX RET



Подпрограмма SCREEN не содержит ничего такого, что бы нами еще не рассматривалось, поэтому отдельно мы ее комментировать не будем, а ограничимся уже приведенными пояснениями и перейдем к динамической части заставки.

В первую очередь напишем подпрограмму, печатающую в заданной позиции экрана элемент, из которого составлена рамка вокруг всего изображения:

; Вывод на экран шарика цвета E в позицию BC PRINT LD A,22 RST 16 LD A,B DEC A RST 16 LD A,C DEC A RST 16 LD A,16 RST 16 LD A,E RST 16 LD A,160 RST 16 RET

Значительно сложнее заставить двигаться человечков, да чтобы они при этом еще переступали с ноги на ногу и поворачивались к вам то лицом, то спиной. Для этих целей введены переменные:

ROW - определяет вертикальную позицию левого человечка. Вертикальная координата правого легко вычисляется, так как они движутся в противофазе: когда один идет вверх, другой движется вниз и наоборот. Горизонтальные же координаты обоих человечков во время движения не изменяются.

DIRECT - задает направление движения также для левого человечка. Если она имеет значение 1, левый человечек идет вниз, а правый - вверх. При изменении направлений движения она меняет знак и становится равной минус 1 (255).

POSIT - сообщает программе, в какой из двух фаз выводить изображения человечков. При ее значении, равном 0, выводятся спрайты SPR2 и SPR4, а если она равна 1 - SPR1 и SPR3. Иными словами, эта переменная отвечает за то, на какую ногу в данный момент должен наступить каждый человечек.

Стоит сказать несколько слов о том, какими программными средствами изменяются эти переменные. Наиболее просто получается переключение переменной POSIT. Для этого достаточно использовать команду XOR 1, инвертирующую значение младшего бита. Чтобы изменить знак в переменной DIRECT, можно поступить следующим образом: инвертировать все ее биты, например, командой CPL, а затем увеличить ее на 1. Можно именно так и поступить, но лучше воспользоваться специальной командой, как раз предназначенной для изменения знака в аккумуляторе. Эта команда записывается мнемоникой NEG (Negative - отрицательный). Что касается ROW, то она изменяется простым сложением с переменной DIRECT.



Теперь приводим тексты соответствующих подпрограмм:

; Перемещение человечков MAN LD A,(ROW) LD B,A LD A,(DIRECT) LD D,A CP 1 ;проверка направления движения JR NZ,MAN1 CALL PRMAN1 LD E,17 ; нижняя граница координаты ROW JR MAN2 MAN1 CALL PRMAN2 LD E,3 ;верхняя граница координаты ROW MAN2 LD HL,POSIT ;изменение переменной POSIT LD A,(HL) XOR 1 LD (HL),A LD HL,ROW LD A,(HL) CP E ;проверка необходимости смены LD A,D ; направления движения JR NZ,MAN3 NEG ;изменение знака в аккумуляторе LD (DIRECT),A ;изменение переменной DIRECT MAN3 ADD A,(HL) ;изменение переменной ROW ; (адресуемой парой HL) LD (HL),A RET

; Левый человечек идет вниз, правый - вверх PRMAN1 DEC B ;координата ROW LD C,3 ;горизонтальная координата левого ; человечка LD HL,SPR5 ;восстановление фона CALL PUT INC B LD A,(POSIT) AND A LD HL,SPR1 JR NZ,PRM11 LD HL,SPR2 PRM11 CALL PUT LD A,22 ;вычисление вертикальной координаты SUB B ; правого человечка LD B,A LD C,27 ;горизонтальная координата правого ; человечка LD HL,SPR5 ;восстановление фона CALL PUT DEC B DEC B LD A,(POSIT) AND A LD HL,SPR4 JR Z,PRM12 LD HL,SPR3 PRM12 JP PUT

; Левый человечек идет вверх, правый - вниз PRMAN2 INC B INC B LD C,3 LD HL,SPR5 CALL PUT DEC B DEC B LD A,(POSIT) AND A LD HL,SPR3 JR NZ,PRM21 LD HL,SPR4 PRM21 CALL PUT LD A,19 SUB B LD B,A LD C,27 LD HL,SPR5 CALL PUT INC B LD A,(POSIT) AND A LD HL,SPR2 JR Z,PRM22 LD HL,SPR1 PRM22 JP PUT

Теперь объединим рассмотренные подпрограммы и напишем управляющую часть:

ORG 60000 ENT $ LD HL,UDG LD (23675),HL CALL BOLD LD A,15 LD (23693),A XOR A CALL 8859 CALL 3435 LD A,2 CALL 5633 ; Инициализация переменных LD A,4 LD (ROW),A LD A,1 LD (DIRECT),A LD (POSIT),A CALL SCREEN LD A,17 RST 16 XOR A RST 16 ; Начало динамической части заставки MAIN LD E,7 ;код цвета шариков, окаймляющих ; рабочий экран ; Вывод рамки, состоящей из разноцветных шариков MAIN1 LD B,22 ;в регистрах BC - координаты экрана MAIN2 LD C,1 CALL PRINT LD C,32 CALL PRINT DJNZ MAIN2 LD C,31 MAIN3 LD B,1 CALL PRINT LD B,22 CALL PRINT DEC C JR NZ,MAIN3 PUSH BC PUSH DE CALL MAN ;вывод очередной фазы движения ; человечков POP DE POP BC PUSH BC LD B,9 ;счетчик цикла задержки перемещения ; человечков MAIN4 PUSH BC LD BC,1 CALL 7997 POP BC ; Проверка нажатия клавиш от 0 до 4. Если нажаты - выход на EXIT LD A,(23560) CP "4"+1 JR NC,MAIN5 ;проверка >"4" (>="4"+1) CP "0" JR NC,EXIT MAIN5 DJNZ MAIN4 POP BC DEC E JR NZ,MAIN1 JR MAIN EXIT LD (KEY),A ;сохраняем код клавиши для других ; частей многокадровой заставки, ; принцип построения которой будет ; рассмотрен в следующей главе POP BC RET ; Подпрограммы

; Блоки данных

; Переменные ROW DEFB 0 DIRECT DEFB 0 POSIT DEFB 0 KEY DEFB 0 ; Адрес размещения нового фонта (обязательно в самом конце, ; чтобы коды набора не перекрыли коды программы) END


Содержание раздела