Радио-86РК/Радио 02,03-87/Компьютерные игры

Материал из Emuverse
Данный материал защищён авторскими правами!

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

Автор: А. ДОЛГИЙ

Источник: http://retro.h1.ru/RK86/Games/Games.php

Компьютерные игры — одно из наиболее массовых применений ЭВМ. Разработка игровых программ постепенно превращается в самостоятельную область творчества и зачастую не менее увлекательна, чем сама игра. Техника программирования, отработанная на игровых программах, с успехом используется для разработки серьезных программ.

Ниже описаны три игровые программы на языке Бейсик. Они разрабатывались и отлаживались на ЭВМ «Радио-86РК» и «Микро-80», описания которых были помещены в журнале. Знакомство с этими программами позволит не только приятно провести время за пультом микро-ЭВМ, но и поможет лучше изучить ее возможности и некоторые приемы программирования. Все три программы рассчитаны на вывод информации на дисплей и создают на его экране динамически изменяющуюся картину.

Тексты программ приведены в варианте для «Радио-86РК» с ОЗУ объемом 16 Кбайт, но в описании каждой из них рассматриваются изменения, которые нужно внести при использовании на других микро-ЭВМ, связанные в основном с различиями в распределении памяти, формате экрана и правилах обращения к устройствам ввода-вывода.

ПЕРЕХВАТЧИК

Эта программа относится к играм, моделирующим реальную ситуацию. К этому же классу принадлежат игры, имитирующие движение автомобиля по извилистой дороге, посадку самолета или стыковку космических кораблей. Все они строятся по тем же принципам, что и тренажеры, на которых обучаются водители, летчики, космонавты — разница лишь в точности учета факторов, влияющих на движение управляемого объекта, и точности воспроизведения окружающей обстановки. На тренажере обучаемый находится, как правило, в реальной кабине автомобиля или самолета. Данные в моделирующую программу вводятся с датчиков, подключенных к реальным органам управления, а результаты моделирования выводятся на реальные приборы, находящиеся в кабине, и управляют перемещением изображения на большом экране.

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

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

Для управления перехватчиком необходимо собрать пульт, схема которого приведена на рис.1. Левый (по схеме) вывод резистора R1 в компьютере «Радио-86РК» подключают к выводу (14) младшего разряда порта С микросхемы D14 (КР580ИК55).

Переменный резистор R2 соединяют с компьютером экранированным проводом или витой парой проводов длиной до нескольких метров. Для устранения наводок корпус переменного резистора соединяют с общим проводом. Распечатка (на языке ассемблера) подпрограммы преобразования сопротивления резистора R2 в пропорциональное ему число приведена в табл.1. Машинные коды подпрограммы записаны в операторах DATA основной программы.

Работу подпрограммы рассмотрим, начиная с команды, имеющей метку L2. Эта и последующие команды настраивают младшие разряды порта С интерфейсного адаптера КР580ИК55 на вывод в режиме 0 и устанавливают высокий логический уровень на контакте, к которому подключен пульт управления перехватчиком. Затем вычисленный ранее результат работы подпрограммы переписывается из регистра В микропроцессора в аккумулятор, и происходит возврат в основную программу. До следующего обращения к подпрограмме конденсатор С1 успевает зарядиться через ограничительный резистор R1 до напряжения на резисторе R2. После вызова подпрограммы младшие разряды порта С переводятся в режим ввода. Входное сопротивление микросхемы в этом режиме очень велико, ток утечки мал, поэтому конденсатор С1 разряжается через переменный резистор, а программа периодически проверяет состояние входа, причем число проверок подсчитывается в регистре В. Микропроцессор выходит из цикла проверки, когда напряжение на конденсаторе падает до уровня переключения входа (примерно до 2 В).

Число, накопленное к этому моменту в регистре В, пропорционально постоянной времени разрядки, а следовательно, сопротивлению переменного резистора.

При первом обращении к этой подпрограмме результат неопределен, так как напряжение на конденсаторе С1 неизвестно. В описываемой игре это несущественно. Если же вы хотите применить подпрограмму там, где такая неопределенность недопустима, добавьте в начале программы «холостое» обращение к подпрограмме, результат которого не будет использоваться.

Игровая программа, текст которой приведен в табл.2, начинает работу с записи в ОЗУ машинных кодов подпрограммы ввода положения движка переменного резистора. Запись осуществляется операторами, находящимися в строке 60, а десятичные значения кодов находятся в операторах DATA (строки 40 и 50). Подпрограмма занимает в ОЗУ адреса с 2800Н по 2819Н. Далее присваиваются значения константам. Числа А и В использованы для вычисления направления движения перехватчика. V и U— это отношения скорости перехватчика соответственно по горизонтали и вертикали к скорости цели. Коэффициент 0,7 в строке 90 учитывает формат экрана. ХМ и YM — это максимальные значения аргументов операторов PLOT и LINE, К — число попыток, a N — число сбитых целей. Оператор FOR в строке 130 задает выполнение К циклов игры, после чего на экран выводится результат.

Игровой цикл начинается с присваивания случайных значений координатам перехватчика и координате YT цели. Затем координата XT изменяется от 0 до максимального значения. Цель, отображаемая оператором PLOT (в строке 180), движется по экрану слева направо. В строке 190 считывается положение ручки управления, вычисляется угол F между осью Х и направлением движения перехватчика. В приведенном варианте он пропорционален сопротивлению резистора. Если вы хотите, чтобы ручка управления изменяла радиус разворота перехватчика, то есть действовала как штурвал самолета, то строку 190 нужно изменить:

190 F=F+A*(USR(10240)—В).

Кроме этого, необходимо изменить значение А и ввести оператор, присваивающий случайное значение переменной Р в начале игрового цикла:

70 А=0.01
135 P=6*28*RND(1).

В таком варианте поразить цель будет значительно труднее.

В следующих строках программы выполняются действия, не допускающие выход перехватчика за экран. В строке 260 перехватчик отображается на экране оператором PLOT. Затем проверяется расстояние между целью и перехватчиком и, если оно меньше заданного, выполняется переход к строке 300. В этой строке увеличивается на единицу содержимое счетчика сбитых целей, а в следующей — вызываются подпрограмма, имитирующая взрыв. Если цель дошла до правого края экрана, то строки 300, 310 обходятся. Затем начинается новый цикл игры.

При переводе игры на другие машины прежде всего нужно решить, куда будет подключен пульт (рис.1). Можно использовать любой свободный вывод портов В и С микросхемы КР580ИК55. Порт А использовать не рекомендуется из-за повышенного тока утечки.

Так как при перепрограммировании микросхемы КР580ИК55 на всех ее выводах устанавливается низкий уровень, нужно убедиться, что это не нарушает нормальной работы других подключенных к ней устройств. Подпрограмму обслуживания пульта нужно изменить в соответствии с правилами обращения к микросхеме КР580ИК55 в данной машине. Константа, записываемая в регистр С микропроцессора в начале работы подпрограммы, должна содержать 1 в разряде, к которому подключен пульт, и 0 во всех остальных разрядах.

В ЭВМ «Микро-80» устройство управления может быть подключено к старшему разряду порта С микросхемы КР580ИК55 модуля клавиатуры. Строки 40 и 50 игровой программы в этом случае должны выглядеть так:

40 DATA 197, 63, 155, 211, 4, 6, 255, 4, 219, 5, 230, 128, 194
50 DATA 7, 40, 62, 131, 211, 4, 62, 15, 311, 4,120, 193, 201

Максимальное значение переменной 1 в строке 60 должно быть равно 10 265. В строке 100 для полного использования площади экрана можно указать YM=63.

ПИТОН

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

Текст программы приведен в табл.3. Для ввода команд, изменяющих направление движения питона, использована подпрограмма опроса клавиатуры, имеющаяся в МОНИТОРЕ «Радио-86РК». Для ускорения движения питона по экрану пришлось отказаться от оператора PRINT. Коды символов, изображающих питона и кролика, заносятся непосредственно в экранную область ОЗУ оператором POKE. Для проверки содержимого ячеек использована функция PEEK. Координаты всех позиций экрана, занятых в данный момент питоном, хранятся в специально организованном массиве двоичных чисел. При перемещении питона числа в этом массиве сдвигаются специальной подпрограммой в машинных кодах. Это позволило достичь достаточно большой скорости движения питона по экрану. При желании скорость можно уменьшить, вставив в программу строку:

445 FOR Z=1 ТО XX: NEXT Z:

Этот оператор создает временную задержку, зависящую от числа XX. С его увеличением скорость перемещения питона уменьшается.

Максимальная длина питона — 255 символов — ограничена тем, что для ее передачи в подпрограмму сдвига выделена только одна ячейка памяти. Это ограничение легко устранить, переделав подпрограмму, но делать это вряд ли целесообразно, так как достичь максимального результата очень трудно.

Для записи машинных кодов в ОЗУ предназначена подпрограмма — перемещающий загрузчик, начинающаяся со строки 800. Она не только переписывает коды (десятичные) из операторов DATA в ОЗУ, начиная с указанного при обращении адреса 1, но и изменяет адреса переходов и ячеек памяти в загружаемой подпрограмме в соответствии с этим адресом. Загружаемая подпрограмма должна транслироваться с ячейки 0000Н и заканчиваться командой RET (десятичное значение кода 201). Других команд RET быть не должно. Если при загрузке содержимое некоторых ячеек должно быть изменено, то порядковые номера этих ячеек (от начала подпрограммы) следует указать после кода 201. Признак конца подпрограммы — любое число, большее 255.

После запуска программы на экран дисплея выводится вопрос: «Вы знаете правила игры?». Если в ответ будет введена буква Н или любое слово (например нет), начинающееся с этой буквы, то подпрограмма, начинающаяся со строки 1000, выведет на экран правила. При вводе любой другой буквы или слова этого не произойдет. В строках 40—70 происходит загрузка в ОЗУ машинных кодов подпрограммы сдвига массива с адреса 3000Н (десятичное значение 12 288). Переменная U1 — адрес обращения к подпрограмме, А0 — адрес ячейки памяти, через которую в подпрограмму сдвига передается длина питона, А1 — адрес начала массива его координат (в этой и следующей за ней ячейках всегда находятся координаты хвоста). Координаты головы размещаются в ячейках с адресами AN и AN+1.

В строке 80 переменным U, D, L, R присваиваются значения, с которыми будут сравниваться коды, возвращаемые подпрограммой ввода команды.

Следующая строка задает положение в ОЗУ буфера экрана и размеры области экрана, в пределах которой перемещается питон. Здесь S0 — адрес ячейки ОЗУ, соответствующей левому верхнему углу области перемещения питона, СМ — число позиций в строке, которые может занимать питон, CN — полное число позиций в строке, RM — число строк в отводимой для игры области экрана. При значениях, указанных в тексте программы, питон перемещается по всему экрану.

Далее присваиваются начальные значения переменным, используемым в программе. Игра начинается после нажатия на любую клавишу. Так как в строке 140 длина питона задана нулевой, то в начале игры он будет состоять всего из одного символа. Далее в строках 170—200 вычисляются случайные координаты кролика, проверяется, не занята ли эта позиция питоном, и символ кролика выводится на экран. В строках 210—250 питон удлиняется на один символ.

Цикл движения питона занимает строки с 260 по 450. Он начинается с вызова подпрограммы ввода кода нажатой клавиши. Возвращаемое значение присваивается переменной А, в зависимости от которой в строках 280—310 присваиваются значения переменным DX и DY, представляющим собой приращения соответствующих координат за один шаг питона. Они и определяют направление его движения. Если ни одна клавиша не нажата, А равно 255, строки 280—310 не выполняются и направление движения питона не изменяется.

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

340 IF X <0 OR X>CM THEN 470
380 IF Y <0 OR Y>RM THEN 470.

В строке 400 вычисляется новый адрес головы питона в буфере экрана, проверяется, не занята ли эта позиция, и если нет, то питон (на экране) и массив его координат (в ОЗУ) сдвигаются, и весь цикл повторяется. Если позиция занята, то в строке 460 выясняется, какой символ находится в этой позиции и (в зависимости от результата проверки) происходит либо переход к строке 170 (появляется новый кролик, и игра продолжается), либо на экран выводится результат игры.

«ОХОТА НА ЛИС»

Эта игра ведется по правилам, напоминающим правила известных соревнований но спортивной радиопеленгации. Игровая ситуация на экране дисплея изображается площадкой размерами 20х50 клеток, на которой замаскированы радиопередатчики — лисы. Количество лис задается перед началом игры. Раз в минуту они подают сигналы, по которым охотник может их запеленговать. Пеленги еще не найденных лис выводятся на экран. Они могут иметь только четыре значения: север, юг, запад и восток.

Охотник и найденные лисы изображаются в соответствующих позициях игровой площадки. Направление движения охотника задается нажатием на клавиш и С. Ю, 3, В. Любая другая клавиша останавливает охотника, но отсчет времени, прошедшего с начала поиска, продолжается. Это время условное: принято, что на переход из любой клетки в соседнюю охотник тратит 10 с. Нужно найти определенное число лис (его тоже задают перед началом игры) за минимальное время. Лиса считается обнаруженной, если охотник остановился в той клетке, в которой она находится. Если же он проходит эту клетку без остановки, то найти замаскированную лису можно только случайно — с вероятностью, заданной в программе. Выходить за пределы площадки запрещено. За это нарушение охотник получает штрафное очко и продолжает поиск с линии старта. За три штрафных очка он дисквалифицируется (игра прекращается).

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

Обратите внимание на условный оператор в строках 100, 250 и 1550. Операторы, следующие послe THEN, выполняются только в том случае, если выражение между IF и THEN не равно нулю. В данном случае оно состоит всего из одной переменной E, что эквивалентно записи: IF Е<>0 THEN… . Следуют отметить, что операции сравнения и языке Бейсик дают число −1, если они истинны, и 0, если ложны. Эти операции могут входить в арифметические выражения. Например, в результате выполнения оператора присваивания А=А* (А<0) +А переменная А не изменит значения, если она положительна, и станет равной нулю, если была отрицательной.

После выделения памяти для массивов координат лис и признаков их обнаружения они случайным образом размещаются на площадке. При этом программа следит, чтобы ни одна из них не попала на стартовую позицию охотника (левый нижний угол экрана) и чтобы две лисы не попали в одну и ту же позицию. О готовности каждой лисы на экран выводится сообщение. Если на площадке спрятано несколько лис, то программа запрашивает, скольких из них будет искать охотник. Правильность ввода контролируется той же подпрограммой, начинающейся со строки 1500. Затем на экран выводится изображение игровой площадки, охотника на стартовой позиции. 11 программа ждет нажатия любой клавиши.

Игровой цикл начинается со строки 370. Строки 370—390 ответственны за вывод на экран времени, прошедшего с начала поиска. Ноли оно превысит заданное, то условный оператор в строке 400 отреагирует на это и прекратит поиск. В предлагаемом варианте игры на поиск отведено 10 (опять же условных) часов. При желании можно в строку 340 вставить операторы, изменяющие предельное время поиска в зависимости от числа лис.

Каждую минуту вызывается подпрограмма, начинающаяся со строки 2000. С ее помощью на экран выводятся направления на еще не обнаруженных лис. Найденные лисы изображаются своими номерами в соответствующих позициях игрового поля. Обратите внимание, что для вывода лис используется функция CHR$ (48+1). Если в операторе PRINT указать просто переменную 1, то фактически будут выведены три символа: пробел (или знак минус) перед цифрой, сама цифра и еще один пробел после нее. В данном случае это недопустимо, так как при этом будут стерты позиции игрового поля, находящиеся рядом с отображаемой лисой.

Позиция экрана, в которую должен быть выведен очередной символ или сообщение, указывается в программе оператором CUR. Использование этого оператора совместно с оператором PRINT для создания на экране динамически изменяющейся картины требует от программиста определенной осторожности. Дело в том, что после выполнения оператора PRINT без ограничителя (запятая или точка с запятой) интерпретатор автоматически выполняет «возврат каретки» и «перевод строки». Если ограничитель используется, то это происходит после вывода каждых 72 символов, включая пробелы, автоматически вводимые интерпретатором. В результате возможны неожиданные сдвиги изображения на экране и вывод символов совсем не туда, куда запланировано. Можно рекомендовать всегда использовать с оператором CUR оператор PRINT без ограничителя и избегать вывода в самую нижнюю строку экрана.

Продолжим рассмотрение игровой программы. В строках 420—490 проверяется, какая клавиша нажата, и присваиваются соответствующие значения приращениям координат охотника. Преобразование кода клавиши в символьный вид в строке 440 введено только для наглядности программы. В следующих за ней условных операторах могли бы сравниваться и числовые значения.

Строка 500 стирает изображение охотника. Далее вычисляются его новые координаты и проверяется, не выходят ли они за пределы площадки. Если это произошло, начисляется штрафное очко, на экран выводится соответствующее сообщение и устанавливаются нулевые координаты охотника, что равнозначно возврату на старт. После вывода изображения охотника в новой позиции операторы в строках 600—670 проверяют, не найдена ли лиса. Вероятность обнаружения лисы «на ходу» задается выражением RND(1)<0.5 в строке 640. Одновременно подсчитывается число найденных лис. Если оно равно заданному, то поиск заканчивается и на старт приглашается следующий участник. В строках 690 и 700 показания программных часов увеличиваются на 10 с. Строки 710 и 720 создают временную задержку, определяющую скорость перемещения охотника по экрану. В каждом цикле задержки вызывается подпрограмма МОНИТОРА, возвращающая код нажатой клавиши. После выхода из цикла переменная А имеет значение, либо соответствующее коду последней из нажатых клавиш, либо 255, если ни одна клавиша не нажималась. Такое решение практически исключает случаи, когда охотник не слушается команды из-за того, что момент нажатия клавиши не совпадает с моментом вызова подпрограммы опроса клавиатуры. Далее весь цикл игры повторятся со строки 370.

Перевод этой программы на другие машины не вызовет затруднений, если в составе математического обеспечения есть подпрограмма ввода кода нажатой клавиши, аналогичная использованной подпрограмме МОНИТОРА «Радио-86РК». В этом случае достаточно лишь указать ее адрес. В ЭВМ «Микро-80» такой подпрограммы нет. Подпрограмма ввода символа с клавиатуры всегда ждет нажатия и отпускания клавиши, что вызывает остановку игры. Более того, интерпретатор языка Бейсик приостанавливает выполнение программы при нажатии любой клавиши.

Для «Микро-80» разработана подпрограмма в машинных кодах, распечатка которой на языке ассемблера с комментариями, поясняющими работу, приведена в табл.5. Подпрограмма проверяет, не нажата ли клавиша, вводит ее код и блокирует клавиатуру, не давая возможности интерпретатору проверять ее состояние. Блокировка достигается перепрограммированием порта В микросхемы КР580ИК55 модуля клавиатуры на вывод. Одна из особенностей этой микросхемы состоит в том, что считывание из порта, запрограммированного на вывод, всегда дает результат 0FFH. Для подпрограммы МОНИТОРА, которой пользуется интерпретатор при определении состояния клавиатуры, это означает, что ни одна клавиша не нажата.

В игровую программу нужно внести следующие изменения:

50 DATA 62, 139, 211, 4, 205, 18, 248, 183, 202, 14, 48 60 DАTА 205, 3, 248, 245, 62, 155, 211, 4, 241, 201 70 FOR I=12288 TO 12318: READ X: POKE l, X: NEXT I 710 A1=USR(12288): IF A1 ТHEN A=A1 750 OUT 4,139: GOTO 120.

Оператор OUT восстанавливает режим микросхемы КР580ИК55, снимая блокировку клавиатуры.

А. ДОЛГИЙ

г. Москва