Денди сколько цветов
Это пост про ограничения старых видеоигр. Сам я под NES никогда не программировал, но с архитектурой поверхностно познакомился. Теперь я не могу играть в игры для NES, не задумываясь, как же они устроены. Иногда это на столько вызывает восхищение, что невольно забываешь про саму игру. «Чему же там восхищаться?», — скажете вы. Да просто укладываться во все ограничения NES, но при этом делать игру красивой, — это действительно целое искусство.
Сейчас я постараюсь рассказать об этом вам, максимально всё упростив.
На NES всё отображаемое на экране делится на спрайты и фон. Спрайты — это объекты, которые двигаются по экрану. Как правило, это непосредственно ваш герой и враги. Иногда это ещё какие-то предметы, но тут всё уже сильно зависит от игры. Фон — это собственно то, что находится позади. И у спрайтов, и у фона есть уйма ограничений.
Фон на NES делится на квадраты размером 8 на 8 пикселей, которые называются тайлами. Итого таких квадратов 30 в высоту и 32 в ширину. При этом фон может плавно двигаться горизонтально и/или вертикально.
Во многих играх, особенно старых, можно заметить, что игра состоит из таких повторяющихся квадратов. Вспомните Super Mario Bros., Bomberman или Battle City. Дело в том, что в память NES можно загрузить одновременно весьма ограниченное количество таких рисунков, поэтому приходилось использовать одни и те же повторно.
Помимо этого существенные ограничения накладывались на цвета. Всего NES может отображать около 53-55 цветов, учитывая повторяющиеся и похожие. По тем временам это было не так уж мало, но всё не так просто. Используются такие штуки, как палитры:
- Палитра — это набор из четырёх цветов, т.е. какие-то четыре цвета из этих 53-55 цветов
- Таких палитр для фона может быть только четыре, при этом один цвет в каждой из них должен быть одинаковым
- Каждая группа из четырёх тайлов (2x2) отображаемых на экране может быть ассоциирована с одной из этих палитр
Это может быть не так просто понять с первого раза. Попробую объяснить на пальцах. Взгляните ещё раз на картинку выше. Каждый квадратик раскрашен не более, чем в четыре цвета. При этом они делятся на три типа: чёрно-бело-голубые, черно-зелёно-голубые, чёрно-коричневые. Возможно, что используется и четвёртый, но я не заметил.
Цвет помеченный звёздочкой постоянно меняется, так монетки и вопросики мерцают. Да, монетки — это часть фона. И именно поэтому облака и кусты — это один и тот же рисунок: тайл один, палитра выбрана разная. Сэкономили немного памяти, но ведь совсем незаметно с первого взгляда.
Как я уже говорил, фон может двигаться. Для этого обычно используется мирроринг, но в эти подробности я вдаваться не буду. При этом есть возможность разделить экран на две части и двигать их отдельно друг от друга, именно так обычно делается неподвижная строка с информацией о жизнях, здоровье, очках и прочем.
Спрайты
Если вы разобрались с ограничениями фона, со спрайтами всё будет легко. Суть в том, что это движущиеся на экране объекты размером 8x8 или 8x16 пикселей. Причём они все одновременно должны быть либо 8x8, либо 8x16, что накладывает несколько других ограничений. В лучшем случае (зависит от размера) всего их может быть аж 64, но на одной строке может отображаться не более восьми, даже если соответствующая область спрайта прозрачная, поэтому слишком много подвижных объектов не сделаешь. Правда, некоторые игры всё-таки делают, заставляя один из спрайтов исчезать на долю секунды, что приводит к неприятному мерцанию. Наверняка многие замечали такое. На цвета наложены примерно те же самые ограничения, что и для фона, но для спрайтов даются отдельные четыре палитры, один из цветов при этом считается за прозрачность. То есть получаем всего три цвета + фон…
Луиджи же — это просто Марио с другой палитрой. Обратите внимание — у Марио рукава, глаза, волосы и усы одного цвета. Именно поэтому у Луиджи глаза, волосы и усы стали зелёными.
Как же так получается?
А теперь взгляните на игры для NES, учитывая описанные выше ограничения. Как же так получается, что фон может быть только из 13 цветов, но многие игры запомнились очень красочными? Как же при таких маленьких спрайтах мы сражались с огромными боссами? Игры начинают выглядеть совсем иначе.
Например, Chip and Dale 2:
Всё весьма красочно и разноцветно, при этом разработчики вписываются во все ограничения.
Как только мы доходим до второй половины уровня, появляются новые цвета:
Просто в момент, когда мы переходим в другую локацию, и экран темнеет, в память загружается уже новые палитра и тайлы. Так создаётся впечатление, что игра гораздо более красочная, чем она есть на самом деле: эти самые 13 цветов достаточно часто меняются от уровня к уровню.
Выше я описал, что фон может делиться на две части, которые движутся отдельно. Именно так сделана начальная заставка, где летит дирижабль Толстопуза:
Колючая проволока внизу движется с одной скоростью, фон с другой, сам дирижабль — это спрайт, который движется с третьей скоростью. Так создаётся иллюзия объёма.
Бывают и совсем другие приёмы. Посмотрите внимательно знаменитую заставку Megaman 2:
Окна и выступы — это спрайты, а само здание представляет из себя фон из просто вертикальных линий, движение которых отследить невозможно:
На самом деле здание движется с той же скоростью, что и город на фоне, но это незаметно. При этом за счёт движения окон складывается впечатление, что здание движется всё-таки гораздо быстрее, а это соответственно создаёт ощущение того, что оно ближе.
Кстати, некоторые спросят, почему у самого Мегамена так много цветов? Да просто на самом деле он состоит из нескольких спрайтов: лица и тела, которые накладываются друг на друга:
А теперь подумайте — как же делались большие подвижные боссы, учитывая все ограничения на количество спрайтов? Ответ прост: такие боссы обычно на самом деле являются фоном. Именно поэтому при битве с ними фон зачастую либо чёрный, либо просто одноцветный. Вот пример из тех же Chip and Dale 2:
В первом случае такой фон двигается вертикально, во втором горизонтально. Думаю, что вы и сами вспомните очень много боссов на чёрном фоне.
В некоторых играх вроде Jurassic Park делают ещё хитрее:
Босс — это всё-таки фон, а вот кустики и камни на фоне — это спрайты. То есть всё шиворот навыворот! И да, спрайт может быть позади фона. Именно поэтому когда персонаж проходит через кусты, они иногда просвечивают сквозь него.
Кстати, у этой же игры в заставке надпись «Ocean» большая, движется в разные стороны с разной скоростью, а потом и вовсе отображается волнами:
Тут всё совсем хитро. Игра отслеживает момент, когда на экране телевизора дорисовывается сканлайн (горизонтальная линия), после чего сдвигает фон по горизонтали. Таким образом можно получить эффект вроде горизонтальных волн.
Продолжать можно очень долго. Любая достаточно серьёзная игра напичкана самыми разными такими «фокусами», которые выжимали из NES гораздо больше, чем было задумано изначально. Надо сказать, что многие из этих ограничений можно было снять, установив в картридж с игрой дополнительные чипы. И это весьма активно делали, в итоге картриджи могли весьма сильно отличаться с аппаратной точки зрения, но тогда нужно было не забывать и об итоговой цене производства, поэтому разработчики не очень сильно себя баловали.
Не стоит забывать и про ограниченные звуковые возможности, но это не так наглядно. Скажу лишь то, что для создания приятной музыки при помощи такого железа действительно нужно было обладать музыкальным талантом. Game Boy был уже немного более продвинутым в этом плане и в результате породил целый музыкальный жанр и свою культуру.
Надеюсь, что теперь и вы будете смотреть на игры иначе, задумываясь о том, как же разработчикам пришлось поломать себе голову.
Денди сколько цветов
Схемотехника Денди по большей степени классична для любой ЭВМ: содержит микросхему процессора, видеопроцессора, оперативной памяти и прочей сопрягающей "рассыпухи". В 80-х годах прошлого столетия консоли Famicom и их «клоны» изготавливались именно в «многокорпусном варианте». Один из типовых вариантов принципиальной схемы приведен ниже (при клике на картинку открывается полномасштабный вариант - чуть более 100кб.)
Несмотря на то, что документ явно «китайского» происхождения, на нем «один-в-один» изображена схема японского Famicom редакции HVC - CPU -07 (проверено). По-сему схему можно использовать не только в целях ремонта и т.п. но и сконструировать по ней систему «с нуля».
Массовую популярность на российском рынке Денди приобрела в большей степени (чем китайцам) благодаря компании "Стиплер", - которая, по всей видимости, имела "пиратские" корни. Лично я очень сильно сомневаюсь в том, что Стиплер делала лицензионные отчисления в пользу Nintendo. Потому что как тогда, для примера, объяснить само возникновение брэнда "Денди"? - а имя оригинального разработчика, кстати, всеми усилиями скрывалось. Или, например то, что в один прекрасный момент эта фирма (казалось бы так раскрученная) внезапно исчезла? (Можете попробовать поискать на гугле . ) Ну да разговор не об том. Внезависимости, занималась ли реально Стиплер работой над схемотехнической архитектурой консолей, либо же просто заказывала OEM-партии клона Famicom под своим логотипом - продукция была действительно высокого качества, не в сравнение морю явных "китайских" подделок (скупаемых "там" за копейки и мешками завозимыми к нам). Наиболее известными "ремэйками" консоли NES в исполнении Стиплер были модели "Dendy Junior" и "Dendy Classic" отличались они лишь дизайном (ну и некоторыми малосущественными нюансами), хотя "классик" стоила несколько дороже. Кстати именно дизайн Dendy Junior являлся точной копией японского Famicom , а дизайн Dendy Classic повторял дизайн «китайских» клонов (или наоборот?).
В месте с тем, за весь период своего производства "начинка" консолей (как стиплеровских так и «китайских») претерпела определенные изменения (не заметные для рядового пользователя, не отразившиеся на внешнем виде изделия и базовых функциях). Интеграция и миниатюризация в электронном мире идет огромными шагами. Первые редакции консоли были «многокорпусными» (см. схему выше) – это и все японские Famicom `ы, и первые Dendy от Стиплера, и даже китайщина концов 80-х начала 90-х годов прошлого века. Но уже к середине 90-х годов купить новую «многокорпусную» Денди было почти не реально. Первая Денди (" J unior") которую я увидел изнутри (не моя – отдали на ремонт) уже была собрана в соответствии с концепцией System-on-a-Chip (система на одном кристалле) - лишь микросхемы памяти были "внешними" - сейчас есть в моей коллекции подобная система, но в исполнении " Classic " (система PAL - на чипе 1818).
Пару слов (и картинок) о моей первой дендюшке (" J unior II "), той самой - купленной в 1995 году. Это последняя вариация консоли в исполнении " J unior" (внешний вид как у Famicom , см. картинку в уголке) - абсолютно все компоненты системы находятся в едином чипе (включая память). Фотографии обоих сторон платы приведены ниже (плата однослойная, с лицевой стороны есть лишь отдельные проволочные перемычки).
Ну а далее . конечно же, я срисовал схему устройства (что не сложно, но весьма кропотливо) - результат перед вами ниже (при клике на картинку открывается полномасштабный вариант - около 400кб.)
Устройство предельно простО. Микро-ЭВМ с необходимой аналоговой обвязкой плюс разъемы - ничего лишнего. Когда зарисовывал схему, складывалось впечатление, что распиновка чипа специально создавалась под конкретную топологию печатной платы, с целью минимизации всех возможных переходов и соединений. Что лишний раз наталкивает на мысль - микросхема UM6561 - есть изделие заказное (а не универсальное, массового производства). В эту пользу говорит и факт отсутствия какой-либо технической документации на данную микросхему, как у самого разработчика - UMC (кстати, достаточно крупного), так и во всевозможных информационных базах. Интересен еще и другой вопрос - "под чей заказ" делалась эта Микро-ЭВМ. Уж не сами ли Стиплер ее заказывали? ;-) С другой стороны - маловероятным кажется и то, что такой крупный мировой производитель электронной базы как UMC приняли заказ на изготовление "чипа" - клона консоли NES (разумеется, при полном отсутствие у заказчика каких любо прав на эту консоль). Тогда под какое применение (официально) был этот чип заказан? - и сколько у него "недокументированных" возможностей? Ладно, оставим мистику в стороне ;-) Хотя о какой "документированности" можно говорить при полном отсутствие какой бы то ни было документации . Все что можно однозначно сказать о Микро-ЭВМ UM6561 - так это то, что в приведенном на схеме включении она полностью (нареканий вроде пока нет) эмулирует работу игровой консоли NES.
Уже в те годы китайцы жмотились на текстолит (хотя и использовали более качественный, нежели в Денди), а также имели неуемную тягу к бескорпусным микросхемам («кляксам»). Почти любая китайская консоль заката эпохи Денди – вторая половина 90-х годов века двадцатого, была сконструирована в виде однокристаллки подобной приведенной выше Dendy Junior II, но в бескорпусном варианте.
На картинке выше фотка центральной платы одной из китайских консолей, внезапно приказавшей долго жить (в далеком 1995-ом) и после почти 20-летнего ожидания в закромах – восстановленной и в настоящий момент вполне себе работоспособной ;-) Трабл был в отказавшем кварце, под замену которого был специально приобретен десяток идентичных ;-) Для удобства тестирования впаяны штыревые гребенки, поменяны резисторы, установлен транзистор …
Расскажу еще о более интересном - о многокорпусных консолях. В 2014 году вновь вспомнилась уже порядком подзабытая тематика о Денди и были куплены у япошек несколько б/у Фамикомов (обзорные материалы о данных консолях размещены отдельно). Здесь же коснемся архитектурной части. Логично, что Фамиком – т.е. NES , рассчитанная на японского потребителя, формирует сигнал в формате NTSC , а радиочастотный модулятор настроен на тамошюю частотную сетку (90 или 96 MHz ). Формат формируемого видео-сигнала определяется вариантом (экземпляром) видеопроцессора ( PPU ). Т.к. схемотехнически различные варианты микросхем PPU идентичны, есть возможность заменить PPU (в случае «многокорпусной» консоли) и тем самым изменить стандарт формируемого видео-сигнала. Так например можно за PAL ить Фамиком … Вместе с процессором нужно будет поменять и «кварц», а в ряде случаев и сам процессор ( CPU ). Варианты «наборов», позволяющих реализовать получение выходного сигнала того или иного формата представим в виде таблицы.
Цвета и палитры NES
Фоновые Палитры
Честно говоря, идея этого документа родилась, когда я вдруг в своих РОМсетах обнаружил перевод Шедевра игры Bucky O’Hare . Про перевод ничего говорить не буду - у меня другая цель. Моё внимание привлёк титульный экран:
Сначала когда я увидел российский триколор, я сразу подумал, что уже в те далёкие времена ромхакеры могли не пожалеть времени и изменить палитру ради патриотических чувств. =) Однако сравнив палитры в оригинале и изменённом РОМе можно легко убедиться, что в этом случае переводчику просто необычайно повезло: сама палитра удивительным образом совпадает с цветами российского флага (просто в оригинале синий цвет в надписи ‘Palcom’ не используется). На этом предисловие заканчивается и начинаются суровые будни. Не так давно для нахождения палитр вам можно было смело посоветовать искать их с помощью Nesticle(которая, лично у меня, не пустилась даже под DosBox’ом), а потом искать последовательность байт с помощью хексредактора. В документе ‘Palette Modifications of an NES file using a Hex Editor’ by aStROcReEp вообще советуют обозначить каждый цвет буковкой, составить таблицу и искать сочетания этих буковок. Эти методы подходят начинающим, однако требуют диких затрат времени и могут не сработать(скажем, когда индексы цветов загружаются из операндов команд). Сейчас ситуация в корне изменилась - появился FCEUxd(FCEUxdsp). Гарантировано идёт под 32-разрядными Windows и имеет удобный хексредактор. Итак, быстрый способ нахождения палитр. Открываем в нашем замечательном отладчике указанный выше РОМ. Ставим останов на запись данных в палитру картинки по адресу $3F00 в PPU непосредственно перед загрузкой нашего титульника и дожидаемся его загрузки. Останов сработал:
В аккумуляторе $0F- чёрный цвет холста. Скорее всего, перед нами подпрограмма, которая выводит Y значений в память PPU, а значения берутся из ячеек, начиная с $0123. Отследим запись в эту ячейку. Поставим останов на запись опять же перед загрузкой титульного экрана. Останов срабатывает дважды в одном и том же месте. С точки зрения рассмотрения алгоритма нам всё равно, какой раз брать.
Подпрограмма вывода всей палитры во всей своей простоте и изяществе! $000B - общий счётчик введённых индексов цветов; $000A - частный счётчик цветов в каждой части палитры (мы же ведь не забыли, что палитра условно разбивается на четыре части?) В ячейках $08 и $09 содержатся указатели на палитру, которые в случае чего можно/нужно будет поменять. $96AB - адрес в RAM, содержащий второй индекс цвета в первой части палитры. Второй, потому что первый загружается из операнда команды по адресу $C551.
Сразу видно преимущество этого метода: в РОМе хранятся только 2,3 и 4-й цвета, а первый всегда $0F. Следовательно, если бы мы воспользовались советами тех документов, что были написаны для начинающих The Palette Hacking Doc by Toma; Palette Modifications of an NES file using a Hex Editor; The newbie NES Pallete hacking Tutorial. by Dark X; NES Palette hacking: The Fast Way (using FCEUd), мы должны были найти во вкладке ‘Tools -> PPU Viewer…’ нашу загруженную палитру, потыкать в каждый цвет мышкой и записать на листочке байты: $0F $27 $16 $20 $0F $27 $14 $03… и попытаться найти их в РОМе. Понятно, что в нашем РОМе первого, пятого,девятого и тринадцатого $0F быть не может. С точки зрения начинающего - палитра ненаходима и/или зажата страшным алгоритмом!
Теперь воспользуемся преимуществами хексредактора FCEuXD: откроем редактор и найдём адрес $96AB, правой кнопкой мыши -> Go Here In Rom File, и вот он наш адрес: $116BB. Для проверки поменяем палитру. Впишем по адресу $116с1 (судя по PPU Viewer’у надпись использует именно третью палитру) значения других цветов. Например, сочетание $28 $05 $00 даст нам цвета германского флага:
Faterland uber alles! =)
В принципе, можно поменять и фон холста (подредактировав команду по адресу $C551), например:
Однако, практической выгоды это не несёт, так как всё, что было прозрачным теперь стало этого цвета. Даже космос стал… голубоватым.
Возникает вопрос: как можно использовать в наших корыстных целях таблицу атрибутов? Один из вариантов - присвоить участку экрана другую часть палитры (скажем, если нам не желательно изменять старую палитру), или даже присвоить участку ранее не встречавшиеся цвета.
Для примера предположим, что нам нужно, чтобы в надписи bucky o’hare слово bucky было зелёного цвета (как и сам главный герой). Однако в исходных частях палитры зелёного цвета нет! Зрячие также могут увидеть, что в четвёртую палитру загружены только цвета холста, т.е. она пустая. Вот и выход: вписать вместо $0F нужные нам цвета, а затем переназначить ту часть таблицы, что отвечает за наше слово со второй части палитры на четвёртую.
Как вписать нужные цвета (среди которых должен быть один зелёный) в палитру - смотри выше. А вот таблица атрибутов может быть найдена следующим образом (для наглядности я возьму довольно долгий способ). Доходим до титульника, открываем Hex Editor, выбираем PPU Memory, находим адрес первой таблицы атрибутов ($23c0) и начинаем запарывать байты поочерёдно (скажем, вписывать в ячейки байт FF, так как он не встречается в нашей таблице). В результате в самом эмуляторе мы увидим, что определённые квадраты начинают окрашиваться необычно. Таким образом, можно вычислить адреса, отвечающие за наше слово (в нашем случае это $23d0-$23D7). Соответственно, ставим останов на запись в эту область PPU и дожидаемся загрузки титульного экрана.
Очевидно, здесь байт рома записывается в PPU столько раз, сколько будет в Y. Если так можно сказать, метод, похожий на RLE сжатие. Находим место, откуда берётся значение аккумулятора: Нажимаем несколько раз Step Into, пока Y не станет равным нулю, после операций над ячейками $00 и $01 (там хранятся указатели) программа загружает следующее значение в нашу таблицу атрибутов:
Y берётся из ячейки $81A4, соответствующей $101b4, а значит вначале значения загружались из $101b2 (мы же не забыли, что продвинулись по программе вперёд?). Даже визуально можно определить, что сначала идёт байт-счётчик ($0E), затем атрибут ($55), который будет записываться $0E раз. Заметьте, что атрибут соответствует 01010101b, а значит, будет указывать на вторую палитру. Далее идёт атрибут $11, который вписывается один раз - он соответствует буковкам ‘TM’ после нашей надписи - они белые.
Перед нами стоит задача: разбить нашу надпись на две части (как видите, вся надпись обладает одним атрибутом, который загружается одним байтом) и переназначить атрибут на четвертую часть палитры. Если быть кратким, то это делается заменой байт по адресу $101b2 на $08 $FF $08 $55. Обратите внимание, что тогда буквы ТМ станут принадлежать второй части палитры (как и слово ‘O’Hare’) и станут фиолетовыми, но, думаю, чем-то нужно будет обязательно пожертвовать. Зато теперь мы добились нужного эффекта - верхнее слово можно будет раскрасить в нужный нам цвет.
Вот, например, что можно сделать с титульником, если подредактировать таблицу атрибутов как было указано выше, заменить пустую палитру своей, и чуть-чуть подменить цвета в графическом редакторе:
Вроде симпатично получилось =)
Спрайтовые Палитры
В сущности, спрайтовые палитры мало чем отличаются от палитры картинок. Непосредственно палитра, как уже было сказано, хранится по адресам $3F10 - $3F1F и правила её нахождения и изменения абсолютно такие же, как и для палитры картинок. Чуть по-другому организовано понятие атрибутов спрайтов.
Внутри PPU есть отдельно адресуемая (от основного адресного пространства PPU - 16k) память спрайтов, размером 256 байт. Эта память хранит “записи” о 64 спрайтах, размер каждой записи 4 байта. Первый байт - координата по вертикали второй - индекс спрайта, третий - искомый нами атрибут, четвёртый - координата по горизонтали. Так как атрибут присвоит каждому спрайту в отдельности, то появляется возможность выделять под номер части палитры не весь байт, а только младшие два бита. Остальные биты отданы под другие атрибуты: например, отражение и приоритет спрайта. Фактически, поиск атрибута спрайта будет сводиться к нахождению спрайтового буфера и нахождению нужного нам спрайта, а следующий за индексом спрайта байт будет являться искомым байтом атрибута.
Итак, предположим, что нам нужно поменять цвет головы главного героя: у обычных зайцев он, вроде, серый =) Находим часть палитры, которой присвоен наш спрайт. Это вполне можно сделать и визуально (уж точно быстрее), однако в обучающих целях попробуем найти эту часть через атрибут спрайта. Находим спрайтовый буфер (эта операция описана в доке CaH4e3’a) - здесь он расположен по адресу $200. Находим индекс нашего спрайта (хотя в памяти PPU несколько голов - нужная нам голова имеет индекс $03) по адресу $0215. Соответственно, атрибут будет $02 = 00000010b, это означает, что тайлу головы присвоена третья часть палитры, так как младшие два бита составляют двойку в десятичной системе. И теперь попробуем поменять эту часть палитры. Поиск всей палитры производится так же, как и для картинок. Правда, в нашем случае палитры спрайтов хранятся несколько иначе, чем палитры картинок, но принципиально поиск ничем не отличается от описанного выше. Последние 8 цветов палитры хранятся по адресам РОМа $11c3d - $11c44. Наш зелёный ($29) цвет по адресу $11c40 заменяем на нормальный серый ($2D)цвет:
При необходимости можно переназначить голову на другие части палитры, однако не стоит забывать, что голова состоит не из одного тайла, т.е. переназначать на другие части придётся и другие тайлы, составляющие голову (уши и прочее).
Игры для NES/Famicom/Денди глазами программиста
Это пост про ограничения старых видеоигр. Сам я под NES никогда не программировал, но с архитектурой поверхностно познакомился. Теперь я не могу играть в игры для NES, не задумываясь, как же они устроены. Иногда это на столько вызывает восхищение, что невольно забываешь про саму игру. «Чему же там восхищаться?», — скажете вы. Да просто укладываться во все ограничения NES, но при этом делать игру красивой, — это действительно целое искусство.
Сейчас я постараюсь рассказать об этом вам, максимально всё упростив.
На NES всё отображаемое на экране делится на спрайты и фон. Спрайты — это объекты, которые двигаются по экрану. Как правило, это непосредственно ваш герой и враги. Иногда это ещё какие-то предметы, но тут всё уже сильно зависит от игры. Фон — это собственно то, что находится позади. И у спрайтов, и у фона есть уйма ограничений.
Фон на NES делится на квадраты размером 8 на 8 пикселей, которые называются тайлами. Итого таких квадратов 30 в высоту и 32 в ширину. При этом фон может плавно двигаться горизонтально и/или вертикально.
Во многих играх, особенно старых, можно заметить, что игра состоит из таких повторяющихся квадратов. Вспомните Super Mario Bros., Bomberman или Battle City. Дело в том, что в память NES можно загрузить одновременно весьма ограниченное количество таких рисунков, поэтому приходилось использовать одни и те же повторно.
Помимо этого существенные ограничения накладывались на цвета. Всего NES может отображать около 53-55 цветов, учитывая повторяющиеся и похожие. По тем временам это было не так уж мало, но всё не так просто. Используются такие штуки, как палитры:
- Палитра — это набор из четырёх цветов, т.е. какие-то четыре цвета из этих 53-55 цветов
- Таких палитр для фона может быть только четыре, при этом один цвет в каждой из них должен быть одинаковым
- Каждая группа из четырёх тайлов (2x2) отображаемых на экране может быть ассоциирована с одной из этих палитр
Это может быть не так просто понять с первого раза. Попробую объяснить на пальцах. Взгляните ещё раз на картинку выше. Каждый квадратик раскрашен не более, чем в четыре цвета. При этом они делятся на три типа: чёрно-бело-голубые, черно-зелёно-голубые, чёрно-коричневые. Возможно, что используется и четвёртый, но я не заметил.
Цвет помеченный звёздочкой постоянно меняется, так монетки и вопросики мерцают. Да, монетки — это часть фона. И именно поэтому облака и кусты — это один и тот же рисунок: тайл один, палитра выбрана разная. Сэкономили немного памяти, но ведь совсем незаметно с первого взгляда.
Как я уже говорил, фон может двигаться. Для этого обычно используется мирроринг, но в эти подробности я вдаваться не буду. При этом есть возможность разделить экран на две части и двигать их отдельно друг от друга, именно так обычно делается неподвижная строка с информацией о жизнях, здоровье, очках и прочем.
Спрайты
Если вы разобрались с ограничениями фона, со спрайтами всё будет легко. Суть в том, что это движущиеся на экране объекты размером 8x8 или 8x16 пикселей. Причём они все одновременно должны быть либо 8x8, либо 8x16, что накладывает несколько других ограничений. В лучшем случае (зависит от размера) всего их может быть аж 64, но на одной строке может отображаться не более восьми, даже если соответствующая область спрайта прозрачная, поэтому слишком много подвижных объектов не сделаешь. Правда, некоторые игры всё-таки делают, заставляя один из спрайтов исчезать на долю секунды, что приводит к неприятному мерцанию. Наверняка многие замечали такое. На цвета наложены примерно те же самые ограничения, что и для фона, но для спрайтов даются отдельные четыре палитры, один из цветов при этом считается за прозрачность. То есть получаем всего три цвета + фон…
Луиджи же — это просто Марио с другой палитрой. Обратите внимание — у Марио рукава, глаза, волосы и усы одного цвета. Именно поэтому у Луиджи глаза, волосы и усы стали зелёными.
Как же так получается?
А теперь взгляните на игры для NES, учитывая описанные выше ограничения. Как же так получается, что фон может быть только из 13 цветов, но многие игры запомнились очень красочными? Как же при таких маленьких спрайтах мы сражались с огромными боссами? Игры начинают выглядеть совсем иначе.
Например, Chip and Dale 2:
Всё весьма красочно и разноцветно, при этом разработчики вписываются во все ограничения.
Как только мы доходим до второй половины уровня, появляются новые цвета:
Просто в момент, когда мы переходим в другую локацию, и экран темнеет, в память загружается уже новые палитра и тайлы. Так создаётся впечатление, что игра гораздо более красочная, чем она есть на самом деле: эти самые 13 цветов достаточно часто меняются от уровня к уровню.
Выше я описал, что фон может делиться на две части, которые движутся отдельно. Именно так сделана начальная заставка, где летит дирижабль Толстопуза:
Колючая проволока внизу движется с одной скоростью, фон с другой, сам дирижабль — это спрайт, который движется с третьей скоростью. Так создаётся иллюзия объёма.
Бывают и совсем другие приёмы. Посмотрите внимательно знаменитую заставку Megaman 2:
Окна и выступы — это спрайты, а само здание представляет из себя фон из просто вертикальных линий, движение которых отследить невозможно:
На самом деле здание движется с той же скоростью, что и город на фоне, но это незаметно. При этом за счёт движения окон складывается впечатление, что здание движется всё-таки гораздо быстрее, а это соответственно создаёт ощущение того, что оно ближе.
Кстати, некоторые спросят, почему у самого Мегамена так много цветов? Да просто на самом деле он состоит из нескольких спрайтов: лица и тела, которые накладываются друг на друга:
А теперь подумайте — как же делались большие подвижные боссы, учитывая все ограничения на количество спрайтов? Ответ прост: такие боссы обычно на самом деле являются фоном. Именно поэтому при битве с ними фон зачастую либо чёрный, либо просто одноцветный. Вот пример из тех же Chip and Dale 2:
В первом случае такой фон двигается вертикально, во втором горизонтально. Думаю, что вы и сами вспомните очень много боссов на чёрном фоне.
В некоторых играх вроде Jurassic Park делают ещё хитрее:
Босс — это всё-таки фон, а вот кустики и камни на фоне — это спрайты. То есть всё шиворот навыворот! И да, спрайт может быть позади фона. Именно поэтому когда персонаж проходит через кусты, они иногда просвечивают сквозь него.
Кстати, у этой же игры в заставке надпись «Ocean» большая, движется в разные стороны с разной скоростью, а потом и вовсе отображается волнами:
Тут всё совсем хитро. Игра отслеживает момент, когда на экране телевизора дорисовывается сканлайн (горизонтальная линия), после чего сдвигает фон по горизонтали. Таким образом можно получить эффект вроде горизонтальных волн.
Продолжать можно очень долго. Любая достаточно серьёзная игра напичкана самыми разными такими «фокусами», которые выжимали из NES гораздо больше, чем было задумано изначально. Надо сказать, что многие из этих ограничений можно было снять, установив в картридж с игрой дополнительные чипы. И это весьма активно делали, в итоге картриджи могли весьма сильно отличаться с аппаратной точки зрения, но тогда нужно было не забывать и об итоговой цене производства, поэтому разработчики не очень сильно себя баловали.
Не стоит забывать и про ограниченные звуковые возможности, но это не так наглядно. Скажу лишь то, что для создания приятной музыки при помощи такого железа действительно нужно было обладать музыкальным талантом. Game Boy был уже немного более продвинутым в этом плане и в результате породил целый музыкальный жанр и свою культуру.
Надеюсь, что теперь и вы будете смотреть на игры иначе, задумываясь о том, как же разработчикам пришлось поломать себе голову.
Читайте также: