Super Mario Bros. COVID-19 Edition
Всем привет!
Сделал для вас игру на актуальную нынче тему :)
Скачать тут:
zxart.ee/rus/soft/game/arcade/platform/super-mario-bros-covid-19-edition/
Движок, который я показывал на CAFe 2019, продолжает развиваться.
За последние пару месяцев в комплекте к нему появился UI-редактор миров.
Именно в нём и сделаны уровни для игры.
Играйте, наслаждайтесь. :)
Баг-репорты присылайте в личку в телеграм.
Сделал для вас игру на актуальную нынче тему :)
Скачать тут:
zxart.ee/rus/soft/game/arcade/platform/super-mario-bros-covid-19-edition/
Движок, который я показывал на CAFe 2019, продолжает развиваться.
За последние пару месяцев в комплекте к нему появился UI-редактор миров.
Именно в нём и сделаны уровни для игры.
Играйте, наслаждайтесь. :)
Баг-репорты присылайте в личку в телеграм.
9 комментариев
Я в эмуляторе немного анализировал что в экранной области происходит — как понял основная идея, что пустые области попиксельно никак не обрабатываются, а скроллится только активное содержимое. Но всё равно интересно какие структуры и т.п.
Ибо действительно fps и отзывчивость фантастические для спектрума.
Сначала идёт обработчик прерывания, на нём висит музыка, звуковые эффекты, и глобальные счётчики фреймов.
Затем идёт блок рендера. На время вызова графических процедур, прерывания запрещаются.
Рендер состоит из следующих шагов:
— очищаются все динамические объекты на экране (герой, враги, призы, файлболлы, — всё, что движется);
— выводятся неподвижные блоки, причём очищать их не нужно, т.к. «с хвоста» блоки чистят сами себя;
— поверх блоков выводятся все динамические объекты, с занесением в стек информации для очистки в следующем фрейме;
Далее опрашивается user input (клавиатура или джойстик). На основе этого для главного героя выбирается спрайт, и придаётся ускорение по осям (разбег, прыжок, торможение, итд).
Затем запускается конвеер обработки всей логики. Она полностью одинакова для всех движущихся объектов в сцене. Каждый объект прогоняется по этому конвееру: — изменяется состояние, координаты, детектируются коллизии, срабатывают события и происходит обработка реакции на события (если они заданы).
Весь алгоритм линейный, т.е. обработка всех физических свойств, всех коллизий и событий для одного объекта всегда занимает примерно одинаковое время, независимо от игровой ситуации.
После прогонки всех объектов по конвееру, последним в очереди идёт проверка общеигровых событий, таких как: достижение конца уровня, переключение режимов ГГ (immunity, starman, итп), проверка возможности захода в «трубы», и т.п.
Затем просто ждём следующего прерывания, меняем экраны местами, и поехали с начала.
Если не успели обработать всю логику, и прерывание пришло раньше, — ничего страшного. Пытаемся компенсировать это время в следующем кадре (т.е. не ждём прерывания, а сразу начинаем готовить следующий кадр).
В целом, у движка есть три режима работы:
— обычный геймплей, когда работают и рендер и логика;
— анимация («взятие приза», «заход в трубу», «скатывание по флагу») — работает только рендер, а логика управляется специально написанным скриптом;
— распаковка данных в память, тут 100% CPU отдаётся на распаковку, а на экране в это время показываются попеременно два статичных кадра, и просто играет музыка.
Если интересно, могу более подробно расписать по любому пункту.
— 204 байта отведено под сохранение 2х-байтных адресов из области атрибутов, которые были «покрашены» в текущем фрейме, и которые нужно почистить позже;
— +2 байта на указатель стека;
— 48 байт отведено под хранение 16 «троек», где первые два байта — это адрес в экранной области, куда был выведен спрайт в текущем фрейме, и еще 1 байт кодирует размер выведенного спрайта;
— +2 байта на указатель стека.
Когда приходит время почистить экран и атрибуты:
— выгребаем по-порядку адреса из атрибутного стека, и вливаем по ним цвет фона;
— затем выгребаем «тройки» из второго стека и выводим на экран пустые прямоугольники: адрес в экране знаем, размер спрайта знаем.
Такие размеры стеков были выбраны исходя из того, что на экране не может быть более 16 динамических объектов одновременно (и то — это с большим запасом; в 3.5 Мгц столько не влезет). Средний размер одного спрайта 3x2 = 6 знакомест. Бывают также спрайты размерами по 2 (оружие), 4 (враг, приз) или 8 знакомест.
Помнить, что было под спрайтом, не нужно. Каждый раз всё заново перерисовывается.
Я, конечно, закладываю некое свободное время во фрейм. Но оно тоже может не успеть, на какой-нибудь супер-медленной машине.
Рендеринг всей графики в игре должен занимать не более ~80% фрейма. Это как бы теоретический максимум.
Но вполне может быть, что если сцена окажется перенасыщенной, и тогда и вывод графики вылезет за фрейм.
Этого нужно избегать еще на этапе дизайна уровня — использовать автоматические метрики, которые подскажут опасность «выхода за фрейм».
и кстати, с чисткой атрибутов не всё в порядке, иногда спрайт игрока перекрашивает фоновые платформы
По поводу атрибутов: — есть три бага, которые ломают мне мозг уже не один месяц, и которые (пока) не удалось победить без удорожания стоимости отрисовки. Два из них воспроизводятся при вышибании первых и последних блоков в движении. И еще один: — не очищается самая левая колонка атрибутов, когда блок уезжает за левую границу.
А такого, чтобы спрайт игрока перекрашивал собой фоновые блоки — я не видел.
(Хотя есть одно исключение: взять «звезду» и подойти вплотную к белому блоку, у которого цвет идентичен цвету фона)