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

             

Программа БИТВА С НЛО



Рисунок 10.1. Программа БИТВА С НЛО

Вначале создадим акустическое сопровождение программы. Нам понадобятся такие звуки: выстрелы с обеих сторон, попадания в НЛО и в лазерную установку, а также соударение НЛО со «стенкой», ограничивающей игровое поле. Учитывая характер звуков, а также и то, что шум можно выводить только в один из каналов, составим блоки данных по правилам, описанным выше.

Начнем с выстрелов управляемой игроком лазерной установки. Для получения этого звука используем «белый» шум. Этот и следующий звуки закрепим за каналом музыкального сопроцессора A.

D_SND1 DEFB 1 DEFW FREQ1 DEFB 2 DEFW ENV1 DEFB 3,8,2,3,8,1,0 FREQ1 DEFB 129,0,130,5,131 ;изменение частоты ENV1 DEFB 15,14,12,128 ;изменение громкости

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

D_SND2 DEFB 1 DEFW FREQ2 DEFB 2 DEFW ENV2 DEFB 3,1,2,1 DEFW FREQ3 DEFB 3,8,20,0 FREQ2 DEFB 128 DEFW 1000 DEFB 130,10,131 FREQ3 DEFB 129,3,130,1,131 ENV2 DEFB 15,14,15,12,15,14,12,10,14,12 DEFB 9,8,7,6,5,4,3,2,11,0,128

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

D_SND3 DEFB 1 DEFW FREQ4 DEFB 2 DEFW ENV3 DEFB 3,1,15,0 FREQ4 DEFB 128 DEFW 200 DEFB 130,20,131 ENV3 DEFB 15,14,14,13,12,12,11,128

Звук, подражающий попаданию в НЛО, должен быть более протяжным, поэтому и блок данных, описывающий огибающую окажется несколько длиннее:

D_SND4 DEFB 1 DEFW FREQ5 DEFB 2 DEFW ENV4 DEFB 3,1,24,0 FREQ5 DEFB 128 DEFW 700 DEFB 130,100,131 ENV4 DEFB 15,14,14,15,15,12,10,11,8,7 DEFB 7,5,6,7,10,12,14,15,10,8,128

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


D_SND5 DEFB 1 DEFW FREQ6 DEFB 2 DEFW ENV5 DEFB 3,1,9, 0 FREQ6 DEFB 128 DEFW 20 DEFB 130,10,-15,40,-30,-5,131 ENV5 DEFB 15,9,12,10,15,13,128



В игре нам понадобится создать изображения грузовика и НЛО. Общую часть программы мы собираемся написать на Бейсике, поэтому проще всего для вывода графических изображений вновь обратиться к символам UDG. Можно было бы закодировать их и в бейсик-программе, но, во-первых, как вы знаете, циклы в интерпретаторе - самое больное место и выполняются они в десятки, если не в сотни раз медленнее, чем в машинных кодах. Но самое главное даже не в этом, а в том, что область памяти, в которой располагаются коды определяемых символов, занята командами перехода на процедуру обработки прерываний (адреса 65524...65526 и 65535, соответствующие положению последних двух символов - T и U). Поэтому, чтобы застраховаться от неожиданностей, коды символов лучше расположить в ассемблерной части программы, что мы и делаем:

SETUDG LD HL,UDG LD (23675),HL RET ; НЛО (A, B, C и D) UDG DEFB 1,65,32,23,13,27,59,55 DEFB 128,130,4,232,240,248,252,252 DEFB 127,125,0,173,173,0,7,1 DEFB 254,190,0,181,181,0,224,128 ; Лазерная установка (E, F, G, H, I и J) DEFB 173,97,191,127,191,127,192,158 DEFB 199,207,201,201,207,207,207,79 DEFB 252,254,35,33,225,225,255,255 DEFB 63,97,204,146,173,37,18,12 DEFB 1,126,255,126,126,0,0,0 DEFB 254,134,51,73,181,148,72,48

Теперь остается собрать все подпрограммы в один блок так, чтобы их удобно было вызывать из Бейсика. Кроме того, допишем недостающие процедуры инициализации звуков:

ORG 60000 ; 60000 - включение 2-го режима прерываний и инициализация массива DATREG JP INITI ; 60003 - выключение 2-го режима прерываний и звука JP STOPI ; 60006 - выстрел лазерной установки JP SND1 ; 60009 - попадание в лазерную установку JP SND2 ; 60012 - выстрел НЛО JP SND3 ; 60015 - попадание в НЛО JP SND4 ; 60018 - соударение НЛО со «стенкой» JP SND5 ; 60021 - символы UDG

SND5 LD HL,D_SND5 LD (CHAN_C),HL LD (CHAN_C+2),HL LD A,1 LD (CHAN_C+9),A LD (CHAN_C+8),A LD (CHAN_C+7),A RET SND4 LD HL,D_SND4 JR SND3_1 SND3 LD HL,D_SND3 SND3_1 LD (CHAN_B),HL LD (CHAN_B+2),HL LD A,1 LD (CHAN_B+9),A LD (CHAN_B+8),A LD (CHAN_B+7),A RET SND2 LD HL,D_SND2 LD A,1 JR SND1_1 SND1 LD HL,D_SND1 LD A,3 SND1_1 LD (CHAN_A),HL LD (CHAN_A+2),HL LD (CHAN_A+9),A LD A,1 LD (CHAN_A+8),A LD (CHAN_A+7),A RET ; Блоки данных, описывающие каждый из пяти используемых в программе звуков



; Далее следуют уже описанные процедуры прерывания

А вот бейсик-программа самой игры:

10 REM *** НЛО *** 20 BORDER 0: PAPER 0: INK 7: CLEAR 59999 30 RANDOMIZE USR 15619 : REM : LOAD "snd_ufo"CODE 40 LET cd=USR 60021: REM *** UDG *** 50 LET cd=USR 60000: REM *** Прерывания *** 60 REM -------------- 70 CLS 80 FOR n=19 TO 20: PRINT AT n,0; PAPER 4; TAB 31;" ": NEXT n 90 FOR n=0 TO 18: PRINT AT n,0; PAPER 4;" ";AT n,31;" ": NEXT n 100 LET kl=0: LET ik1=7: LET ik2=ik1: LET pow=0: LET pow1=pow: LET x1=4: LET y1=1: LET w=0: LET xp=0: LET yp=0: LET s1=10: LET s=10: LET x=4: LET y=1 110 LET a$=INKEY$ 120 IF a$="p" AND s<28 THEN LET s=s+1: GO TO 180 130 IF a$="o" AND s>1 THEN LET s=s-1: GO TO 190 140 IF a$=" " THEN LET cd=USR 60006: GO TO 230 150 IF a$="e" THEN LET cd=USR 60003: STOP 160 REM -------------- 170 GO TO 200 180 PRINT AT 17,s1;" ";AT 18,s1;" ": GO TO 200 190 PRINT AT 17,s1+2;" ";AT 18,s1+2;" " 200 INK 6: PRINT AT 17,s;"EFG";AT 18,s;"HIJ" 210 LET s1=s 220 LET ik2=7: GO TO 280 230 IF INT x=s OR INT x+1=s THEN LET yy=INT y+1: LET pow1=pow1+1: LET cd=USR 60015: LET ik2=2: GO TO 250 240 LET yy=0 250 GO SUB 270: OVER 1: GO SUB 270: OVER 0 260 GO TO 280 270 INK 7: PLOT s*8+5,41: DRAW 0,126-yy*8: RETURN 280 REM ----- нло ---- 290 IF w=0 THEN LET xp= (RND*1.5+.5): LET yp= (RND*1.5): LET w=INT (RND*25+5): LET xp=xp*SGN (RND*4-2): LET yp=yp*SGN (RND*4-2) 300 IF x+xp>=1 AND x+xp<30 AND y+yp>=0 AND y+yp<=12 AND w>0 THEN LET x=x+xp: LET y=y+yp: LET w=w-1: LET kl=0: GO TO 330 310 IF ((INT (x+xp)<1 AND INT x=1) OR (INT x=29 AND INT (x+xp)>29)) AND kl=0 THEN LET kl=1: LET cd=USR 60018 320 LET w=0: GO TO 290 330 PRINT AT INT y1,INT x1;"··";AT INT y1+1,INT x1;"··" 340 INK 5: PRINT AT INT y,INT x;"AB";AT INT y+1,INT x;"CD" 350 LET x1=x: LET y1=y 360 IF RND*10<3 THEN LET cd=USR 60012: LET xf=RND*255: GO SUB 410: OVER 1: GO SUB 410: OVER 0: LET xf1=INT (xf/8): IF xf1=s OR xf1=s+1 OR xf1=s+2 THEN LET pow=pow+1: LET cd=USR 60009: LET ik1=2: GO TO 380 370 LET ik1=7 380 PRINT AT 21,1; INK ik2;"Score car:";INT pow1;" " 390 PRINT AT 21,19; INK ik1;"Score ufo:";INT pow;" " 400 GO TO 110 410 INK 2: PLOT INT (x)*8+7,159-INT (y)*8: DRAW xf-(INT (x)*8+7),25-(159-INT (y)*8): RETURN



Прокомментируем немного строки этой программы и поясним значение некоторых переменных.


    40 - «включение» символов UDG;

    50 - включение 2-го режима прерываний;

    80...90 - рисование грунта;

    100 - задание начальных значений переменных:


    kl - управление звуком при подлете НЛО к стенке (kl=0 - звук разрешен, kl=1 - запрещен);

    ik1, ik2 - цвет надписей;

    pow - количество попаданий НЛО;

    pow1 - количество попаданий автомобиля;

    x1, y1 - координаты для удаления предыдущего изображения НЛО;

    w - количество перемещений НЛО до изменения направления движения;

    xp, yp - приращения координат НЛО;

    s1 - координата для удаления предыдущего изображения автомобиля;

    s - текущая координата автомобиля;

    x, y - текущие координаты НЛО.


110...150 - опрос клавиатуры;

180...200 - восстановление фона позади движущегося автомобиля и перемещение его в новое положение;

230 - проверка попадания луча лазера в НЛО;

250 - рисование луча лазера;

290...400 - управление полетом НЛО;

410 - рисование следа от выстрела НЛО.


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