Как делались игры на денди
Это пост про ограничения старых видеоигр. Сам я под 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 был уже немного более продвинутым в этом плане и в результате породил целый музыкальный жанр и свою культуру.
Надеюсь, что теперь и вы будете смотреть на игры иначе, задумываясь о том, как же разработчикам пришлось поломать себе голову.
Добавляем в игру сложный режим
Когда игрок прошёл все уровни, ему можно дать возможность поиграть на повышенной сложности: он уже знает всю игру и может пройти более сложные ловушки и боссов. Например, сложный режим может отличаться дизайном уровней и поведением противников.
Чтобы и этот режим поместился в оставшуюся память, снова используют трюки с памятью и графикой.
Чтобы игрок понял, что начались трудности, просто меняют палитру. Это почти столько же по памяти, но выглядит сложнее. Уровень можно поменять так: берут исходную картинку, накладывают сверху новые детали и получают сложную локацию. В среднем на это уходит по 7 байт на каждый экран.
Карта
Для карт у нас столько же памяти, сколько и на спрайты (то есть мало), поэтому разработчики будут действовать так же:
- разбивать фон на отдельные ячейки;
- смотреть, как можно оптимизировать эти ячейки для хранения в памяти;
- смотреть, можно ли что-то использовать повторно, для экономии памяти.
Главная задача на этом этапе — максимальная экономия видеопамяти. Для этого каждый экран с уровнем игры разбивается не на метаплитки 2 x 2, как в примере выше, с персонажем, а на метаметаплитки или суперплитки — 4 x 4 ячейки. Вот для чего это нужно:
Если разбить просто на квадратики 8 x 8, как в памяти, то вся видимая на экране часть уровня займёт 960 байт. Это почти килобайт, и это очень много. Разбивают уровень на метаплитки 16 x 16. Теперь на одну карту нужно 240 байт, чтобы пометить каждую такую метаплитку, но это всё равно много. Уменьшаем дальше. Теперь уровень делится на супербольшие плитки по 16 ячеек в каждой. В итоге для того, чтобы пронумеровать каждую такую суперплитку, нужно всего 60 байт. Уже можно работать. Вот так собираются метаплитки — из четырёх ячеек в памяти. Теперь можно собирать такие метаплитки в виртуальные наборы и каждой присвоить какой-то код. Но и это ещё не всё. Вот теперь получилась суперплитка. Это готовый блок для уровня, и чтобы собрать такое, нужно совсем немного памяти. Коллекция виртуальных суперплиток. С ними можно сделать любые уровни и фоны.
Рисуем карты (и оптимизируем их)
Даже 60 байт на экран, которые у нас получились, — это всё равно очень много, ведь нужно сделать много разных карт, написать логику поведения персонажей и сделать меню, заставки и титры. Каждый байт на счету.
Первый вариант — уменьшить количество памяти для отрисовки карты: сделать их симметричными, что даст нам 30 байт вместо 60. Мы рисуем одну половинку карты, а потом просто отзеркаливаем её. Сравним с картой, которую мы бы хотели получить:
Вроде всё на месте, а выглядит плохо — сразу видна симметрия и доступ наверх закрыт блоками.
И вот тут разработчики делают очередной хитрый ход, который даст им немного дополнительной памяти для графики. Смотрите:
- Они дают для хранения одной суперплитки один байт.
- Считают по картинке, сколько получилось суперплиток в прошлом разделе — 96.
- Так как программисты начинают считать с нуля, то самое большое число, которое получится, — 95, а это 1011111 в двоичной системе счисления.
- В этом длинном числе всего 7 цифр, а в байте их 8, поэтому остаётся один лишний бит из каждого числа.
- 4 суперплитки дадут 4 бита.
- Эти 4 бита можно использовать, чтобы сдвинуть по кругу ряд с зеркальным отражением и получить как бы новый ряд, уже без видимой симметрии.
Если вы не знаете, что такое двоичная система счисления, — почитайте нашу статью об этом, а потом вернитесь сюда.
4 суперплитки дают 4 бита. Посмотрим, что можно с ними сделать. Сначала делают симметричный уровень… А затем сдвигают верхнюю полосу вправо по кругу. 1100 — это 12 в десятичной системе счисления, именно столько сдвигов вправо нужно сделать, чтобы получилось как на картинке. То же самое делают с третьей строкой и получают уже приемлемое начало уровня.
Действуя таким образом, разработчики могут менять уровни до неузнаваемости, не затрачивая при этом вообще лишней памяти. Помним, что наш экран — это ещё не весь уровень, сверху нужно нарисовать ещё много раз по столько же.
Вторая половинка)
Ответ на пост «Нам такая невеста не подходит или, может, мы чего не понимаем?»
Знакомая сына одна ростила. А когда он, лет а 20 девочку привел, сделала все что бы её отвадить. Хороший мальчик, не стал через мамин труп жениться. С девочкой расстался.
Теперь мальчику под сорокет. Живет с мамой. Мама плачет что мальчик не женат, внуков не видать, сидит как сыч - играет все свободное время. Оказалось другие девочки его не интересуют.
Так и живут.
Персонажи
В игре есть два вида графики: статичный фон и движущиеся предметы — игроки, противники, боссы и выстрелы. Всё, что движется, называется спрайтами. Разработчики делят всю графическую память на две части — одну под спрайты, вторую под фон:
Каждая клеточка — это мини-квадратик 8 на 8 пикселей. В каждом таком квадратике можно что-то нарисовать, но использовать при этом только три цвета. Если объединить несколько квадратиков в один, получится метаспрайт. В нашем случае — персонаж. Приставка может использовать одновременно только 4 вида палитры, поэтому у нас получается 4 цветных главных героя и нераскрашенный злодей. Новое ограничение: на экране одновременно может быть только 8 спрайтов — на большее не хватает памяти. Поэтому для злодея места не остаётся. Можно пойти на хитрость и показывать их быстро-быстро по очереди, но тогда картинка будет мерцать и выглядеть хуже. Разработчики радикально уменьшили размеры героев и злодея до одного спрайта. Теперь они выглядят более условно, зато помещаются на экран. Меньше размер героя — больше свободного места для дизайна злодеев, боссов и спецэффектов. Сейчас в табличке собраны все варианты того, как может выглядеть персонаж в игре — и в прыжках, и на бегу.
Разработка игр под NES на C. Главы 1-3. От введения до Hello World
Впервые я задумался о том, как разрабатывают игры под приставки где-то через 20 минут после того, как в самый первый раз увидел Turbo Pascal. На глаза иногда попадался Subor с клавиатурой, и появилась мысль: "Наверное можно набрать какую-то программу, а потом в нее поиграть". Но интерес быстро затух, потому что абсолютно никакой информации по этой теме тогда не было доступно. Следующий раз эта же идея всплыла, когда увидел вполне играбельные эмуляторы старых консолей. Тогда стало ясно, что вбивать листинг в саму консоль и необязательно. Где-то очень потом появился Хабр с благожелательной аудиторией для таких вещей. В какой-то момент даже начал собирать разрозненную инфу чтобы написать мануал самому, и вот сегодня наткнулся на готовый учебник, который явно надо перевести.
Разработка под старые консоли документирована вдоль и поперек, но именно по NES 99% информации относятся к разработке на Ассемблере. Меня почему-то зарубило, что надо освоить именно работу с С.
следующая >>>
Всем привет.
Меня зовут Дуг. Я пишу игры для NES вот уже год, и решил начать этот блог. Я намерен написать туториал по разработке игр под NES, чтобы вдохновить других людей делать собственные игры.
Особенностью блога будет использование чистого С, так что другие программисты смогут начать писать быстро и не особо вникая в ассемблер для процессора 6502. Насколько мне известно, других туториалов такого формата по компилятору cc65 пока нет, кроме нескольких примеров игр на сайте Shiru.
Также помните, что я не профессионал ни в разработке, ни в ведении блога. Если возникнут вопросы по NES, скорее всего ответы найдутся в Вики.
Я постараюсь максимально упростить обучение, и использовать самые простые примеры. Также рекомендую начать с простейшей идеи игры. Читателю явно захочется сделать новую Зелду, но это не получится. Простейшая игра потребует 2-3 месяца на разработку, Зелда — 2-3 года. Такой проект скорее всего будет заброшен. Ориентируйтесь на Пакман, хотя бы первое время.
Память консоли
Поговорим о структуре памяти. У NES два независимых адресных пространства — память процессора с диапазоном $0-$FFFF и память PPU — видеочипа.
Начнем с памяти процессора.
- Первые $800 это RAM.
- Диапазон $6000-$7FFF некоторые игры используют для работы с SRAM (сохранение на картрирдж с батарейкой), или как дополнительный Work RAM.
- На пространство $8000-$FFFF отображается ROM. Некоторые мапперы (дополнительный процессор в картридже) могут использовать более 32k ROM, но они все равно обычно работают через $8000-$FFFF.
- Адрес $FFFC-$FFFD это вектор reset, который указывает на начало программы.
Здесь более подробная информация.
У PPU свое, независимое адресное пространство. Оно имеет размер $3FFF, но местами зеркалируется. Доступ к нему идет через регистры в памяти процессора. Видеопамяти хватает на 4 экранных буфера, но в подавляющем большинстве игр используется только 2 — для реализации прокрутки.
- $0-$1FFF = здесь хранятся спрайты
- $2000-$23FF = Таблица имен 0
- $2400-$27FF = Таблица имен 1
- $2800-$2BFF = Таблица имен 2
- $2C00-$2FFF = Таблица имен 3
При этом таблицы 2 и 3 это зеркало таблиц 0 и 1 - $3F00-$3F1F = палитра
Таблица имен, nametable, связывает тайлы фона и их позицию на экране.
Зеркалирование позволяет управлять горизонтальной или вертикальной прокруткой, но всему свое время.
Еще в PPU есть отдельная область памяти OAM, Object Attribute Memory, размером 256 байт. Доступ к ней реализован через регистры в адресном пространстве процессора, и она позволяет управлять отображением спрайтов.
Еще один момент. Есть два типа картриджей. В некоторых два ROM чипа — PRG-ROM с исполняемым кодом и CHR-ROM с графикой. В таком случае графика автоматически отображается в адреса $0-1FFF PPU. Это позволяет очень просто сделать отрисовку — просто записать номер тайла в таблицу. Мы будем использовать этот формат.
Другой тип картриджа использует CHR-RAM вместо CHR-ROM. Это позволяет подгрузить часть графики в эту дополнительную оперативную память. Это сложная техника, и в этом туториале не рассматривается.
Теперь можно посмотреть на софт, используемый для разработки.
- Компилятор
- Редактор тайлов
- Графический редактор
- Notepad++
- Хороший эмулятор
- Упаковщик тайлов
В этом туториале рассматривается только cc65. Это один из лучших компиляторов для 6502, процессора NES.
Я использую версию 2.15 (для проверки введите ‘cc65 --version’ в консоли). Файлы из разных версий несовместимы, поэтому при необходимости используйте nes.lib из комплекта вашего компилятора.
Во-вторых, надо создать графику. Я использую YY-CHR
Для предобработки графики нужен любой графический редактор: Photoshop или GIMP, по вкусу.
Код удобно писать в Notepad++. У него есть подсветка сишного синтаксиса и нумерация строк — это облегчает отладку.
А теперь эмулятор. Я использую FCEUX 90% времени, потому что в нем есть крутой дебаггер и инструменты для работы с памятью, просмотрщики спрайтов и все такое. Но он не самый точный в эмуляции. Игры надо будет тестировать где-то еще. Судя по отзывам, самые точные эмуляторы это Nintendulator, Nestopia, и puNES. Еще желательно подгрузить более точную палитру — лежит здесь.
Есть две версии FCEUX — SDL и Win32. Первая работает почти везде, вторая только в Windows. Так вот, отладчик есть только во второй. Так что в случае альтернативной ОС придется воспользоваться виртуалкой или Wine.
И наконец расстановщик тайлов. Мы можем сделать игру без него, но он точно поможет. Я рекомендую NES Screen Tool. Он отлично показывает ограничения консоли по цветам и отлично подходит для одноэкранных игр. Для игр с прокруткой лучше подойдет Tiled map editor.
Как же всем этим пользоваться?
В YY-CHR надо проверить, чтобы цвет был двухбитный.
Палитра сейчас не имеет значения, потому что она все равно задается в другом месте.
Как работает сс65
Все компиляторы для NES работают через консоль, без графического интерфейса. То есть пишем программу в Блокноте, а потом вызываем компилятор с нужными параметрами.
Дл упрощения работы будем использовать .bat-скрипты и Makefile. Это позволит автоматизировать процесс и собирать образ картриджа в одно касание.
Процесс примерно такой. cc65 компилирует файл с кодом на С в ассемблерный код. ca65 собирает объектный файл. ld65 линкует его в образ картриджа .nes, который можно запустить в эмуляторе. Настройки хранятся в .cfg файле.
- Большая часть переменных должна быть типа unsigned char — 8 бит, значения 0-255
- Лучше не передавать значения в функции, или делать это через директиву fastcall, которая передает аргументы через 3 регистра — A,X,Y
- Массивы не должны быть длинее 256 байт
- printf отсутствует
- ++g заметно быстрее, чем g++
- cc65 не может ни передавать структуры по значению, ни возвращать их из функции
- Глобальные переменные намного быстрее локальных, даже структуры
Испольуйте опцию -O для оптимизации. Есть еще опции i,r,s, которые иногда комбинируют в -Oirs, но они, например, могут удалить чтение из регистра процессора, значение которого не используется. А это фатально.
Поддерживается импорт переменных из других файлов. cc65 умеет импортировать переменные и массивы из ассемблерных модулей командой
а если это символ из нулевой страницы памяти, то добавьте директиву
В дальнейшем курсе эти конструкции будут использоваться редко. Единственное исключение — импорт большого бинарного файла. В этом случае оптимально будет завернуть его в ассемблерный файл:
а потом импортировать в С как
Знак _ здесь критичен, потому что при компиляции в ассемблерный код cc65 добавляет _ перед каждым именем переменной. Нам надо этому соответствовать.
Можно вызывать функции, написанные на ассемблере, через __fastcall__. В этом случае аргументы передадутся в функцию через регистры, а не стек — экономит время. В некоторых случаях без ассемблерного кода не обойтись, например при инициализации приставки. В любом случае, чем меньше аргументов передается в функцию, тем лучше. Сравним две функции, причем переменные test и A глобальные:
Еще можно вставлять ассемблерный код прямо в сишный. Я так почти никогда не делаю, но наверное иногда это необходимо. Выглядит примерно так:
Кроме того, я заменил громоздкий код инициализации crt0.s на компактный reset.s, и подправил конфигурацию для всего этого. Эти файлы иногда будут меняться. nes.lib используется стандартный, из состава компилятора. Проект собирается с опцией –add-source, которая не удаляет промежуточные ассемблерные файлы — можно порассматривать сгенерированный код.
Удобней определить переменные в сишном коде, а потом импортировать в ассемблерный через
Но это вопрос вкуса, на мой взгляд, такой код наглядней.
Hello World
Эта программа будет просто печатать текст на экране. Надо помнить, что приставка вообще не знает про кодировку ASCII и работу с текстом в любом виде. Но зато есть возможность вывести картинки размером 8х8 поверх фона.
Так что делаем массив спрайтов-букв, чтобы адреса букв в нем соответсвовали их ASCII-кодам. Потом их можно будет дернуть из кода на С.
Код инициализации приставки пока берем как есть, после его выполнения происходит переход на main().
Нам надо сделать такие операции:
- Выключить экран
- Настроить палитру
- Вывести заветные слова
- Отключить прокрутку
- Включить экран
- Повторить
Выключение экрана нужно, потому что работа с видеопамятью вызывает мусор на экране. Надо или выключить экран, или ждать кадровый гасящий импульс (V-Blank). Детально этот вопрос мы рассмотрим в следующий раз.
Код инициализации заполняет память нулями, так что весь экран будет залит нулевым тайлом — в нашем случае, он пустой. А вся палитра заполнена серым цветом.
Для вывода на экран надо записать координаты начала заливки начиная со старшего байта по адресу $2006, а потом записывать номера тайлов в $2007. PPU будет выводить тайлы с соответствующими номерами один за другим, с переходом на новую строку. Можно перенастроить PPU на шаг вывода, равный 32 — тайлы будут выводиться один под другим. Нам же надо выставить шаг 1, через регистр $2000. Пересчитать координаты экрана в адрес можно через NES screen tool.
Нам также надо заполнить первые 4 цвета палитры — они отвечают за фон. Они записываются по адресу $3F00.
Запись в регистры PPU ломает положение прокрутки, так что ее тоже надо сбросить. Иначе картинка может уехать за экран. Мы делаем это через регистры $2006 и $2005.
Дропбокс
Гитхаб
На Гитхабе чуть исправил Makefile, чтобы корректно работал под Windows.
Строка
ONCE: load = PRG, type = ro, optional = yes;
внутри секции segments<> в файлах .cfg нужна для совместимости со свежей версией cc65.
Включение экрана через “PPUMASK = 0x1e” описано в Вики.
Все файлы здесь размером 0х4000. Это самый маленький возможный размер PRG ROM. 90% игр сюда не влезут, и будут отображаться на адреса $8000-$FFFF. У нас же игра загружается в адреса $C000-$FFFF и зеркалируется в $8000-$BFFF. Для разработки большей игры надо будет перенастроить адрес начала ROM на $8000, и выставить размер тоже $8000. А еще включить второй банк PRG ROM в секции header.
Мелочная какая
Логика игры
Чтобы в игру было интереснее играть дольше пяти минут, разработчики поставили такие требования:
- Это будет платформер — игра, где главному герою нужно бегать и прыгать по платформам, залезать наверх и скакать через препятствия.
- Герой сможет ловко двигаться и стрелять по врагам.
- Чтобы можно было играть компанией, делают мультиплеер на четырёх человек.
Так как у нас ограничения по памяти, всю игру пишут на Ассемблере — это язык, который работает напрямую с процессором. С одной стороны, код Ассемблера исполняется очень быстро; с другой — в нём работа идёт тупо с перекладыванием данных из одной ячейки процессора в другую. Это примерно как готовить суши, работая с индивидуальными рисинками.
Память распределили так:
- 8 килобайт на графику,
- 32 килобайта на сам код игры и хранение данных.
Ответ на пост «Яндекс.Про заблокировал не за что»
Братан, ну что же ты так лажаешь, зачем лишний раз позволяешь окружающим думать о таксистах плохо?
Телефон у тебя рутованный, и не надо строить целку, рассказывая "я всего лишь хотел поставить эмодзи" Если бы дело было в эмодзи, ты бы не ставил туда Магиск - он смайликам не нужен, а нужен для сокрытия Рута.
А рут таксисту нужен для обмана Яндекса.
В частности для подмены координат. Чтоб не выполнять плохой заказ.
Для подмены фотоконтроля личности. Чтоб кататься по чужим документам.
Для подмены фотоконтроля автомобиля. Чтоб не оклеивать автомобиль, или скрыть иные проблемы.
Рут на телефоне прямо запрещен правилами, и последние полгода Яша активно геноцидит только за него, ты разве не знал?
Зачем ты выложил скрин с показателями?
Активность 43 означает, что ты регулярно отказываешься от заказов(и не умеешь восстанавливать активность), что тоже не нравится Яше.
В итоге ты дал еще один повод публике сказать, что все таксисты-мундаки.
Современные агрегаторы выстроили несправедливый рынок с дикими перекосами.
Но общество не любит нарушений правил, которые в частности ты принял офертой при установке Яндекс.Про
Так что было бы лучше, если бы ты пиздел поменьше на публике.
Как писали игры для приставок: чудеса оптимизации и жёсткий кодинг
В 1980-х годах, когда приставки только появлялись, вышла NES — Nintendo Entertainment System. В Россию она попала в виде китайского клона «Денди», «Кенги» и прочих, поэтому если у вас была восьмибитная приставка, то это была NES.
У NES было очень мало памяти и очень медленный по нынешним меркам процессор. Эта статья о том, как сделать крутую игру в очень ограниченных условиях.
Та самая приставка, справа пока ещё две кнопки вместо четырёх. Для разбора мы взяли видео из канала Morphcat Games — How we fit an NES game into 40 Kilobytes. Там разработчики повторяют опыт геймдизайнеров прошлого и пишут игру для старого железа. Как обычно, если знаете английский, то лучше посмотрите видео целиком, а если нет — держите наш текстовый вариант.
BMW и новые технологии
Большой босс и оптимизация памяти
Если с персонажем всё стало проще, когда его уменьшили, то с боссом всё немного сложнее. Он большой, занимает много места и у него много анимации. Задача — сделать так, чтобы боссы занимали как можно меньше места в памяти.
Большой босс и все его варианты анимации. Если мы распределим все спрайты по таблице один в один, то у нас быстро закончится место и один кусочек не поместится. Запомните эту картинку как пример неоптимизированной работы с памятью. Для начала разработчики разбили босса горизонтально на три части, и каждая анимируется отдельно. Видно, что анимация причёски состоит из трёх картинок, каждая из которых немного отличается от остальных. Если разбить картинки с причёской на отдельные квадратики, то мы заметим, что у них есть повторяющиеся части. Поэтому достаточно нарисовать одну деталь, а потом использовать её во всех трёх вариантах причёски. Находим оставшиеся одинаковые части и тоже оставляем только одну из них. А вот тут видно, что это один и тот же спрайт, только в зеркальном виде. Компьютеру несложно нарисовать его отражённым, поэтому тоже можно смело оставить только один из них. С последними треугольничками в каждой картинке — то же самое: это отзеркаленные первые спрайты. В итоге вся верхняя часть босса вместе с анимацией поместилась в четырёх спрайтах. Это и есть оптимизация: было 16 спрайтов, стало 4. То же самое делают для средней части. Сейчас она занимает 3 x 8 = 24 спрайта. А сейчас — 7. После полной оптимизации босс занимает всего 21 спрайт. Из этих кусочков собирается итоговый вид босса. Сравните с первоначальным вариантом до оптимизации ?
БМВ водительница
На Ленинградском шоссе в Москве владелица BMW поцарапала ключом автомобиль Tesla.
Водитель электромобиля вышел в супермаркет буквально на несколько минут. А когда вернулся, обнаружил на машине царапины.
Судя по камерам, женщине не понравилось, что соседняя машина была слишком близко припаркована. Бизнесмен уже написал заявление в полицию.
Почему именно 40 килобайт
В 1980-х объём памяти на цифровых устройствах измеряли в килобайтах, потому что ещё не было таких продвинутых её технологий. В большинстве картриджей для восьмибитных приставок было по 40 килобайт памяти. Для сравнения, это в сто тысяч раз меньше, чем на флешке в 4 гигабайта. Даже эта статья весит больше, чем 40 килобайт, так что по современным меркам этого действительно мало.
Два блока памяти в картриджах, 8 и 32 килобайта, в сумме — 40 килобайт.
Чтобы использовать больше памяти, нужно было идти на всякие ухищрения — ставить расширители памяти или отдельные блоки для работы с несколькими картриджами одновременно. Так как почти ни у кого из геймеров такой роскоши не было, то разработчики использовали только 40 доступных килобайт.
Когда у тебя мало памяти, у тебя мало возможностей: уровни однообразные, враги однообразные, геймплей одинаковый. Но иногда разработчики шли на безумные ухищрения, и в игру получалось запихнуть много «миров», секретов и вариантов геймплея.
Одна из игр, которая взорвала мозг всем в своё время, была та самая «Супер Марио»: в ней было огромное количество разнообразных уровней разной сложности, боссы, секретные уровни и непростой, очень насыщенный геймплей. Были уровни на земле, под землёй, под водой и даже на небе; у героя было несколько режимов — низкий, высокий, в белом комбинезоне. А как вам идея разрушаемого мира? А как вам атаки с воздуха? Короче, «Марио» была безумной, невероятной игрой для своего времени, а всё благодаря оптимизациям.
В видеоролике разработчики поставили себе похожую цель: сделать насыщенную, разнообразную игру с большим количеством уровней, миров и настроений. И они показали, как этого добиться с помощью жёстких оптимизаций.
«Супер Марио» — игра, в которую играл каждый, у кого была приставка.
Цены на картошку
Живу в Волгограде. Цены на картошку в мешках бьют 50+ рублей.
Что происходит? Молодая в августе стоила дешевле. В пошлом году я в это время затарил 200+кг по 22р. за кг.
Обьясните мне. Я нифига не понимаю. Это сговор фермеров-овощеводов? Или такой неурожай на картоху?
Жуткий клиент
Давненько не было забавных историй с клиентами, но описанная ниже ситуация немного меня напрягла и позабавила одновременно)
Для многих не секрет, что я делаю ножи, и материал для рукоятей использую вообще максимально разнообразный (чем я и прославился):
Зуб мамонта стабилизированный:
Ну и прочее и прочее.
И бывает, что клиент хочет на рукоять, что-то памятное: кто-то просит добавить перо птицы, кто-то вишнёвые косточки, один попросил кожуру арбуза. Ну, свои загоны у каждого, кто я такой, чтобы судить или учить: если можно сделать, то почему бы и нет? Но бывают и такие кадры (К -клиент):
К: Привет! Отличные ножи!
Я: Добрый! Спасибо! Могу что-то подсказать?
К: Хочу себе изготовить нож, для охоты. Наткнулся на твой магазин на этси, и вижу, что ты делаешь Кастомизацию. И используешь очень разнообразный набор материалов.
Я: Да, если это можно залить эпоксидкой смолой и обработать впоследствии- конечно могу.
К: Найс! А с костями работаешь?
Я: Эм, ну я использую бивни мамонтов, зубы, или искусственную слоновью кость, но прям кости стараюсь не юзать, так как я не всегда уверен, что они легально были добыты. Одно дело мамонт, который уже мёртв, а другое убивать животных ради зубов не хочется.
К: Неееееее, все нормально, у меня свои кости, и никого никто не убивал! Это бедренная кость моего покойного брата. Он умер 3 года назад, и вот я хотел бы использовать ее, чтобы изготовить нож.
Моя примерная реакция:
Я: Бедренная кость брата? Это прям его кость? Настоящая? Вашего родного брата?
К; Да. Мы были большими фанатами охоты, и мне было бы очень важно, чтобы о нем у меня осталась такая память.
Я: Понял! Прошу прощения, но настолько ценный и необычный предмет не стоит высылать почтой, а то если потеряют, то уже все. Тем более наша таможня такое изымет почти сразу, а потом не докажешь, что это человеческая кость, которая добыта законным путём.
К: А ты прав. Бл*ть, чертовы бюрократы. Ну ладно, отличные ножи, обязательно что-нибудь потом куплю, как закончу с этим проектом! Удачи!
Как писались игры на Dendy
Радуга-пружинка
Очень эта штука в детстве нравилась.Сам лично себе такую купил первый раз в 24.
Всегда думал ,что "максимум" для этой игрушки , это спускаться по лесенке
Дали отпор
Москва. Таганско-Краснопресненская линия метро.
Горные жители начали приставать к девушкам и чуть было не случился сиквел недавних событий, но в этот раз всё прошло по другому сценарию. Русские люди сплотились и дали отпор дикарям.
Считаем, что это благодаря массовой огласке прошлого случая, буквально федеральному пиару и героизации Романа Ковалёва. Теперь терпилой быть стыдно, а давать отпор, не проходить мимо несправедливости - это почётно.
Когда в Татарстане сделали вход в ТЦ по QR-коду
Скрин из паблика VK
Ответ на пост «Вместо повышения зарплат инженерам, власти предлагают компаниям договориться об ограничении конкуренции за сотрудников»
У нас в городе мало производств,где платят нормальные (по меркам региона) деньги. Не так давно появился новый игрок - европейская компания, которая сразу начала приглашать специалистов, в том числе с нашего. Предлагали з/п от 125% до 200% от нашей. Народ, который 5 лет не получал ни повышения, ни даже просто индексации з/п, естественно, обрадовался и побежал туда, сверкая пятками. Потеряли чуть ни не половину офиса и ИТР. Что сделал наш дир, опытный приезжий руководитель с европейским же образованием? Уходящим предлагал от +2 до +10к к з/п и удивлялся, что никто не соглашается остаться.
А потом, спустя пару месяцев, торжественно объявил всем, что достигнута договоренность с директором конкурента о том, что наши сотрудники не будут рассматриваются на вакансии там. Сидите и не дергайтесь. Здорово, правда?
Читайте также: