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

       

ПОСТРОЕНИЕ ПЕЙЗАЖЕЙ



ПОСТРОЕНИЕ ПЕЙЗАЖЕЙ

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

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

LD A,40 ;INK 0, PAPER 5 LD (23693),A CALL 3435

и требуемый фон готов. Несколько сложнее обстоят дела с космическим пространством. То есть, задать черный цвет «бумаги» никакой проблемы не составит, но вот со звездами не все так просто. Можно, конечно, нарисовать и закодировать маленькие спрайты и даже заставить их случайным образом вспыхивать (особенно хорошо выглядит задание повышенной яркости в фазе максимума). Но ведь каждый спрайт-звездочка - это целое знакоместо, поэтому много ли их можно разместить на экране. Значительно лучше смотрятся звездочки размером в пиксель, как, например, в игре ELITE, но тут уже требуется небольшая программка, которую мы предлагаем вам написать самостоятельно.

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


ORG 60000 ENT $ LD A,5 LD (23693),A XOR A CALL 8859 CALL 3435 ; Вывод восьми спрайтов «трава» LD B,8 ;задаем количество выводимых ; спрайтов «трава» LD HL,DATA1 ;читаем адрес блока координат LD DE,TRAW CALL POSIT ; Вывод трех спрайтов «куст» LD B,3 LD HL,DATA2 LD DE,KUST CALL POSIT ; Вывод спрайта «человечек» LD B,1 LD HL,DATA3 LD DE,MAN ; Подпрограмма начальной установки регистров для процедуры PTBL POSIT PUSH BC LD B,(HL) ;устанавливаем Y INC HL LD C,(HL) ;устанавливаем X INC HL PUSH HL PUSH DE EX DE,HL LD A,SPRPUT ;вывод с наложением CALL PTBL POP DE POP HL POP BC DJNZ POSIT RET

; Задание пар координат (Y,X) для вывода восьми спрайтов «трава» DATA1 DEFB 17,0,17,4,17,8,17,12,17,16 DEFB 17,20,17,24,17,28 ; Заголовок спрайта «трава» TRAW DEFB 4, 0,0,4, 0,1,4, 0,2,4, 0,3,4 ; Данные для спрайта «трава» DEFB 193,106,191,253,255,235,181,36 DEFB 18,170,247,255,255,94,107,41 DEFB 101,200,255,219,255,255,87,10 DEFB 18,170,247,255,255,95,107,41 ; Задание пар координат для печати трех спрайтов «куст» DATA2 DEFB 11,14,13,14,15,14 ; Заголовок спрайта «куст» KUST DEFB 4, 0,0,6, 0,1,4, 1,0,6, 1,1,4 ; Данные для спрайта «куст» DEFB 33,12,102,242,185,13,53,121 DEFB 56,100,192,218,160,134,157,56 DEFB 29,204,110,28,54,182,87,91 DEFB 50,112,119,238,236,234,90,84 ; Пара координат для вывода «человечка» DATA3 DEFB 14,23 ; Заголовок спрайта «человечек» MAN DEFB 6, 0,0,5, 0,1,5, 1,0,5 DEFB 1,1,5, 2,0,5, 2,1,5 ; Данные для спрайта «человечек» DEFB 3,15,17,36,48,16,26,31 DEFB 192,240,248,56,132,60,120,240 DEFB 25,14,7,24,31,59,55,55 DEFB 240,192,184,124,244,246,250,194 DEFB 56,27,3,0,6,6,7,0 DEFB 26,104,160,144,48,36,184,0

Задание в виде отдельных блоков данных (DATA1...DATA3) пар координат, первая из которых соответствует вертикальной позиции спрайта, а вторая - горизонтальной, позволяет легко «разбрасывать» спрайты по всему экрану, создавая любые их комбинации. Вывод спрайтов осуществляется процедурой PTBL.



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

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

ORG 60000 LD IX,LAB_0 ;перед вызовом в IX заносится адрес ; данных лабиринта LABS1 LD C,(IX+1) ;позиция начального элемента по горизонтали LD B,(IX+2) ;позиция начального элемента по вертикали LD A,(IX+3) ;количество повторений и направление AND 31 JR Z,LABS5 ;если выводится одиночный элемент LD E,A LABS2 LD A,(IX) ;код символа (0...5) CALL PRINT ;вывод символа на экран BIT 7,(IX+3) ;проверка направления вывода JR NZ,LABS3 INC C ;слева направо JR LABS4 LABS3 INC B ;сверху вниз LABS4 DEC E ;следующий элемент JR NZ,LABS2 JR LABS6 LABS5 LD A,(IX) ;вывод одиночного элемента CALL PRINT LABS6 LD DE,4 ;увеличиваем адрес в блоке данных ADD IX,DE ; на 4 байта LD A,(IX) ;проверка на достижение конца блока данных INC A ;если -1 (255) JR NZ,LABS1 RET PRINT PUSH BC PUSH DE PUSH HL LD L,A ;по коду определяем адрес символа LD H,0 ADD HL,HL ADD HL,HL ADD HL,HL LD DE,D_SYMB ADD HL,DE PUSH HL LD A,B ;вычисляем адрес видеобуфера CALL 3742 LD A,L ADD A,C LD L,A POP DE LD B,8 PUSH HL PRINT1 LD A,(DE) ;переносим на экран 8 байт LD (HL),A INC DE INC H DJNZ PRINT1 POP HL ;восстанавливаем начальный адрес экрана LD A,H ;рассчитываем адрес атрибутов ; соответствующего знакоместа AND #18 RRCA RRCA RRCA ADD A,#58 LD H,A LD A,(23695) ;записываем байт атрибутов в видеобуфер LD (HL),A POP HL POP DE POP BC RET ; Данные для построения лабиринта (рамки) ; IX+0 - номер символа в таблице D_SPR (0..5) ; IX+1 - начальная позиция экрана по горизонтали ; IX+2 - начальная позиция экрана по вертикали ; IX+3 - младшие 5 битов - количество повторений вывода символа, ; 7-й бит определяет направление вывода: ; установлен - сверху вниз (задается символами @#80), ; сброшен - слева направо LAB_0 DEFB 0,2,8,0, 1,3,8,2 DEFB 2,5,8,0, 3,5,9,0 DEFB 5,5,10,0, 1,6,10,20 DEFB 3,2,9,2@#80, 5,2,11,0 DEFB 1,3,11,0, 2,4,11,0 DEFB 3,4,12,8@#80, 4,4,20,0 DEFB 1,3,20,0, 0,2,20,0 DEFB 3,2,21,2@#80, 5,2,23,0 DEFB 1,3,23,2, 4,5,23,0 DEFB 3,5,22,0, 0,5,21,0 DEFB 1,6,21,20, 4,26,10,0 DEFB 3,26,9,0, 0,26,8,0 DEFB 1,27,8,2, 2,29,8,0 DEFB 3,29,9,2@#80, 4,29,11,0 DEFB 1,28,11,0, 0,27,11,0 DEFB 2,26,21,0, 3,26,22,0 DEFB 5,26,23,0, 1,27,23,2 DEFB 4,29,23,0, 3,29,21,2@#80 DEFB 2,29,20,0, 1,28,20,0 DEFB 5,27,20,0, 3,27,12,8@#80 DEFB 0,3,9,0, 2,4,9,0 DEFB 4,4,10,0, 5,3,10,0 DEFB 0,27,9,0, 2,28,9,0 DEFB 4,28,10,0, 5,27,10,0 DEFB 0,27,21,0, 2,28,21,0 DEFB 4,28,22,0, 5,27,22,0 DEFB 0,3,21,0, 2,4,21,0 DEFB 4,4,22,0, 5,3,22,0 DEFB -1 ;конец данных ; Данные символов (элементов лабиринта) D_SYMB DEFB 127,213,159,191,253,182,248,181 DEFB 255,85,255,255,85,170,0,255 DEFB 254,83,249,245,121,181,121,181 DEFB 249,181,249,181,249,181,249,181 DEFB 249,117,249,245,81,169,3,254 DEFB 249,189,255,191,213,170,192,127

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

Прежде чем перейти к следующему разделу, поясним встретившуюся в блоке данных LAB_0 не очень понятную запись @#80. В комментарии было сказано, что это означает установку 7-го бита в числе. Дело в том, что ассемблер GENS помимо простых арифметических операций сложения, вычитания, умножения и деления предоставляет возможность использования в выражениях поразрядных операций OR, XOR и AND. Обозначаются они соответственно символами @, ! и &. Поэтому, например, выражение 2@#80 (2 OR #80) примет значение #82 или 130, а запись %101!%110 (%101 XOR %110) после вычислений заменится числом %011 или 3.


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