Заметки о DS для новичков
Антон Яковлев
🕛 25.03.2008, 16:19
Эту небольшую статью я посвящаю начинающим разработчикам. Большая часть текста написана по мотивам доклада на КРИ-2007, однако есть кое-что "бонусное", составленное из вопросов, на которые я обещал подготовить ответы.Введение
В настоящий момент консольный рынок является лакомым кусочком для отечественной игровой индустрии. Как правило, издатель находится на Западе и именно он устанавливает свои, порой неожиданные правила. Основная сложность выхода на консольный рынок - это процедура получения статуса консольного разработчика под платформу: издатели неохотно дают проекты командам без статуса, а статус непросто получить без издателя. Одним из способов "прорваться" является участие в проектах под устаревшее поколение или в невысокотехнологичных проектах. Львиная доля игр под DS как раз технологически просты (упор в них делается на геймплей, а не технологию), что, как мне видится, способно облегчить получение разработчиком этого самого статуса. У вас есть идея хорошей казуальной игры? Или не против выпустить порт вашей детской флеш-игры? Пожалуйста, тут вас ждут!
Безусловно, DS - это не только хорошая "транзитная" платформа, но и возможность получить массу удовольствия (а кому-то и ностальгии по 80-м). Программисты наверняка оценят отсутствие аппаратной поддержки чисел с плавающей запятой, а художникам понравится аппаратно ускоренная 2D- и 3D-графика.
Аппаратное обеспечение
Немало информации об аппаратном обеспечении Nintendo DS уже доступно в Сети. Здесь мы не будем пересказывать технические характеристики, а лишь вкратце опишем наиболее интересное "железо" с функциональной точки зрения.
DS снабжен двумя экранами: верхним и нижним. Нижний экран - сенсорный, распознает нажатия с субпиксельной точностью. Впрочем, диаметр эффективной части стилуса и обильные дрожания сводят на нет такую точность. Оба экрана отображают 16-битную графику в разрешении 256х192, состоящую из четырех слоев. Каждый слой может содержать либо 2D-, либо 3D-графику (к сожалению, 3D только в одном слое из четырех). Итоговая картинка на экране формируется путем объединения этих слоев. DS имеет два графических ядра, предназначенных для аппаратного ускорения 2D-графики (по одному для каждого экрана), и одно графическое ядро для 3D-графики. Как правило, гонка за минимизацией использования видеопамяти (ее всего-то 686 Kб) и объема пересылаемого по шине трафика вынуждает использовать такие настройки слоев, которые исключают получение доступа к столь привычному буферу кадра как для 2D, так и для 3D. Последнее сразу исключает многопроходный рендеринг в любых его проявлениях.
Конечно же, все три графических ядра имеют свои уникальные и интересные ограничения и свойства (даже 2D-ядра и то чуть-чуть отличаются). Их детальное обсуждение выходит за рамки этой статьи, мы же отметим только два самых интересных, относящихся к 3D-ядру. Во-первых, 3D-ядро поддерживает только 2 тыс. треугольников на кадр. В совокупности с особенностью построения каждого кадра независимо от результатов предыдущего это ограничение говорит само за себя. Во-вторых, рендеринг осуществляется по строкам: для каждой строки экрана составляется набор примитивов, перекрывающихся с этой линией. Все примитивы складываются в буфер, имеющий ограниченную емкость. Последнее вынуждает отказываться от основанных на частицах спецэффектов (крайне сложно следить за переполнением этого буфера).
Помимо двух экранов имеется два процессора: ARM9 и ARM7. Первый работает на частоте 66Mhz, а второй на частоте шины - 33Mhz. Как уже отмечалось, второй процессор доступен только для ограниченного использования: сэмплирование сенсорного дисплея, поддержка сети, звук и прочее. Важно понимать, что ограниченность выражается в том, что пользователь имеет возможность задать параметры модулям, осуществляющим эту работу, но никак не возможность расширить функциональность. Например, в выдающем сэмплинги сенсорного дисплея модуле есть масса настроек (в том числе настройка частоты сэмплирования), но нет ни одной возможности расширить функциональность (скажем, дописать для определения силы нажатия код, анализирующий сопротивления в районе касания).
DS снабжена двумя слотами для картриджа: один для DS-картриджа и один для GBA-картриджа. Про первый мало что можно сказать за исключением того, что DS-картриджи бывают очень больших размеров - до 2 Gbit, в них отсутствует такое до боли знакомое разработчикам под PS2 понятие как время установки читающей головки (seek time). Cо вторым слотом интереснее: помимо прямого назначения (запуск игр в режиме совместимости с GBA) его можно использовать для установки плат расширений. К примеру, можно соорудить фотокамеру и использовать ее в играх для управления процессом. Подобного рода концепты всячески поддерживаются Nintendo, и даже существует программа партнерства по изготовлению расширений для DS.
Следует отметить, что не все DS-картриджи одинаковы: они различаются типом и объемом основной памяти, а также типом и объемом дополнительной памяти. Основная память доступна только на чтение, а дополнительная - на чтение и запись, она имеет размер, измеряющийся в десятках килобайтов. Тонкость состоит в том, что издателю необходимо оплатить всю партию картриджей перед продажами, на этапе их производства. Стоимость производства сильно зависит от объема основной и дополнительной памяти, что вынуждает разработчиков уменьшать размер игры до того, который готов оплатить издатель (ведь еще неизвестно, как готовый продукт будет продаваться). Конечно, для каждого типа игр есть некоторые разумные пределы на минимальный размер картриджа, но факт остается фактом: чтобы сосчитать количество игр, вышедших на максимальном объеме картриджа, хватит пальцев одной руки.
Несколько слов об отладке. Традиционно для консольных разработчиков доступны так называемые девкиты (development kit, набор для разработчика - прим. авт.). Девкит - это по сути та же самая консоль, но с дополнительными возможностями для отладки: дополнительной памятью, системой связи с отладчиком, устройствами для профилирования и прочим. Существует девкит и для DS. Заказать его можно у Nintendo сразу же после получения статуса примерно за 2 тыс. евро. На вид он отличается от обычной DS наличием коробки военного типа, которая одним шнуром соединяется с DS, а другим - с компьютером. Снабжен вдвое большим количеством памяти и позволяет отлаживать (расставлять точки останова, смотреть значения переменных и т.д.) игры.
Полезность девкита состоит не только в отладке. Помимо своих обычных функций, он позволяет получить доступ к файловой системе компьютера, к которому присоединен девкит, прямо из приложения, запущенного на этом девките. Простор для применения последней возможности воистину широк:
* Подмена ресурсов "на лету" (текстуры, геометрия, звуки, настройки и т.д.). * Сохранение логов для последующего анализа, полезное при применении проходящего ночью игру бота в автоматическом режиме - по сохраненному логу пришедший утром программист сможет понять, что произошло. * Изучение игрового баланса - член фокус-группы проходит сохраняющую логи игру. В логе есть информация обо всех изменениях: передвижения персонажа, оппонентов, кто в кого стрелял и т.д. По этой информации можно оценить, где требуется добавить оппонентов, а где - убрать; решается вопрос об их количественных характеристиках (здоровье, скорость стрельбы и т.д.).
Программное обеспечение
Для того, чтобы создать приложение для любой консоли, нужно иметь под рукой соответствующий SDK. В SDK входит все самое необходимое: компиляторы C/C++, отладчики, стандартная библиотека C\C++, библиотеки так называемых "родных" (native) функций и разнообразный инструментарий (запись образа игры на понятный консоли носитель, средства анализа производительности и т.д.). По факту для DS доступно два таких SDK: официальный от Nintendo и "домашний" от народных умельцев. Как и следует ожидать от закрытой платформы, издавать игры на "домашнем" SDK нельзя. Однако попробовать свои силы и быстро оценить концепт новой игры полезно. На практике, оказывается крайне удобным изготовить видео предполагаемого геймплея и проиграть его на DS: сразу же становятся видны правильные пропорции, цветовые решения и прочее. Например, станет ясно, что планируемое количество врагов на экране плохо различается (отметим, что оно может хорошо различаться на ЖК мониторе - у них разная яркость и цветность).
Неофициальный SDK не требует специального дорогостоящего оборудования для запуска игры. В комплект разработчика неофициального SDK входит обычная DS из магазина, устройство для чтения карт SD, вставляемое в GBA-слот и загрузчик, выполненный как DS-картридж. Полезность такого комплекта состоит не столько в возможности запускать собранные на основе неофициального SDK игры, сколько в возможности запуска игр, собранных с официальным SDK. Это может пригодиться в двух основных случаях:
* вы уже получили доступ к официальному SDK, но еще не получили на руки оборудование (интерес к DS растет, и у Nintendo случаются перебои с отгрузкой оборудования); * вам требуется переслать версию игры людям, не имеющим доступа к записывающему оборудованию либо не имеющим специальных предназначенных для записи картриджей.
Часто имеющие "домашнюю" технодемку начинающие разработчики интересуются, как же их код переживет переход на официальное SDK. Конечно, нужно будет немало переделать. Чего только стоит поиск аналогов "домашних" функций в официальном SDK. Но это не самое страшное: есть непереносимые с "домашнего" SDK тонкости, такие как использование собственных модулей ARM7.
Для DS доступно два официально поддерживаемых компилятора: SN Systems и Freescale Codewarrior (далее - MCW). Последний очень популярен в силу того, что он прилагается к SDK бесплатно. Эта версия известного Codewarrior базируется на GCC с улучшениями и дополнениями. К примеру, имеется хороший стриповщик. Безусловно, не все в Codewarrior сделано хорошо: он по-прежнему использует бинарные файлы проекта, несколько затрудняющие одновременную работу над ними нескольких пользователей.
Самое первое, видимо, с чем столкнется начинающий разработчик под DS - это отсутствие привычного типа float. На самом деле он конечно есть (доступен при помощи специального расширения в MCW в нескольких вариантах, отличающихся уровнем совместимости со стандартом), но программно эмулируемый. Самая быстрая реализующая float библиотека проигрывает в среднем в два раза числам с фиксированной запятой. Последнее обуславливает повсеместное использование чисел, векторов, матриц и кватернионов, заданных в формате с фиксированной запятой. Обеспечивая более высокую производительность, это решение добавляет тонкостей. К примеру, приходится отказываться от привычных инкрементальных трансформаций (как правило, поворотов). Это значит, что если вы раньше при вращении объекта текущую матрицу умножали на матрицу "доворота" на нужное количество градусов, то теперь вам потребуется хранить начальную матрицу объекта и каждый раз умножать ее на матрицу поворота на полный угол.
Впрочем, не все так плохо: в каждой DS есть два математических сопроцессора. Первый занимается исключительно делением чисел различной битности (32/32, 64/64, 64/32 и др.). Второй считает квадратный корень. Оба сопроцессора работают в синхронном и асинхронном режиме. С синхронным режимом все просто, а вот с асинхронным - интересно. Во-первых, сразу ясно, что асинхронное деление и извлечение квадратного корня представляют из себя инструмент для низкоуровневой оптимизации функций, вызываемых очень много раз на кадр. Во-вторых, многопоточность создает известную проблему "блокировка ресурсов". Это приводит к тому, что на практике никто не выполняет код в другом потоке, пока происходит деление в текущем. Вместо потоков производят переупорядочивание кода так, чтобы во время выполнения асинхронного вызова можно было считать что-то, что потом пригодится. Например известно, что за время вычисления квадратного корня можно вычислить разность двух векторов и посчитать скалярное произведение в случае если все аргументы прогружены в регистры. Надо ли упоминать, что в таком коде стремятся минимизировать количество вызовов других функций и обращений к пямяти: все что можно предварительно прогружается в кэш, данные - в регистры (их, кстати, больше 30). Таким образом, соптимизированный код выполняется на 40% быстрее, чем его грамотный аналог на C++. Впрочем, обратная сторона медали даст о себе знать очень быстро: стоимость поддержки оптимизированного кода возрастает чуть ли не в разы. Дональд Э. Кнут писал, что преждевременная оптимизация - корень всех зол. В этом свете стоит четко понимать, что и на какой стадии проекта нужно оптимизировать: запутанный код никогда больше не будут изменять, только перезахоранивать при необходимости.
Не лишним будет заметить, что официальный SDK содержит две большие части: низкоуровневые функции (переместить одну память в другую, задать режим отрисовки полигонов, открыть файл и т.д.) и высокоуровневые функции (загрузить подготовленную модель из файла и отправить на отрисовку, открыть файл на присоединенном компьютере, загрузить элемент 2D анимации и т.д.). Безусловно, использование высокоуровневых функций опционально: никто не мешает самостоятельно соорудить надстройку над низкоуровневыми функциями. Разработчики делятся по этому признаку на две категории:
* Использующие в основном высокоуровневые функции. Они получают быстрый старт, но ценой меньшей управляемости в дальнейшем; кроме того, эти функции в известном смысле диктуют архитектурные решения. * Использующие в основном низкоуровневые функции. Они получают большую гибкость и управляемость ценой медленного старта.
Разумеется, решать что использовать в конкретном случае нужно на месте, и универсальных советов тут фактически нет. В любом случае, нужно смотреть на мир реально: Nintendo предоставляет хороший инструментарий, учитывающий специфику платформы. В него входят: экспортеры текстур, анимаций, моделей из популярных 3D пакетов, а также редакторы 2D и звука. Безусловно, они не идеальные, но сможете ли вы за короткий срок написать лучше то, что писалось и поддерживалось уже более трех лет?
Последний этап в разработке любой консольной игры - это прохождение контроля качества у платформодержателя. В Nintendo такая процедура называется LOT Check и состоит в сборке игры со специальной версией SDK с последующей отправкой на проверку. В зависимости от результата занимающей около недели проверки приходит ответ: либо игра "готова" к печати, либо "не готова". В первом случае можно праздновать завершение проекта, а во втором случае перед повторной посылкой потребуется произвести разнообразные "улучшения" с целью удовлетворить требованиям. Не лишним будет заметить, что все требования известны заранее и доступны разработчику на официальном сайте в виде документа на 30 страницах. Каждое требование - либо необходимое, либо рекомендуемое. Всем необходимые требования нужно соблюсти, а рекомендуемые хорошо бы, но не обязательно. Сложность переделок по требованию может сильно варьироваться от минимальной (заменить текст с "Touch Screen to Continue" на "Touch the Touch Screen to Continue") до существенной (исправить "corrupt graphics in Location 1").
Заключение
Нередко начинающие разработчики получают доступ к SDK для разработки небольшой игры. Типичный срок для такого проекта составляет 6-8 месяцев. В бюджете предусматривается 2-3 программиста (плюс опционально 1 эксперт по платформе) и два художника. С чего начинают делать игру? Как правило, с создания технологии для скорейшей и лучшей реализации игрового замысла. Однако в борьбе за технологию не следует забывать, что конечный продукт - это игра, а не набор технологий. Поэтому, в первой итерации сборника технологий (еще пока даже не движка) должно быть только то, что позволит создать первый прототип игры. Как только сборник готов, следует приступать к прототипу. Не стоит недооценивать этот этап: прототип позволяет ясно понять, какую игру стоит делать, а какую не стоит. Кроме того, прототип позволяет придать так называемую production value каждой планируемой технологии. Часть априори нужных технологий станет ненужными апостериори и наоборот. Несмотря на то, что идея проста, в отечественном игропроме она непопулярна. Чтобы в этом убедиться, достаточно просмотреть соответствующий блог разработчиков и обратить внимание на те задачи, которые ставятся на разных этапах разработки.
Несомненно, следует соблюдать баланс Силы: отсутствие качественных технологий затруднит создание качественной игры. Но и это не страшно! На DS особенно хорошо продаются игры жанра "треш": хороший геймплей продается даже на слабой технологии. Обратное неверно.
Статья написана на основе доклада на КРИ-2007.