Создание графики для nes/dendy
Предыдущие мои статьи рассказывают о том как начать программировать под денди на ассемблере. Мы научились отрисовывать спрайты и background, так же мельком обсудили что такое таблица атрибутов и таблица имен, так же мы разобрались как прочитать контроллер. В тех статьях Я использовал chr от игры super mario bros 2 потому как не художник, но все же для создания игры мне пришлось искать инструменты какое мне помогут в создание своей графики для игры. Под катом этапы разработки графики.
Довольно много времени ушло на то что бы найти инструмент под linux для создания таблицы имен, через какое то время я даже начал писать своё на php. Идея была проста, и уже был близок к завершению. Возможно конвертировать изображение bmp или png пройдя попиксельно. С лева на право 128 пикселей, и с верху в низ 256 строк. Далее определяем цвет каждого пикселя, а таких может быть всего 4-ре и в зависимости от цвета ставим соответствующие биты, каждый пиксель в файле chr описывается 2 битами, по следующему принципу:
цвет 0 = 00 = 00000000
цвет 1 = 01 = 00000001
цвет 2 = 10 = 00000010
цвет 3 = 11 = 00000011
То есть эти 2 бита всего лишь последние 2 бита порядкового номера цвета. При этом в спрайтах цвет 0 — прозрачный цвет. В background’e это цвет фона.
В chr буквально храниться 2 банка, 128 на 128 пикселей. Часто 1-банк используется для спрайтов (и называется левым), 2-й банк в свою очередь используется для спрайтов фона (ну или тайлов, Я могу ошибаться в терминологии). С этим разобрались, и вот как только Я заканчивал свой скрипт, то нашел уже готовый на node.js img2chr
Скрипт устанавливается довольно просто
$ npm install -g img2chr
У данного скрипта есть 2-ва параметра 1-й это файл картинки (я использую png), 2-й это файл куда надо сохранить chr
img2chr test.png test.chr
После этого мы можем подключать chr в коде и использовать его.
Немного об эмуляторе FCEUXПопробовал несколько эмуляторов к моменту написания этой статьи, оказалось что более всего удобен FCEUX под Windows, запущенный из под wine. Он предоставляет дебагер, и может дампить nametable и attribute table что довольно удобно для правильного рендера уровней.
Как я сказал выше Я не художник, и тем более не умею красиво рисовать. Первым делом я создал изображение 128×256 пикселей расчертил по 8 пикселей ячейку, ошибся в первой ячейки, но оказалось не критично.
Картинка с линиямиЗеленой линией я разделил картинку на две страницы. Далее я нарисовал грубые контуры будущих спрайтов.
Грубый набросокПосле чего я подумал что когда персонаж будет стоять то его тело и руки будут симметричными, по этому сократил количество спрайтов, удалив похожие, ведь их можно аппаратно отобразить по горизонтали или вертикали. При этом добавил спрайты оружия и кулаков, хотел сделать кулаки другого цвета.
Кулаки и удаленные спрайтыДалее я начал работу над сглаживанием контуров, приводя контуры к более геометрически правильному виду, удалив лишние пиксели, и там где не хватало добавил. Часть изображения начал раскрашивать уже в оттенке серого.
Контуры и цветаДалее я продолжил раскраску спрайтов в соответствующие цвета
Цвета промежуточный вариантВ завершение я удалил сетку с изображения. И раскрасил оставшиеся части. Воображение у меня не такое богатое, что бы рисовать хорошо, но что то более менее среднее получилось.
Окончательный вариантПосле этого мне оставалось одно запустить команду
img2png test.png t.chr
Импортировать себе в код и нарисовать фон и спрайты. Напомню что спрайты рисуются довольно просто последовательной записью в порт PPU $2004
Y — координаты
Номер спрайта
Маска отображения
X — координата
Типичный код отрисовки спрайта выглядит так
LDA #100 ; загружаем в акумулятор A значение 100
STA $2004 ; сохраняенм значение координаты Y в порт $2004
LDA #$01 ; спрайт под номером 1 (0-я строка, 1-й спрайт)
STA $2004 ; записываем спрайт в порт
LDA #%00010110 ; маска
STA $2004
LDA #100 ; x координата
STA $2004
И на экране был выведен мой спрайт. Что не могло не радовать. После этого я вывел все спрайты для отрисовки героя их вышло 10, конечно это очень большое количество спрайтов, так как мы можем достичь ограничений приставки например 64 спрайта одновременно на экране, но об этом мы поговорим в следующих статьях.
Предыдущие статьи:
Программирование NES
Считывание контроллера