ZX Review
#7-8-9-10
08 ноября 1997 |
|
Читатель-читателю - Программирование аркадной игры со скроллингом экрана.
(c) М.Татаринов, г.Соликамск, Пермская обл. Всем, кто задумал делать ар- кадную игру, посвящается... Если вы решили написать игру со скроллингом экрана и не знае- те, как это сделать, то данная статья поможет вам. Хочу ска- зать, что ограниченный обьем статьи не позволяет мне привес- ти конкретные примеры (полный пакет процедур для работы с кар- той занял у меня около 2-х кило- байт), но если вы решились пи- сать игру, то вы достаточно ква- лифицированный программист и разберетесь, что к чему. Все, сказанное в статье, имеет прак- тическое подтверждение, поэтому смело пишите свои процедуры. 1. Формат карты Минимальным элементом на кар- те является блок размером 32x32 пикселя, т.е. 4x4 знакоместа. Такие размеры выбраны не случай- но, вот их преимущества: 1) 4 - это одна из степеней числа 2, так что все арифмети- ческие операции предельно упро- щаются за счет использования ко- манд сдвига. 2) Огромный плюс - это малые размеры памяти, занимаемой кар- той. Так, карта размером 1024x16 знакомест (8x8) занимает всего лишь 1024 байта, карта же из блоков 8x8 займет в 16 раз боль- ше, т.е. 16 Кб. 3) 1 блок 4x4 печатается быс- трее, чем 16 отдельных знако- мест. Хотя размер одного блока ра- вен 16x8+16=144 байта (если с атрибутами), 30-40 блоков впол- не хватает и не занимает много памяти. 2. Немного о графическом наборе В каком формате хранить ин- формацию о графических шаблонах, дело ваше. Я же предлагаю формат растрового имиджа, который печа- тается быстрее. 4 линии ───────> ┌────────┐ │ ┌────────┐ │ ├───────>┤ │ │ │ │ ├───────>┤ │ ├────────┤ │ ├───────>┤ │ │ │ │ 16 линий├───────>┤ │+атрибуты├────────┤ │ ├───────>┤ │ │ │ │ ├───────>┤ │ ├────────┤ │ ├───────>┤\│/ │ │\│/ └────────┘ │ └────────┘ │ Стрелками показано направле- ние печати, т.е. линия за лини- ей. Информацию об атрибутах я предлагаю хранить в виде отдель- ного файла, который приписывает- ся в конец BitMap'а. Сделано это опять же для упрощения расчета адреса блока. Т.к. размер блока без атрибутов равен 128 байтам, то вычислить смещение в файле шаблонов чрезвычайно просто: ;в B - номер шаблона ADD A,A ;X2 - в данном случае уместно, т.к. для ;файла, в котором больше 127 блоков, вам ;места не хватит LD H,0 LD L,A ADD HL,HL ;x4 ADD HL,HL ;x8 ADD HL,HL ;x16 ADD HL,HL ;x32 ADD HL,HL ;x64 ADD HL,HL ;x128 LD DE,TABL ADD HL,DE 3. Вывод карты с точностью до знакоместа по произвольным коор- динатам (имеются в виду коорди- наты на карте, а не на экране). Внимательный читатель навер- няка заметил, что дискретность карты составляет блок 4x4, сле- довательно, и скроллинг должен быть не меньше, чем на 4 знако- места. Такая дискретность подхо- дит для Map Editor'а, но никак не для игры, поэтому необходи- мо разработать прием, позволяю- щий вывести в окно произвольный участок карты с точностью до знакоместа. 0┌────┬────┬─ Y LENGTH ──┬────┬────┬─ 1│0 │1 │2 │3 │4 │5 │6 │ -│----│----│----│----│----│----│----│- 2│ │ ╔══════════════════════╗ │ 3│ │ ║│ │ │ │ │ ║ │ ─┼────┼───║┼────┼────┼────┼────┼─║──┼─H 0│7 │8 ║│9 │10 │11 │12 │13 │ E 1│ │ ║│ │ │ │ │ ║ │ I -│----│---║│----│----│----│----│-║--│─G 2│ │ ║│ │ │ │ │ ║ │ H 3│ │ ║│ │ │ │ │ ║ │ T X ─┼────┼───║┼────┼────┼────┼────┼─║──┼─ 0│14 │15 ║│16 │17 │18 │19 │20 │ 1│ │ ║│ │ │ │ │ ║ │ -│----│---║│----│----│----│----│-║--│- 2│ │ ║│ │ │ │ │ ║ │ 3│ │ ║│ │ │ │ │ ║ │ ─┼────┼───║┼────┼────┼────┼────┼─║──┼─ 0│21 │22 ╚═23═══24═══25═══26═══27 │ 1│ │ │ │ │ │ │ │ -│----│----│----│----│----│----│----│- 2│ │ │ │ │ │ │ │ 3└────┴────┴────┴────┴────┴────┴────┴─ 0123 0123 0123 0123 0123 0123 0123 Взгляните на рисунок, и вам сразу станет понятно, как рас- считать требуемую позицию окна с координатами (X,Y) на карте. Если вы не поняли, то привожу следующие выводы: 1) Очевидно, что если карта имеет размеры Length * Height, то для грубого расчета позиции окна (X,Y) стартовое смещение распечатки будет равно X+Length* Y (координаты заданы с точностью 4x4). Чтобы увеличить точность позиционирования окна, мы вводим смещение окна отдельно по X и Y. Оно может быть от 0 до 3 и по- казывает смещение относительно начала текущего блока. На рисун- ке эти координаты = (1.2;1.1), где целая часть - номер блока на карте, дробная - смещение. 2) Чтобы вывести карту на эк- ран, нужно рассчитать координа- ты печати на экране. Дробные части координат X и Y (в данном случае это 2 и 1), если их обра- ботать командой NEG, дадут нам стартовые координаты печати на экране или в буфере, т.е. 2 ста- нет -2, 1 станет -1 (#FE, #FF, если угодно). 4. Как работает подпрограмма печати блока и как ускорить вы- вод карты. Наверняка вы заметили, что реальное количество знакомест, печатаемых в окне, меньше, чем количество знакомест, входящих в состав окна, поэтому число выво- димых блоков должно быть на 1 больше, чем длина и высота окна, деленные на 4. То есть, если размеры окна 32x16, то число пе- чатаемых блоков 32/4+1=9; 16/4+ 1=5. Из этого следует, что под- программа печати блока должна уметь отсекать невидимые знако- места (клиппирование). Хочу ска- зать, что операции сравнения и увеличенное число блоков резко снижают быстродействие печати. Для увеличения скорости я приме- нил прием использования двух подпрограмм печати. Посмотрите на рисунок. Мы видим, что не все блоки требуют отсечения, поэто- му мы создаем еще одну подпрог- рамму печати, которая не отсе- кает элементы блока. Эта под- программа должна иметь цикл только в 4 знакоместа, а 8 лиш- них выводятся без цикла с по- мощью LDI. Привожу вам "портрет" окна 32x1 знакомест. Clip - от- секать элемент, No clip - не от- секать: 0 9 блоков clip, но если смеще- ние=0, то 9 блоков no clip. 4 первый - clip, 7 no clip, 1 clip. 8 аналогично. 12 аналогично. 16 так же, как 0, только при смещении = 0 не печатается. 5. Скроллинг Ну, это элементарно. Рассмот- рим скроллинг вперед на 1 знако- место. Пусть переменные HPOS и HDISP играют роль координат и смещения. Проверяем HDISP на 3. Если = 3, то HDISP:=0, HPOS:= HPOS+1; иначе увеличиваем HDISP. В другие направления - аналогич- но. Напоследок скажу, что печать карты должна идти в буфер, кото- рый я организую с адреса #E000 (подробнее об этом - см. книгу "Прикладная графика"), и в свя- зи с этим формат буфера задает сам программист. Наиболее удоб- ная раскладка буфера - линия за линией, что существенно упрощает процедуру печати. И еще. Если вам необходимо больше быстродействия, советую пропускать нулевые элементы при печати (пробелы), но тогда вам придется использовать подпрог- рамму очистки буфера. Этот метод наиболее эффективно повышает быстродействие, но в результате скорость игры не постоянна. P.S. Если вы собираетесь ис- пользовать стек для повышения быстродействия и намереваетесь использовать звуковое сопровож- дение, работающее по IM 2, то скорость воспроизведения звука будет "плавать". Это вызвано тем, что при работе со стеком необходимо запрещать прерывания. При написании предыдущей игруш- ки я столкнулся с этой пробле- мой, т.к. печать блока и очис- тка буфера использовали стек. Попутно хочу ответить на вопрос Васильева Антона (N 4-5, 1996). Я тоже занимался пробле- мами обработки оцифрованного звука на AY, и вот что я делал. Способ записи звука практически не отличается от предложенного Сергеем Беловым (читаем шестой бит, вращаем регистр), только я использовал псевдокомпрессию. На AY оцифрованный звук выводится через регистры амплитуды, а мак- симальное значение амплитуды не превышает 15, т.е. четырех би- тов. В связи с этим, в 1 байт можно поместить в 2 раза больше информации: 1) 0000xxxx=E - 1 цикл чтения 2) xxxxyyyy=E - 2 цикл чтения 3) (HL)=E - запоминание INC HL В регистрах 11 и 12 задается скорость смены амплитуды при ис- пользовании встроенного генера- тора огибающей. Прим.ред.: Спасибо Максиму за эту весь- ма интересную статью. Только вот хочется добавить пару слов по поводу использова- ния стека при выводе карты. Да, действи- тельно, прерывания при этом должны быть запрещены, но избавиться от "плавания" звука при этом все же возможно. Для этого вывод карты надо начинать сразу после HALT, а сам вывод должен умещаться в коли- чество тактов между прерываниями. Тогда вы успеете разрешить прерывания как раз к мо- менту, когда следующее прерывание должно произойти. * * *
Другие статьи номера:
Похожие статьи:
В этот день... 21 ноября