Написание аркадной игры После сборки 16-цветного девайса на пе─ нтагоне (см.статью) я решил закрепить этот успех написанием игрушки под 16 цветов.Бы─ ла выбрана идея игры Pang. Сначала я скон─ струировал шарики (в фотошопе с использо─ ванием преобразования декартовых координат в полярные) и написал выводилку спрайтов (чтобы посмотреть, как эти шарики прыгают на фоне картинки). Выводилка спрайтов и стиралка спрайтов попеременно вызываются в цикле LOO (так в программе и сейчас). Пока обновляется 2-й экран,видно 1-й,и наоборот (так и сейчас). Спрайты конвертировались из 16-цветного .bmp (палитру для конверсии можете нарисо─ вать сами, это очень просто: сначала неяр─ кие, потом яркие, в стандартом порядке,0-й цвет будет прозрачный) прилагаемым исход─ ником bmpTOspr.H. Исходник bmpBKspr.H де─ лает то же самое, но переворачивает спрайт лицом влево, если он был лицом вправо (и наоборот). Потом я попросил Shiru Otaku вытащить цветные спрайты персонажа и прочих объек─ тов этой игры с первой попавшейся пристав─ ки. Shiru Otaku работает очень быстро, по─ тому нужные спрайты были добыты за 3 дня. Они (в SNES версии) нарисованы под 32768 цветов (16 цветов на спрайт, 256 цветов на экран). Перевести все эти цвета в 15 стан─ дартных было очень просто - достаточно бы─ ло разложить все спрайты на одну картинку (получилось около 60 разных цветов) и от─ редактировать цвета в палитре.При этом да─ же сохранились практически все цветопере─ ходы.Благодаря тому,что в SNES-версии раз─ решение 256x224, не пришлось масштабиро─ вать спрайты. Параллельно я добавил в программу (ко─ торая,как вы помните,умела только выводить спрайты) следующие вещи: 1. Интеллект, который работает на преры─ вании (см.статью про игровой цикл в IG#6). Этот интеллект оперирует 11-байтными опи─ сателями юнитов (тип персонажа, его фаза, координаты,скорости,время и энергия). Эне─ ргия в Pang не нужна,это поле зарезервиро─ вано для игр-"стрелялок". Оно двухбайтное, потому что в Wolf2004 еле хватало одного байта, хотя в Wolf2004 нет боссов с кучей энергии (способ убивания Гитлера основан не на энергии, а на хитрости). К слову, в Wolf2004 ещё и не было скоростей движения спрайтов. Взамен организовывался временный (!) буфер направлений движения для персо─ нажей, близких к игроку. Так пришлось пос─ тупить из-за того, что монстр/объект в Wolf2004 с древних времён описывался 8 ба─ йтами,и разбайтовка этих байт торчала сли─ шком во многих местах программы (не через индексные регистры) - переделать было бы очень трудно. В Wolf2004 нужно было разде─ лить живых и неживых персонажей в разные списки в разных форматах (живым больше байт, неживым меньше). Но это не было сде─ лано.Увеличить универсальный описатель с 8 байт до 9 и выше было нельзя - не хватало памяти, например, на уровне L. Впрочем, в Wolf2004 есть несколько свободных килобайт в верхней памяти,там предполагалось разме─ стить работу с сетью (LAN). 2. Пересчитывалка координат персонажей в координаты на экране,передаваемые в список SPRS (которым пользуется процедура вывода спрайтов). Заодно тип персонажа и фаза пе─ ресчитываются в адрес спрайта. И вообще, переброска перед выводом требуется для на─ дёжности - ведь если из цепочки был удалён один персонаж (а удаляется он по прерыва─ нию,т.к.интеллект висит на прерывании!),то выводилка может случайно перескочить через конец списка или может взять половину дан─ ных от одного персонажа (и тут случайно - БАЦ - прерывание!), а вторую половину - от другого.Так что если перекидывалка узнаёт, что во время её выполнения произошло пре─ рывание, она начинает перекидывание снача─ ла. В Wolf2004 персонажи не удалялись (ка─ жущееся "удаление" - это просто занесение в Y-координату специального числа) и не добавлялись,поэтому не требовалось копиро─ вание списка персонажей перед циклом выво─ да. Чтобы совсем избавиться от глюков,позже я организовал: 2.I. Проверку на случай пе─ реполнения буфера под спрайтами. 2.II. Вы─ ход из цикла искусственного интеллекта по─ сле выполнения операций удаления каких-ли─ бо персонажей (можно было поступить иначе: сдвигать текущий указатель юнита, если был удалён кусок списка,лежавший в памяти ниже этого юнита). 3. Списки фаз для пересчёта фаз персона─ жей в адреса спрайтов. 4. Для каждого персонажа адрес списка фаз (п.3) и адрес процедуры обработки пер─ сонажа (для цикла интеллекта). Сначала спрайты не имели заголовка,и их размеры лежали отдельно.Заголовок я сделал потом. Длину спрайта в байтах я внёс в за─ головок в самый последний момент, раньше эта длина вычислялась. Поэтому в исходнике такая оригинальная загрузка спрайтов - че─ рез макрос iNCBIN. Этот макрос подставляет в заголовок спрайта то самое поле длины. Макрос выглядит так запутанно потому, что для работы он должен узнать текущее смеще─ ние компиляции (ведь спрайты грузятся вну─ три блика DISP..ENT !). Фоновые экраны у меня первоначально грузились просто из bmp,лежащего на диске─ те. Но это неудобно и некрасиво. Поэтому я организовал упаковку. Если,например,заста─ вку к Pang паковать в виде 4bit bmp, то получается rar размером 2790. А если пако─ вать разложенную по столбцам,то получается rar размером 2254. XOR между строк и XOR между столбцов не помогает. Распаковка заставок (DEPKS16) происхо─ дит так: 1. включаем 1-й экран (мог быть включен 2-й). 2. очищаем 2-й экран;включаем 2-й экран. (Вариант: 2.очищаем #5800..#5aff; включаем 6912 режим.) 3. bmp, упакованный rar'ом (без заголов─ ка),кладётся в хвост страницы #14. (Удобно перекидывать из другой страницы через 2 LDIR'а, используя область #a000...#bfff.) 4. вызывается smallunr.H (с параметром RARS=#6000) - распаковка rar на адрес чуть ниже #a000 (например, #9f00). Назовем этот адрес "addr". Сейчас данные в addr..addr+#5fff (почти до конца памяти), включена #14 страница. 5. разворачиваем экран #4000 (начиная с addr+192, после столбца пропускаем 3*192). 6. разворачиваем экран #6000 (начиная с addr+(3*192)). 7. убиваем каждый 2-й столбец в блоке данных (192 байта копируем, 192 пропускаем и т.д.). Сейчас данные в addr..addr+#2fff (почти до #d000). 8. разворачиваем экран #e000 (начиная с addr+192, после столбца пропускаем 192). 9. убиваем каждый 2-й столбец в блоке данных. Сейчас данные в addr..addr+#17ff (почти до #b800). 10. разворачиваем экран #c000 (берём ба─ йты с addr, подряд). 11. включаем 1-й экран (или включаем 16- цветный режим, если выключили). Как видите, используется всего 2 дей─ ствия-процедуры ("разворачивать" и "уби─ вать") и не используются лишние области памяти (кроме остатка одной из экранных страниц - страницы #14 )! (На АТМ страницы другие.) Память #a000..#bfff - буфер изоб─ ражения под спрайтами, и его вполне можно портить, пока спрайтовый движок не вызыва─ ется. А вызывается он только внутри цикла LOO. Дальше было просто добавление програм─ мок и подпрограммок искусственного интел─ лекта. Эти программки довольно однообраз─ ны. Во всех используются одни и те же ре─ гистры: IX (адрес описателя персонажа), BC (Y), DE (X). Сделана сначала одна процеду─ рка проверки коллизий,а потом ещё две.Одна проверяет коллизию героя с врагами (вызы─ вается из обработчиков героя и перебирает врагов, хотя можно было бы вызывать из об─ работчиков врагов и ничего не перебирать - герой-то один). Другая проверяет коллизию гарпуна с врагами (аналогичное замечание). Третья - коллизию героя с призом. Были между делом нашлёпаны процедурки вывода счёта и времени, таблички уровней и прочая мелочь. В конце концов из запасников были выта─ щены маленькие музончики (которые я писал в 2002-2004 гг.) и вставлены в игру. Был взят модуль звуковых эффектов из старого доброго Wolf2004, в звуках немного измене─ ны параметры.Этот модуль не универсальный, он умеет играть только небольшой класс звуков (например, в процессе проигрывания эффекта не могут меняться периоды тональ─ ника и шума). Сборка игры во время её написания прои─ зводилась много раз (как минимум перед ка─ ждым тестированием на реальном пентагоне) и проблем не вызывала, т.к.это автосборка. Основной блок плюс спрайты пакуется в бей─ сик-файл. Файлы с музыкой и картинками ле─ жат отдельно и подгружаются (в странички) через #3d13 после старта игры. Программу, оформленную таким образом, можно пересоби─ рать хоть по 100 раз на дню. Меня удивляют некоторые программисты, которые при каждой сборке своих программ вручную запускают пакер и так же вручную приклеивают загруз─ чик (вручную вводя размеры файлов и пр.). Программа писалась под Unreal Speccy v0.32b8 и между делом проверялась на реа─ льном пентагоне. SMT оперативно организо─ вал поддержку 16-цветного устройства в эмуляторе,благодаря чему перетаскивать иг─ ру на пентагон для проверки приходилось не так уж часто. От момента запроса спрайтов до релиза игры, т.е. показа её заинтересо─ ванным лицам (в двух сборках:для Пентагона и АТМ !) прошло 17 дней. Для меня это ре─ корд. Лестницы и блоки я делать не стал - игра и сейчас имеет хорошую playability,да и проект изначально задумывался как недол─ гий. Об ускорении этого движка. Программа создавалась как кроссплатфор─ менная - легко переделываемая, кроме того, обучающая - легко понимаемая (обратите внимание на количество комментариев в ис─ ходниках). Поэтому хитрости не были приме─ нены. 1. На АТМ можно поместить страницу гра─ фики в область ПЗУ и не LDIR'ить спрайты перед выводом. Того же можно добиться на пентагоне, если положить самые популярные спрайты (т.е. шарики и верёвку - итого 4 спрайта) в нижнюю память и вставить небо─ льшую проверку перед LDIR'ом. Попробуйте в исходнике. Выигрыш должен быть небольшой - 21 t/байт (сейчас ў130 t/байт, включая RESPR ). Причём этот выигрыш считается от процессорного времени, оставшегося после вычитания времени на музыку (5% для 70000 t),интеллект (10% по оценке для 70000 t) и вывод цифр (5%?). Т.е. общий выигрыш можно оценить в (21 t/130 t)*(100%-10%-5%-5%) < < 13% времени. На пентагоне в нетурбо выи─ грыш меньше - где-то 11% (т.к. 45000 t вместо 70000 t,в силу чего музыка и интел─ лект забирают порядка 30% ). 2. При использовании большого объёма па─ мяти можно хранить картинки распакованны─ ми,а шрифт - в виде спрайтов букв под раз─ ные раскраски. Но и сейчас можно не распа─ ковывать одну и ту же картинку перед каж─ дым входом в один и тот же уровень, а про─ сто стереть с неё спрайты (с обоих экра─ нов). Попробуйте в исходнике. 3. При наличии копии заднего плана можно не сохранять фон под спрайтами,а восстана─ вливать его прямо из копии заднего плана. На пентагоне неактуально (рабочий экран и копия заднего плана не помещаются в одно адресное пространство),сработает только на АТМ. Выигрыш не больше 16 t/байт (сколько точно - не ясно, т.к.должен быть полностью переписан RESPR ). И две проблемы: 3.I. вывод цифр замедляется в полтора раза (ес─ ли считать,что они уже развёрнуты по реко─ мендации 2 ); 3.II. при написании игр со скроллингом скроллинг замедляется в полто─ ра раза,а он и так должен быть ужасно мед─ ленный (вывод двух экранов,т.е. 48k!). Ко─ нечно, для некоторых игр вообще не нужно запоминать задний план и восстанавливать его под спрайтами - можно просто перестра─ ивать весь задний план (на одном экране, т.е. 24k) в начале каждого цикла вывода спрайтов. Alone Coder