Следующий регистр - R6 - определяет среднюю частоту выводимого шума. Поскольку получение шумовых эффектов одновременно в разных голосах не имеет практического применения (их все равно невозможно будет различить на слух), то этот регистр является общим для всех трех каналов. Для него можно задавать значения от 0 до 31, то есть значащими являются только пять младших битов. Регистр R7 служит для управления звуковыми каналами. Он подобен флаговому регистру центрального процессора и значение имеет каждый отдельный бит. Младшие три бита используются для управления выводом чистого тона в каждый из трех каналов. Если бит установлен, вывод запрещен, а при сброшенном бите вывод звука разрешается. Бит 0 связан с каналом A, 1-й бит относится к каналу B и 2-й - к C. Биты 3, 4 и 5 заведуют выводом в каналы A, B и C соответственно частоты «белого» шума. При установке бита вывод также запрещается, а при сбросе его в 0 - разрешается. 6-й и 7-й биты для извлечения звука значения не имеют. Регистры R8, R9 и R10 определяют громкость звука, выводимого соответственно в каналы A, B и C. С их помощью можно получить 16 уровней громкости, посылая в них значения от 0 до 15. То есть значение для получаемой амплитуды в этих регистрах имеют 4 младших бита. Однако следует знать еще об одной интересной особенности этих трех регистров. Если в каком-нибудь из них установить 4-й бит (например, послав в него число 16), то получится звук не с постоянной, а с изменяющейся во времени громкостью. В этом случае необходимо указать дополнительную информацию в регистрах R11, R12 и R13. Спаренные регистры R11 и R12 задают скорость изменения громкости звука: чем больше число, тем более плавной будет огибающая. В них можно записывать значения от 0 до 65535. Надо сказать, что изменение младшего регистра почти не ощущается, поэтому чаще достаточно определять лишь регистр R12. Регистр R13 формирует огибающую выходного сигнала. Установкой одного или нескольких битов из младшей четверки можно получить несколько разнообразных эффектов. При установке нулевого бита звук получается затухающим, если установить 2-й бит, громкость будет наоборот увеличиваться, а установив одновременно 1-й и 3-й биты, вы получите звук, постоянно изменяющийся по громкости. Последними тремя регистрами действительно иногда бывает удобно пользоваться, хотя гораздо чаще огибающая формируется программным путем, что позволяет получить значительно большее разнообразие оттенков звучания. Перейдем теперь к вопросу, как программируются регистры музыкального сопроцессора. Связь с ними осуществляется через порты с адресами 49149 (#BFFD) и 65533 (#FFFD). Чтобы записать какое-либо значение в любой из регистров, его необходимо прежде всего выбрать (или назначить), выполнив команду OUT в порт 65533. Например, регистр R8 выбирается следующими командами: LD BC,65533 ;в паре BC - адрес порта ; для выбора регистра LD A,8 ;в аккумуляторе - номер регистра OUT (C),A ;выборПосле этого в выбранный регистр можно записывать данные либо читать его содержимое. Для записи используется порт 49149, а для чтения - опять же 65533. Приведем фрагмент программы, в котором читается значение установленного ранее регистра и если оно не равно 0, содержимое регистра уменьшается на единицу: LD BC,65533 ;адрес порта для чтения IN A,(C) ;читаем значение текущего регистра JR Z,ZERO ;если 0, обходим DEC A ;уменьшаем на 1 ; Выбираем порт 49149 для записи ; (значение регистра C остается прежним - #FD) LD B,#BF OUT (C),A ;записываем значение в выбранный регистр ZERO ......... ;продолжение программыДобавим к сказанному, что выбор регистров музыкального сопроцессора и все манипуляции с ними лучше производить при запрещенных прерываниях, хотя в приведенных примерах это и не отражено. Можно написать универсальную подпрограмму, которая считывает из блока данных значения всех регистров и тем самым задает параметры звуков одновременно для всех трех каналов: OUTREG DI ;запрещаем прерывания ; Данные будем считывать из массива DATREG ; в обратном порядке, начиная с последнего элемента LD HL,DATREG+13 LD D,13 ;начальный номер загружаемого регистра LD C,#FD ;младший байт адреса порта сопроцессора OUTR1 LD B,#FF ;адрес для выбора регистра OUT (C),D ;выбираем регистр LD B,#BF ;адрес для записи в регистр ; Записываем в порт байт из ячейки, адресуемой парой HL, ; и уменьшаем HL на 1 OUTD DEC D ;переходим к следующему регистру ; (с меньшим номером) JP P,OUTR1 ;повторяем, если записаны еще не все ; регистры (D >= 0) EI ;разрешаем прерывания RET DATREG DEFS 14 ;массив данных для регистров сопроцессораЭта процедура вполне может быть использована как для получения отдельных звуковых эффектов, так и для создания музыкальных произведений. Основная сложность заключается в написании программы, которая бы изменяла соответствующим образом элементы массива DATREG и тем самым управляла работой сопроцессора. Чтобы получить действительно первоклассное звучание, потребуется достаточно серьезная программа, которую объем книги, к сожалению, не позволяет здесь привести (надеемся, ее все же удастся включить в одну из последующих книг серии «Как написать игру»). Поэтому мы предлагаем более простую процедуру, извлекающую отдельные звуки, характер которых, тем не менее, вы сможете изменять практически в неограниченных пределах. (Упомянутая музыкальная программа строится, в общем, по такому же принципу, что и приводимая здесь процедура. Поэтому после ее досконального изучения вы можете попытаться самостоятельно написать программу, пригодную для исполнения музыкальных произведений.) Эту программу также лучше составить в виде прерывания, чтобы можно было получать звуки любой продолжительности и не отвлекаться на их формирование в основной программе. Начнем с выяснения, какие переменные нам здесь потребуются. Помимо уже известных по предыдущему примеру значений базового и текущего адресов в блоке данных, описывающем характер звучания и флага разрешения вывода звука понадобятся переменные, задающие частоту тона и шума, длительность звучания, количество повторений эффекта, флаг разрешения вывода в канал тона или шума. Кроме этого, необходимо каким-то образом задавать огибающую звука и характер изменения высоты тона или шума. Эти две последние характеристики должны изменяться независимо друг от друга, поэтому порядок их изменения лучше всего определять в двух дополнительных блоках данных. То есть к перечисленным переменным добавятся еще четыре: базовые и текущие адреса для каждого из этих двух блоков. В связи с обилием переменных, а также и с тем, что все они должны иметься в трех экземплярах - для каждого канала по полному набору - лучше всего свести их в таблицу, начало которой передавать в регистре IX. Построим такую таблицу с указанием смещений от начала и значений каждого смещения: 0/1 - базовый адрес блока данных эффекта 2/3 - текущий адрес в блоке данных 4/5 - частота тона 6 - частота шума 7 - флаг разрешения вывода в канал 8 - длительность звучания эффекта 9 - количество повторений эффекта 10 - вывод тона (1), шума (8) или их комбинации (9) 11/12 - базовый адрес данных для формирования частоты 13/14 - текущий адрес данных для формирования частоты 15/16 - базовый адрес данных для формирования огибающей 17/18 - текущий адрес данных для формирования огибающейПоскольку задавать все значения переменных в основной программе немыслимо, они должны быть определены в блоках данных, а чтобы иметь возможность устанавливать их выборочно (ведь, например, при выводе чистого тона частота шума не имеет значения), используем принцип управляющих кодов. В основном блоке данных будем определять адреса двух дополнительных блоков и заказывать выводимый звук - чистый тон, шум или их комбинацию, а также длительность звучания эффекта: 0 - конец данных (возврат на повторение эффекта) 1 - адрес данных для изменения тона (+2 байта адреса) 2 - адрес данных для формирования огибающей (+2 байта адреса) 3 - управление выводом тона/шума (+2 байта: 1-й определяет вывод тона, шума или комбинированный вывод, 2-й - длительность звучания)Когда программа встретит код 0, вывод звука либо прекратится, либо весь эффект повторится еще раз - в зависимости от заданного изначально количества повторений. Следующие два байта после кодов 1 или 2 интерпретируются как адреса дополнительных блоков данных, определяющих характер изменения частоты звука и огибающей соответственно. С этих двух кодов должен начинаться любой блок данных, иначе программа не будет «знать», каким образом изменять звук. Последний код (3) служит собственно для извлечения звука. После него необходимо указать еще два однобайтовых параметра: первый задает вывод тона (1), шума (8) либо одновременно и тона и шума (9), второй определяет продолжительность заданного звука в 50-х долях секунды. В дополнительных блоках данных также используем некоторые управляющие коды. После байта со значением 128 будет задаваться двухбайтовая величина частоты тона (см. табл. 10.1), а за кодом 129 последует байт средней частоты шума, который может иметь значения от 0 (самый высокий звук) до 31 (самый низкий). Определив частоты, можно поставить метку начала их изменения, поставив код 130. Далее должны следовать значения приращения частоты, которые лежат в диапазоне от -124 до +127. За один такт прерываний (1/50 секунды) будет выполнен один из этих кодов. Завершаться этот блок данных должен кодом 131, после которого все составляющие его числа будут проинтерпретированы с начала или от кода 130, если таковой был использован. Соберем все коды данных для изменения частоты воедино: 128 - задание частоты тона (+2 байта частоты тона) 129 - задание частоты шума (+1 байт частоты шума) 130 - метка повторения эффекта 131 - возврат на начало или метку -124...+127 - приращение частотыВ блоке данных для формирования огибающей будет использован только один управляющий код 128, отмечающий конец интерпретации записанных значений и переход на повторение эффекта. Остальные коды, задающие громкость звука, могут передаваться числами от 0 до 15. Каждое из этих чисел также обрабатывается за одно прерывание. 128 - возврат на начало данных огибающей 0...15 - значение громкостиПрежде чем продолжить, хочется обратить ваше внимание на то, что при построении собственных блоков данных необходимо следить за порядком следования управляющих кодов, иначе результат будет очень далек от ожидаемого. Кроме того, ни один из блоков не может состоять только из управляющих кодов, поскольку в этом случае компьютер просто «зависнет». Выяснив, что мы хотим в итоге получить, напишем процедуру для интерпретации описанных блоков данных. Она имеет довольно внушительные размеры, но все же попытайтесь с ней разобраться. На входе перед обращением к ней в аккумуляторе задается номер канала (0 для A, 1 для B и 2 для C), а индексный регистр IX, как мы уже говорили, адресует таблицу переменных соответствующего канала: GETSND LD (N_CHAN),A ;запоминаем номер канала LD A,(IX+7) AND A RET Z ;выход, если вывод в канал не разрешен DEC (IX+8) ;уменьшаем счетчик длительности звука JR NZ,GETS5 LD L,(IX+2) ;текущий адрес основного блока данных LD H,(IX+3) GETS1 LD A,(HL) INC HL AND 3 JR NZ,GETS2 ; Код 0 - возврат на повторение эффекта LD A,(IX+11) ;установка текущего адреса LD (IX+13),A ; данных изменения частоты LD A,(IX+12) ; на начало LD (IX+14),A ; блока LD L,(IX) ;начальный адрес основного LD H,(IX+1) ; блока данных DEC (IX+9) ;уменьшение количества повторений JR NZ,GETS1 XOR A ;завершение звучания в канале LD (IX+7),A ;запрет вывода звука в канал LD (IX+10),A LD A,(N_CHAN) ADD A,8 LD E,A XOR A JP SETREG ;выключение громкости GETS2 DEC A JR NZ,GETS3 ; Код 1 - адрес данных для изменения тона LD A,(HL) ;младший байт адреса LD (IX+11),A INC HL LD A,(HL) ;старший байт адреса LD (IX+12),A INC HL JR GETS1 GETS3 DEC A JR NZ,GETS4 ; Код 2 - адрес данных для формирования огибающей LD A,(HL) ;младший байт адреса LD (IX+15),A LD (IX+17),A INC HL LD A,(HL) ;старший байт адреса LD (IX+16),A LD (IX+18),A INC HL JR GETS1 ; Код 3 - управление выводом тона/шума GETS4 LD A,(HL) ;1 - тон, 8 - шум, 0 - пауза, ; 9 - тон и шум одновременно INC HL AND 9 LD (IX+10),A LD A,(HL) ;продолжительность вывода INC HL LD (IX+8),A LD (IX+2),L LD (IX+3),H ; Восстановление текущего адреса данных для изменения тона LD A,(IX+11) LD (IX+13),A LD A,(IX+12) LD (IX+14),A GETS5 LD L,(IX+13) LD H,(IX+14) GETS6 LD A,(HL) INC HL CP 128 ;задание частоты тона JR NZ,GETS7 LD A,(HL) LD (IX+4),A INC HL LD A,(HL) AND 15 LD (IX+5),A INC HL JR GETS6 GETS7 CP 129 ;задание частоты шума JR NZ,GETS8 LD A,(HL) AND 31 LD (IX+6),A JR GETS6 GETS8 CP 130 ;метка нового начала JR NZ,GETS9 LD (IX+11),L LD (IX+12),H JR GETS6 GETS9 CP 131 ;возврат к началу JR NZ,GETS10 LD L,(IX+11) LD H,(IX+12) JR GETS6 ; Изменение частоты звука или шума GETS10 LD (IX+13),L LD (IX+14),H LD D,0 BIT 7,A JR Z,GETS11 LD D,255 GETS11 LD E,A LD L,(IX+4) LD H,(IX+5) ADD HL,DE LD (IX+4),L LD (IX+5),H ADD A,(IX+6) LD (IX+6),A ; Определение элементов массива DATREG, задающих частоту LD (DATREG+6),A ;частота шума LD A,(N_CHAN) ADD A,A LD E,A LD A,L PUSH HL CALL SETREG ;младший байт частоты тона POP HL INC E LD A,H CALL SETREG ;старший байт частоты тона ; Формирование огибающей LD L,(IX+17) LD H,(IX+18) GETS12 LD A,(HL) INC HL CP 128 ;повторение с начала JR NZ,GETS13 LD L,(IX+15) LD H,(IX+14) JR GETS12 GETS13 LD (IX+17),L LD (IX+18),H AND 15 PUSH AF LD A,(N_CHAN) ADD A,8 LD E,A POP AF JP SETREG ;задание громкости звукаВ процедуре обработки прерываний приведенная подпрограмма будет вызываться трижды для определения характера звучания в каждом из трех каналов независимо друг от друга. Это дает возможность использовать в программе одновременно три самостоятельных источника звука, закрепив за каждым игровым объектом свой звуковой канал. Правда, здесь есть одно небольшое ограничение: поскольку средняя частота «белого» шума общая для всех трех каналов, то его лучше выводить только в какой-то один, а другие два использовать для вывода изменяющегося тона. Вот описываемая процедура обработки прерываний: SND128 PUSH AF PUSH BC PUSH DE PUSH HL PUSH IX CALL NXTSND POP IX POP HL POP DE POP BC POP AF JP 56 NXTSND LD IX,CHAN_A XOR A CALL GETSND ;задание переменных для канала A LD IX,CHAN_B LD A,1 CALL GETSND ;задание переменных для канала B LD IX,CHAN_C LD A,2 CALL GETSND ;задание переменных для канала C ; Вычисление значения регистра R7, ; управляющего выводом в каналы тона и шума LD A,(CHAN_C+10) AND 9 ;выделяем биты 0 и 3 RLCA ;сдвигаем влево LD B,A ;результат сохраняем в регистре B LD A,(CHAN_B+10) AND 9 ;то же самое для других двух каналов OR B RLCA LD B,A LD A,(CHAN_A+10) AND 9 OR B CPL ;инвертируем биты LD E,7 ;устанавливаем данные регистра R7 в DATREG CALL SETREG ; Извлечение звука OUTREG LD HL,DATREG+13 LD D,13 LD C,#FD OUTR1 LD B,#FF OUT (C),D LD B,#BF OUTD DEC D RET M ;выход, если D < 0 JR OUTR1 DATREG DEFS 14 ; Задание элемента E массива DATREG значением из аккумулятора SETREG LD HL,DATREG LD D,0 ADD HL,DE LD (HL),A RET N_CHAN DEFB 0 ;номер текущего канала ; Таблицы переменных для каждого канала CHAN_A DEFS 19 CHAN_B DEFS 19 CHAN_C DEFS 19Наше прерывание остается дополнить процедурами включения и выключения 2-го режима. Попутно желательно выполнить и некоторые другие действия, а именно, при установке 2-го режима нужно очистить все три таблицы переменных, инициализировав их нулевым байтом, а при возврате первого режима прерываний необходимо еще убедиться, что звук выключен: INITI LD HL,CHAN_A ;инициализация таблиц переменных LD DE,CHAN_A+1 LD BC,19*3-1 LD (HL),0 LDIR LD HL,SND128 ;установка прерывания IMON ......... STOPI CALL IMOFF ;возврат к 1-му режиму LD A,#FF ;выключение звука LD E,7 CALL SETREG ;запись в регистр сопроцессора R7 ; значения #FF JP OUTREG IMOFF .........Порядок действий при использовании описанной программы должен быть следующим. В начале работы нужно включить 2-й режим прерываний, вызвав процедуру INITI. Извлечение очередного звука необходимо начинать с определения некоторых переменных в таблицах CHAN_A, CHAN_B или CHAN_C. Для этого нужно записать в первые два байта таблицы, соответствующей выбранному каналу, адрес начала основного блока данных и то же значение продублировать в следующих двух байтах таблицы. Затем указать количество повторений звука по смещению +9, а элементы таблицы +8 и +7 инициализировать байтом 1 (переменную по смещению +7 нужно задавать обязательно в последнюю очередь, так как именно она «запускает» звук). По окончании работы (или если в программе предусмотрены обращения к дисководу) следует восстановить стандартный режим обработки прерываний и выключить звук, обратившись к подпрограмме STOPI. Продемонстрируем применение описанной процедуры извлечения звуков на примере небольшой игры, которую назовем БИТВА С НЛО. По земле катается грузовик с зенитной лазерной установкой, который методично расстреливает маячащую в небе «летающую тарелку» (рис. 10.1). НЛО также не остается внакладе и отвечает хоть и малоприцельным, но зато плотным веерным огнем.
Рис. 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 SETUDG ......... 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 ; Блоки данных, описывающие каждый из пяти используемых в программе звуков D_SND1 ......... D_SND2 ......... D_SND3 ......... D_SND4 ......... D_SND5 ......... ; Далее следуют уже описанные процедуры прерывания INITI ......... STOPI ......... SND128 ......... NXTSND ......... OUTREG ......... SETREG ......... GETSND .........А вот бейсик-программа самой игры: 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Прокомментируем немного строки этой программы и поясним значение некоторых переменных.
50 - включение 2-го режима прерываний; 80...90 - рисование грунта; 100 - задание начальных значений переменных:
ik1, ik2 - цвет надписей; pow - количество попаданий НЛО; pow1 - количество попаданий автомобиля; x1, y1 - координаты для удаления предыдущего изображения НЛО; w - количество перемещений НЛО до изменения направления движения; xp, yp - приращения координат НЛО; s1 - координата для удаления предыдущего изображения автомобиля; s - текущая координата автомобиля; x, y - текущие координаты НЛО. 180...200 - восстановление фона позади движущегося автомобиля и перемещение его в новое положение; 230 - проверка попадания луча лазера в НЛО; 250 - рисование луча лазера; 290...400 - управление полетом НЛО; 410 - рисование следа от выстрела НЛО.
МУЗЫКАЛЬНЫЙ РЕДАКТОР WHAM FXКодирование вручную звуковых эффектов, а тем более - музыки, дело весьма утомительное. Хотя такой способ при наличии определенного опыта в конечном итоге и дает наилучшие результаты, но для начинающих он мало пригоден. А что говорить о простых пользователях, общающихся с компьютером только на уровне игровых или, в лучшем случае, прикладных программ. Поэтому стоит сказать хотя бы несколько слов о программе, специально предназначенной для создания компьютерной музыки - музыкальном редакторе. В первой книге серии «Как написать игру для ZX Spectrum» мы рассказали о работе с редактором Wham. Этот же редактор был достаточно подробно описан и в книге [2]. Поэтому здесь мы не станем еще раз повторяться, а объясним, как работать с другой версией этой программы, специально рассчитанной на возможности музыкального сопроцессора. Редактор Wham FX был создан тем же автором и внешне не слишком отличается от своего предшественника. Не особенно сильно изменен и принцип управления, а также способ ввода мелодии. Но, конечно, имеются и некоторые существенные отличия, на которых в основном мы и хотим заострить ваше внимание. После загрузки программы вы услышите мелодию, демонстрирующую возможности редактора. Нажав любую клавишу, можно прервать прослушивание и попасть в главное меню, многие пункты которого повторяют функции первой версии Wham. Среди них уже знакомые LOAD TUNE и SAVE TUNE (загрузка и сохранение пьесы), SET TEMPO (изменение темпа), HELP PAGE (подсказка) и EDIT MODE (режим ввода и редактирования). Остальные две опции - SYST MENU (системное меню) и ENVELOPES (формирование огибающих звука) - мы рассмотрим ниже, а сейчас сразу перейдем к редактированию мелодии, нажав клавишу 6. Большая часть экрана в режиме редактирования (рис. 10.2) занята нотными линейками, на которых отображается вводимая вами мелодия. Нижнюю часть экрана занимает изображение клавиатуры фортепиано, которое помогает установить соответствие между клавишами компьютера и вводимыми звуками. В средней части экрана расположено несколько окон: три небольших окна слева символизируют характер звучания в каждом из трех каналов; в четвертом окне указываются номера редактируемого канала (CHN) и текущей октавы (OKT); в следующем, самом большом окне выводится информация об используемых в произведении эффектах; последнее окно, изображающее прибор со стрелкой, носит скорее декоративный характер - при проигрывании мелодии стрелка постоянно прыгает в такт звукам, отражая уровень громкости.
Рис. 10.2. Режим редактирования Прежде чем начинать вводить новую мелодию, нужно убрать из памяти старую, оставшуюся после загрузки программы или от предыдущих упражнений. Нажмите клавишу 7 и на запрос ERASE CURRENT TUNE (Y/N)? - удалить текущую мелодию (да/нет)? - ответьте утвердительно нажатием клавиши Y. Теперь можно записывать ноты. Ввод мелодии в Wham FX в принципе ничем не отличается от записи музыки в первой версии программы. Для получения звуков здесь также используются клавиши двух нижних рядов и Enter - для ввода пауз, октавы переключаются клавишами 1...4, а переход к редактированию другого голоса происходит при нажатии клавиши T. Правда, данная версия рассчитана на компьютер Spectrum 128, а следовательно, на расширенную клавиатуру, поэтому нота ДО извлекается нажатием клавиши Caps Lock (на обычной клавиатуре - Caps Shift/2), а также задействованы кнопки с символами запятой и точки. Клавиши Caps Shift и Symbol Shift служат здесь для других целей, поэтому при вводе звуков не используются. При записи музыки вы можете по мере надобности сдабривать ее различными шумовыми эффектами, имитирующими ударные инструменты. Таких инструментов в одной пьесе можно иметь до девяти, а вставляются подобные звуки при одновременном нажатии клавиши Symbol Shift и одной из клавиш второго ряда сверху от Q до O. Если вы ошиблись при вводе очередного звука, вернуться на одну позицию назад можно с помощью клавиши Delete (Caps Shift/0), а для быстрой прокрутки назад на несколько тактов воспользуйтесь клавишей True Video (Caps Shift/3). Для продвижения вперед нажимайте клавиши O (быстро) или P (медленно). Чтобы прослушать полученную музыку, нужно вернуться в самое начало пьесы, нажав R, а затем включить проигрывание клавишей Q. Наиболее интересной особенностью редактора Wham FX является возможность изменения характера звучания каждого голоса в отдельности. Для этого нужно подвести курсор к тому месту в пьесе, начиная с которого вы хотите получить иной звук (первая нота фрагмента должна появиться у правого края экрана) и нажать клавишу Extend Mode (Caps Shift/Symbol Shift). Внизу экрана появится дополнительное меню, состоящее из пяти пунктов:
Выбор интересующей функции осуществляется нажатием клавиши, соответствующей первой букве слова. Поясним назначение каждого из этих пунктов. После выбора ENVELOPE компьютер даст два дополнительных запроса: какой формы должна быть огибающая (нужно ввести число от 1 до 7) и на какой голос данный эффект будет распространяться (нажмите клавишу от 1 до 3 или 0, если хотите иметь одинаковое звучание во всех трех голосах). В отличие от предыдущего пункта, VOLUME задает постоянный уровень громкости. При выборе этой опции нужно сначала ввести шестнадцатеричное число от 1 до F, соответствующее желаемой громкости, а затем опять же указать голос, к которому данное изменение относится. Опция SLIDE имитирует такой распространенный в эстрадной музыке прием исполнения, как BEND. При этом звук плавно изменяется по высоте в пределах нескольких полутонов, повышаясь или же наоборот, понижаясь. Компьютер попросит сначала ввести интервал (от 0 до 7 полутонов), на который звук «поедет», затем направление (UP или DOWN - вверх или вниз) и, как и для предыдущих пунктов, номер канала. BLANK используется в том случае, если вы по ошибке поставили эффект не в том месте, где хотели. Никаких дополнительных запросов в этой опции не предусмотрено. Последний пункт LOOP служит для установки метки цикла в канале эффектов FX и обязательно должен использоваться перед началом компиляции пьесы. Однако до этих пор прибегать к нему не следует, так как если вы решите продолжить ввод мелодии, снять поставленную метку не удастся. Немного потренировавшись во вводе нот и изменении их звучания, можно приступать к программированию настоящей музыки. Чтобы помочь вам в этом нелегком предприятии, предлагаем сначала ввести небольшой фрагмент, приведенный на рис. 10.3 и в табл. 10.2. Просим музыкальных критиков не придираться к правописанию нот, так как рисунок отражает то, что вы увидите на экране монитора, а не то, как должны быть записаны ноты для исполнения пьесы грамотными музыкантами. В таблице выписана последовательность нажатия клавиш при вводе звуков каждого голоса. Сокращение Okt. обозначает октаву, Ent - клавишу Enter, SS - Symbol Shift (запись SS/E, например, обозначает одновременное нажатие Symbol Shift и E), а буквы и цифры справа от обозначения клавиш указывают на установку того или иного эффекта (V - VOLUME, E - ENVELOPE).
Рис. 10.3. Ноты пьесы
После того как мелодия введена в память, желательно сохранить ее на ленте или диске. Для этого выйдите в главное меню, нажав клавишу 6, и прежде чем воспользоваться пунктом 2 (SAVE TUNE) выберите устройство, на котором пьеса будет сохранена. Это делается так. Войдите в системное меню, нажав клавишу 3. Перед вами предстанет новый список, в котором нас сейчас интересует третий пункт. В нем белым цветом будет выделена надпись BETA DISK или CASS TAPE. Если надпись не соответствует желаемой, нажмите 3, а затем выберите нужное устройство, иначе нажмите клавишу 0 для возврата в главное меню. Теперь остается сохранить пьесу, предварительно указав имя файла (при работе с диском возможен также вывод на экран каталога). Когда работа над пьесой завершена, ее нужно скомпилировать, чтобы получить файл, исполняемый независимо от редактора. Вернитесь в режим редактирования, прокрутите мелодию до конца и расставьте метки цикла во всех голосах: нажмите клавишу W и на запрос SET LOOP HERE? (Y/N) ответьте клавишей Y, затем повторите то же самое для других двух голосов. Не забудьте поставить метку также и в канале эффектов FX, нажав Extend Mode и выбрав в дополнительном меню пункт LOOP. Расставив метки, переходите в главное меню, а затем в системное, откуда вызывается опция COMPILE & SAVE (компиляция и сохранение). Это пятый пункт системного меню. Если все метки расставлены и компиляция прошла успешно, на экран выводится ряд сообщений, из которых можно понять, что для проигрывания мелодии нужно ввести из Бейсика команду RANDOMIZE USR 64000или аналогичную ей, а из ассемблера полученная подпрограмма вызывается соответственно командой CALL 64000Тут же сообщается, что для регулирования темпа исполнения нужно записать некоторое число по адресу 64062 (при исполнении нашей пьесы это число будет равно примерно 230). Изучив выданную информацию, наберите имя файла для сохранения скомпилированной мелодии и нажмите Enter. На этом можно было бы поставить точку в данном кратком описании, но все же хочется сказать пару слов и о других возможностях, предоставляемых редактором Wham FX. Если вас не слишком устраивают предлагаемые программой формы огибающих звуков, то вы можете с помощью пункта 4 главного меню исправить положение и создать свои собственные уникальные звуки. Нажав клавишу 4, вы попадаете во встроенный редактор для формирования огибающих. В верху экрана выстроятся 8 диаграмм, показывающих существующие формы звуков: первые 7 можно заказывать в дополнительном меню режима редактирования, а восьмой, помеченный двумя звездочками, относится к шумовым эффектам. Нажмите цифровую клавишу, соответствующую звуку, который вы хотите изменить. На экране появится выбранная диаграмма в увеличенном масштабе (рис. 10.4), а под ней - курсор в виде стрелки. Управляя клавишами Left (Caps Shift/5) и Right (Caps Shift/8) переместите стрелку в нужную точку огибающей и отрегулируйте громкость с помощью клавиш Down (Caps Shift/6) и Up (Caps Shift/7). Получив таким образом нужную форму огибающей закончите редактирование, нажав Enter.
Рис. 10.4. Формирование огибающей Другая возможность касается «ударных инструментов». Их звучание также можно варьировать в некоторых пределах. Выберите в системном меню опцию SET PRESET NOISE VALUES, нажав клавишу 1. На экране вы увидите таблицу, показанную на рис. 10.5. В первой графе указан порядковый номер эффекта, а во второй - клавиша, за которой этот эффект закреплен в режиме редактирования мелодии. Нажав соответствующую цифровую клавишу, вы сможете изменить другие параметры, обозначенные в таблице. Сначала появится запрос об установке нового значения для графы FREQUENCY (частота), на который нужно ввести число от 0 до 31. Затем вводится номер огибающей (клавиши 1...8), помещаемый в графу ENVELOPE. Если вы хотите задать звук постоянной громкости, введите на этот запрос 0. В этом случае компьютер попросит указать уровень звука (графа VOLUME) вводом шестнадцатеричного числа от 0 до F.
Рис. 10.5. Редактирование шумовых эффектов Аналогично можно отредактировать любой из девяти эффектов, а для возврата в главное меню нужно нажать клавишу 0. В системном меню есть еще одна интересная функция - SET CHANNEL LOOP PARAMETERS, служащая для установки начальных меток циклов в каждом канале. К услугам этого пункта полезно прибегать в тех пьесах, где мелодия начинается не с сильной доли (то есть не на счет «раз»), а с затакта. Нажмите клавишу 2 и укажите, в каком канале и с какого смещения мелодия в выбранном голосе будет начинаться при повторении. Начальные метки задаются для каждого канала в отдельности (в том числе и для канала эффектов FX), а смещения могут иметь как положительные, так и отрицательные значения. Добавим, что ошибиться в расстановке этих меток не страшно, ибо в любой момент их можно переместить как вперед, так и назад (если ввести отрицательное число). СОДЕРЖАНИЕ:
|