Как написать игру для ZX Spectrum 1994 г.

Блок взаимодействия с играющим - особенности управления клавиатурой. Взаимодействие играющего с программой.


Особенности управления клавиатурой

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

Для реализации его, так же как и для джойстика, нужно знать адреса портов. Как мы уже говорили, клавиатура связана с портом 254, но на практике этого недостаточно, так как в этом случае мы будем считывать значения со всех полурядов одновременно и при нажатии Caps Shift, A, Q, 1, 0, Р, Enter и Space будем получать один и тот же код. Для выбора опрашиваемого полуряда нужно указать не только младший, но и старший байт адреса порта. Полный адрес может быть вычислен из выражения 254 + 256*(255-2 N), где N принимает значения от 0 до 7. Вот эти адреса и соответствие их полурядам клавиатуры:

При ненажатых клавишах из всех портов считывается код 255 (то есть все биты установлены). Если нажать какую-нибудь клавишу, то один из битов «сбросится» в 0, причем младшим битам соответствуют крайние клавиши каждого полуряда, а старшим - те, что ближе к центру клавиатуры. Значит, чтобы определить, например, нажата ли клавиша О, нужно выполнить оператор LET KEY=IN 57342

При нажатой клавише О полученный результат будет 11111101 в двоичном

Такая запись равноценна следующей: IF J(1)<>0 THEN виде, или 253 - в десятичном. Если окажутся «сброшены» и другие биты, это будет означать, что нажаты и другие клавиши. Рассмотрим небольшую программку, напоминающую графический редактор, в которой используется подобный способ управления.

Программа 27. ОПРОС КЛАВИАТУРЫ.

10 INK 6: PAPER 0: BRIGHT 1: BORDER 1: CLS 20 LET P=0

40 LET =120: let Y=80: LET X1=X: LET Y1=Y 50 GO SUB 1000

80 IF P THEN PLOT X-3,Y-2: DRAW 4,4: PLOT X-2,Y-2: DRAW 4,4

100 IF IN 57342=253 AND X>6 THEN LET X=X-2

110 IF IN 57342=254 AND X<248 THEN LET X=X+2

120 IF IN 64510=254 AND Y<168 THEN LET Y=Y+2

130 IF IN 65022=254 AND Y>6 THEN LET Y=Y-2

140 LET P=0

150 IF IN 32766=251 THEN LET P=1 160 GO SUB 1000

170 LET X1=X: LET Y1=Y: GO SUB 1000

180 IF INKEY$="N" OR INKEY$="n" THEN CLS : GO TO 50

190 GO TO 80

1000 OVER 1

1010 PLOT X1-2,Y1: DRAW -4,0: PLOT X1+2,Y1: DRAW 4,0 1020 PLOT X1,Y1-2: DRAW 0,-4: PLOT X1,Y1+2: DRAW 0,4 1030 OVER 0 1040 RETURN

После ввода и запуска программы экран окрасится в черный цвет, а синий бордюр ограничит рабочее поле. В центре экрана появится мигающий курсор желтого цвета в виде перекрестья прицела. Нажимая клавиши Q, А, О и Р, курсор можно перемещать во всех направлениях. Если при этом нажать еще и клавишу М, то за курсором потянется след. Теперь прокомментируем вкратце строки этой программы:

10 - установка атрибутов экрана;

20 - переменная Р указывает положение «пера»; 0 - «перо» поднято, 1 - опущено;

40 - установка начальных координат курсора;

50 - обращение к подпрограмме, выводящей изображение курсора на экран;

80 - если переменная Р не равна нулю, то есть «перо» опущено, то рисуется его профиль;

100... 190 - блок у правления курсором и положением «пера». Если нажата клавиша О, то курсор (а вместе с ним и «перо») перемещается на один шаг, равный двум пикселям, влево. Но это только в том случае, если курсор не дошел до левого края экрана (если условие Х>6 выполняется). В строках 110... 130 аналогично проверяется нажатие клавиш Р, Q и А. Обратите внимание, что в конце этих строк отсутствует оператор GO TO, что позволяет при нажатии двух клавиш получить диагональное перемещение курсора, так как изменится не одна координата, а сразу обе;

140, 150 - управление положением «пера». Если нажата клавиша М, переменная Р становится равной 1 и «перо» опускается на «бумагу»;

160 - курсор после обращения к подпрограмме 1000 стирается;

170 - изменение координат и вывод курсора в новое место экрана;

180 - если нажата клавиша N, то рисунок на экране стирается - можно начинать рисовать новый;

190 - переход для продолжения рисования;

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

Во многих программах вместо Kempston-джойстика используются Sinclair-джойстики. Для того чтобы приспособить рассмотренные программы к этому типу джойстиков, достаточно заменить в них опрос клавиш Q, А, О, Р и М на цифровые клавиши 6, 7, 8, 9, 0 (правый Sinclair-джойстик) или 1, 2, 3, 4, 5 (левый Sinclair-джойстик).

Взаимодействие играющего с программой

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

Рассмотрим на примере игры СОКОБАН, как решаются некоторые из перечисленных задач.

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

перемещение больше напоминает головоломку, чем работу грузчика. Причем при движении по складу нельзя одновременно толкать два ящика, стоящих вплотную друг к другу, и тянуть ящик на себя. Так что не задвигайте груз в угол, иначе он останется там навсегда (рис. 53).

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

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

10 CLEAR 59999 20 LOAD ""CODE 60000

30 POKE 60035,230 40 POKE 60026,0 50 LOAD ""

10 - выполняется оператор CLS и изменяется адрес RAMTOP; 20 - загружается с ленты музыкальный блок, который помещается в память с адреса 60000; 30 - устанавливается темп исполнения мелодии; 40 - устанавливаются цвета бордюра на время исполнения мелодии; 50 - загружается собственно игровая программа.

Таким образом, после программы-загрузчика на ленте должен располагаться созданный ранее (см. главу 4) кодовый музыкальный блок, а за ним программа СОКОБАН, текст которой приводится ниже. В строке 230 помещен оператор, который запускает музыкальную кодовую программу.

Программа 28. СОКОБАН.

10 REM -- U. D. G. ---------

20 FOR N=0 TO 39

30 READ S: POKE USR "A"+N,S

40 NEXT N

50 DATA 62,42,127,127,93,85,20,20 60 DATA 0,191,191,191,0,251,251,251 70 DATA 0,127,127,127,99,127,127,127 80 DATA 0,24,36,66,66,36,24,0 90 DATA 0,127,127,127,99,127,127,127

100 REM -- ZASTAWKA ---------

110 BORDER 1: PAPER 1: INK 6: CLS

120 PLOT 0,0: DRAW 0,175: DRAW 255,0: DRAW 0,-175: DRAW -255,0

130 PLOT 2,2: DRAW 0,171: DRAW 251,0: DRAW 0,-171:DRAW -251,0

140 PRINT AT 1,10; INK 4;"** "; INK 2;"SOKOBAN";INK 4;" **"

150 PRINT AT 4,5; INK 7;"CONTROLS KEYS:"

160 PRINT AT 6,2;"O - LEFT"

170 PRINT AT 8,2;"P - RIGHT"

180 PRINT AT 10,2;"Q - UP"

190 PRINT AT 12,2;"A - DOWN"

200 PRINT AT 14,2;"L - REPEAT LEVEL"

210 PRINT AT 16,2;"E - GAME OVER"

220 PRINT AT 19,4; INK 3;"PRESS ANY KEY TO CONTINUE"

230 RANDOMIZE USR 60000

250 DIM U$(17,19): DIM P$(17,19)

260 LET LE=0

300 REM ----------------------

310 LET LE=LE+1: IF LE>1 THEN GO TO 110 320 CLS 330 INK 4

340 PRINT AT 0,0;"CS/4;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;7" 350 PRINT AT

21,0;"CS/1;CS/3;CS/3:CS/3;CS/3;CS/3;CS/3;CS/3;CS/3;CS/3;CS/3;CS/3;CS/3;CS/3;CS/3;CS/3

;CS/3;CS/3;CS/3;CS/3;CS/3;CS/3;CS/3;CS/3;CS/3;CS/3;CS/3;CS/3;CS/3;CS/3;CS/3;CS/2"

360 FOR N=1 TO 20

370 PRINT AT N,0;"CS/5"

380 PRINT AT N,31;"5"

390 NEXT N

400 PRINT AT 0,11; INK 3;" LEVEL:";LE;" " 410 RESTORE 1000+(LE-1)*100 420 FOR I=1 TO 17 430 READ U$(I)

440 IF U$(I)=nnnnnnnnnnnnnnnnnnnn" THEN GO TO 520 450 FOR J=1 TO 19

460 LET YY=I+2: LET XX=J+6: LET A$=U$(I,J) 470 IF A$="B" THEN INK 2

480 IF A$="C" THEN INK 6

490 IF A$="D" THEN INK 7: LET P$(I,J)="D"

500 PRINT AT YY,XX;A$

510 NEXT J

520 NEXT I

530 READ X,Y

540 POKE 23658,8

550 REM ----------------------

560 BEEP .01,-10: PRINT AT Y+2,X+6; INK 7;"A" 570 REM -- INKEY$ -----------

580 IF INKEY$="P" THEN LET X1=X+1: LET Y1=Y: GO TO 660 590 IF INKEY$="O" THEN LET X1=X-1: LET Y1=Y: GO TO 660 600 IF INKEY$="A" THEN LET Y1=Y+1: LET X1=X: GO TO 660 610 IF INKEY$="Q" THEN LET Y1=Y-1: LET X1=X: GO TO 660 620 IF INKEY$="E" THEN GO SUB 900: GO TO 110 630 IF INKEY$="L" THEN GO SUB 900: GO TO 410 640 GO TO 580

650 REM ---------------------

660 IF U$(Y1,X1)<>" " AND U$(Y1,X1)<>"D" THEN GO TO 700 670 PRINT AT Y+2,X+6; INK 7;P$(Y,X) 680 LET X=X1: LET Y=Y1: GO TO 550 700 IF U$(Y1,X1)="B" THEN GO TO 550

710 LET X2=X1-X: LET Y2=Y1-Y: LET X2=X+2*X2: LET Y2=Y+2*Y2

720 IF U$(Y2,X2)="B" OR U$(Y2,X2)="C" OR U$(Y2,X2)="E" THEN GO TO 550

740 PRINT AT Y+2,X+6; INK 7;P$(Y,X)

750 LET X=X1: LET Y=Y1: LET U$(Y,X)=P$(Y,X)

760 IF P$(Y2,X2)="D" THEN LET U$(Y2,X2)="E": GO TO 780

770 LET U$(Y2,X2)="C"

780 IF U$(Y2,X2)="C" THEN PRINT AT Y2+2,X2+6; INK 6;"C":GO TO 550 790 IF U$(Y2,X2)="E" THEN PRINT AT Y2+2,X2+6; INK 7;"E" 800 PRINT AT Y+2,X+6; INK 7;"A" 810 FOR N=1 TO 17

820 IF U$(N)="ППППППППППППППППППП" THEN GO TO 860

830 FOR M=1 TO 19

840 IF U$(N,M)="C" THEN GO TO 550

850 NEXT M

860 NEXT N

870 FOR N=-10 TO 50 STEP 3: BEEP 0.01,N: NEXT N 880 FOR N=50 TO -5 STEP -5: BEEP 0.01,N: NEXT N 890 GO TO 310

900 REM -- BEEP ------------

910 FOR N=30 TO 50 STEP 3 920 BEEP 0.01,N 930 NEXT N 940 RETURN

1000 REM -- LEVEL 1 ----------

1001 DATA "ППППППППППППППППППП"

1002 DATA "ППППППППППППППППППП"

1003 DATA "ППППППППППППППППППП"

1004 DATA "ПППП^^ПППППППППП"

1005 DATA "ППППДПППДПППППППППП"

1006 DATA "ПППП^ППДПППППППППП"

1007 DATA "ППBBBППCBBППППППППП"

1008 DATA "ППДППО С ВППППППППП"

1009 DATA "BBB B BB ШПЕ^Ш^"

1010 DATA ' Б.ПППД BB BBBBBППDDB"

1011 DATA "B ОППСППППППППППДОВ"

1012 DATA "BBBBB BBB B BBППDDB"

1013 DATA "ППППBПППППВВВВВВВBВ"

1014 DATA "ППППВВВВВВВПППППППП"

1015 DATA "nnnnnnnnnnnnnnnnnnn"

1016 DATA nnnnnnnnnnnnnnnnnnn"

1017 DATA "nnnnnnnnnnnnnnnnnnn"

1018 DATA 12,12

1100 REM -- LEVEL 2 ----------

1200 REM -- LEVEL 3 ----------

1300 REM -- LEVEL 4 ----------

1400 REM -- LEVEL 5 ----------

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

10...90 - эти строки кодируют графические символы, необходимые для построения игрового пространства. Букве А в режиме курсора [G] соответствует грузчик, букве В - кирпичная стенка, С - ящик, D - место, куда этот ящик необходимо поставить и Е - ящик, поставленный на свое место;

100...220 - вывод на экран заставки. Сначала рисуется двойная рамка по периметру экрана, затем печатается название игры и информация о назначении клавиш;

230 - вызов кодовой подпрограммы, исполняющей музыкальный фрагмент MEL 1. Чтобы исполнение не было бесконечным, необходимо при выборе условий компиляции в программе Wham установить определенный режим. Выберем такой, когда мелодия прекращает звучать при нажатии любой клавиши (это соответствует условию 1. KEYPRESS).

Если вы хотите исключить музыкальный фрагмент из программы, строку 230 нужно заменить на такую: 230 PAUSE 0: СО SUB 900

250 - задаются два массива: в массив U$(17,19) в строках 450...520 записывается картина игрового пространства, а массив Р$(17,19} служит для восстановления фона и содержит только те элементы картинки, которые могут стираться при прохождении по ним грузчика или ящиков, а именно обозначения мест установки ящиков.

260 - в переменной LE хранится номер уровня;

310 - увеличение номера уровня и проверка завершения последнего уровня. Если вы дополните программу своими лабиринтами, то понадобится изменить условие IF LE>1, вместо единицы подставив количество уровней в вашей версии программы;

320...390 - очистка экрана и печать рамки, в которую затем будет помещен склад-лабиринт. Рамка рисуется с помощью псевдографических символов;

400 - печать номера уровня;

410 - оператор RESTORE (восстановить) уже упоминался нами во второй главе. Здесь он необходим для указания начала данных для каждого уровня. В выражении, следующим за RESTORE вычисляется номер строки, с которой располагаются данные игрового пространства уровней Так для первого уровня данные должны начинаться со строки 1000, а для каждого следующего уровня номера строк увеличиваются на 100;

420... 520 - в этих строках осуществляется чтение оператором READ из списка DATA информации о конфигурации стен склада, расположении ящиков и тех местах, куда эти ящики необходимо передвинуть. Буквы в строках 1001... 1017 набираются в режиме курсора [G] и соответствуют графическим символам, определенным в начале программы;

430 - здесь строка за строкой считываются данные из списка DATA и записываются в двухмерный массив U$(17,19), причем первая координата указывает на положение символа по вертикали, а вторая - на его положение по горизонтали;

440 - эта строка служит для ускорения построения экранного изображения. Если считанная строка символов целиком состоит из пробелов, то происходит переход на следующий «виток» цикла;

450...510 - во внутреннем цикле анализируется очередная строка массива U$ и формируется изображение на экране;

460 - перед тем, как поставить тот или иной символ на экран, его координаты (переменные YY и XX) изменяются таким образом, чтобы все изображение лабиринта оказалось посередине. В переменную А$ заносится анализируемый символ;

470, 480, 490 - в зависимости от выводимого символа устанавливается его цвет: стены (графический символ В) будут иметь красный цвет, ящики (С) окрасятся желтым цветом, а места для установки ящиков (D) будут белыми. Кроме того, если в анализируемой строке массива встречается графический символ D, он записывается в соответствующее место другого массива - Р$;

500 - печать очередного символа в место с заранее рассчитанными координатами;

530 - последними в операторах DATA читаются координаты грузчика (в отличие от ящиков, фрагментов стенки и т. д. у грузчика нет номера в массиве, а есть только координаты);

540 - оператором РОКЕ 23658,8 устанавливается режим ввода заглавных букв, чтобы в дальнейшем при опросе клавиатуры избежать лишних проверок. Более подробно об операторе РОКЕ мы расскажем позже;

560 - изображение грузчика выводится на экран после короткого звукового сигнала;

Далее идут строки, которые образуют все вместе блок взаимодействия с играющим, представляющий в данный момент для нас наибольший интерес;

580...640 - блок, в котором осуществляется управление движением грузчика путем изменения его координат, повтор текущего уровня (клавиша L) и выход на начальную заставку при нажатии клавиши Е;

660 - координаты X1, Y1 показывают, куда перемещается грузчик, а X, Y - место на экране, где он находится сейчас. Здесь проверяется клетка, куда должен встать грузчик. Если она не фоновая (не пробел и не «ромбик»), то программа переходит на строку 700;

670 - в клетке, где ранее находился грузчик, нужно восстановить прежний фон, заполнив ее тем символом, который был здесь раньше. Требуемый символ может быть либо пробелом, либо «ромбиком», соответствующим графическому символу D. Этот символ мы берем из массива Р$ и выводим на экран;

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

700 - проверяется условие: если клетка, куда должен встать грузчик, заполнена фрагментом стенки, то переход на строку 550, выводящую изображение грузчика. Координаты при этом не изменяются, так как идти сквозь стенки нельзя;

710 - все графические символы мы перебрали, кроме ящика, который может обозначаться символами С или Е. В этой строке сначала вычисляются направление перемещения ящика, а затем координат клетки, расположенной впереди него (Х2, Y2), то есть того места, куда он перемещается;

720 - проверка содержимого клетки с координатами (Х2, Y2). Если там стена, другой ящик или ящик, поставленный на свое место, то все остается по-старому (безусловный переход на 550);

740 - так же, как и в строке 670, восстанавливается фон клетки, где ранее находился грузчик;

750 - присваивание переменным, обозначающим координаты грузчика новых значений. Место в массиве U$, откуда убран ящик, заполняется фоком из массива Р$;

760 - Если ящик встал на «ромбик», то в массиве U$ на этом месте появляется символ Е, обозначающий ящик, поставленный на свое место.

В противном случае (строка 770) ящик, как и прежде, обозначается символом С;

780 - если ящик не встал на свое место, то он закрашивается желтым цветом. Далее - безусловный переход на строку 550;

790 - если ящик установлен, куда нужно, то он закрашивается белым цветом;

800 - грузчик появляется на новом месте. Эта строка введена для того, чтобы изображение грузчика не пропадало на время последующих проверок;

810...860 - проверка: остались ли не поставленные на свои места ящики или нет. Строка 820 здесь введена для ускорения цикла. Если остался хотя бы один ящик, то происходит переход на строку 550, после чего весь цикл проверок повторяется;

870, 880 - если оказалось, что все ящики поставлены на свои места, то звучит трель, и мы попадаем на следующую строку;

890 - переход на новый уровень, то есть в новый лабиринт-склад, к новому расположению ящиков;

900 - подпрограмма звукового сопровождения начала игры (заменяет при необходимости кодовую подпрограмму MEL 1).

Со строки 1000 начинаются блоки данных, описывающих различные уровни игры, вам предоставляется возможность самостоятельно сформировать лабиринты уровней, начиная со второго. Впрочем, ничто не мешает вам изменить и первый уровень. Нужно помнить только, что каждая строка в кавычках должна состоять из 19 символов, а самих строк должно быть 17. В конце каждого блока необходимо указывать два числа, определяющих начальные координаты грузчика. И последний совет: количество ящиков в лабиринте (графический символ С) должно совпадать с количеством «ромбиков» (символ D).




СОДЕРЖАНИЕ:


  Оставте Ваш отзыв:

  НИК/ИМЯ
  ПОЧТА (шифруется)
  КОД



Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
Ценник - Вам, например, интересно знать по чем в Кемерово масло или в Смоленске водка?
История - Хакеры - статья "ОНО" - об истории появления хакерства. ч.2
Дискуссия - Товарищи зомби!
Humor - Unfiltered: маразматические реальные объявления и высказывания людей, как известных так и не очень из журнала "Крокодил".
Анонс

В этот день...   28 марта