+10.22
Рейтинг
31.23
Сила

Сергей

Да, дизайн уровней просчитан заранее. Процесс их создания наполовину автоматизирован, поэтому, когда собираешь уровень, то можно просчитать будущую нагрузку на CPU.

По поводу атрибутов: — есть три бага, которые ломают мне мозг уже не один месяц, и которые (пока) не удалось победить без удорожания стоимости отрисовки. Два из них воспроизводятся при вышибании первых и последних блоков в движении. И еще один: — не очищается самая левая колонка атрибутов, когда блок уезжает за левую границу.

А такого, чтобы спрайт игрока перекрашивал собой фоновые блоки — я не видел.
(Хотя есть одно исключение: взять «звезду» и подойти вплотную к белому блоку, у которого цвет идентичен цвету фона)
Графика рисуется через стек, и оставлять прерывания небезопасно.
Я, конечно, закладываю некое свободное время во фрейм. Но оно тоже может не успеть, на какой-нибудь супер-медленной машине.

Рендеринг всей графики в игре должен занимать не более ~80% фрейма. Это как бы теоретический максимум.
Но вполне может быть, что если сцена окажется перенасыщенной, и тогда и вывод графики вылезет за фрейм.
Этого нужно избегать еще на этапе дизайна уровня — использовать автоматические метрики, которые подскажут опасность «выхода за фрейм».
В памяти в RAM 2 по статичным адресам находятся четыре стека (по два стека на два экрана):
— 204 байта отведено под сохранение 2х-байтных адресов из области атрибутов, которые были «покрашены» в текущем фрейме, и которые нужно почистить позже;
— +2 байта на указатель стека;
— 48 байт отведено под хранение 16 «троек», где первые два байта — это адрес в экранной области, куда был выведен спрайт в текущем фрейме, и еще 1 байт кодирует размер выведенного спрайта;
— +2 байта на указатель стека.

Когда приходит время почистить экран и атрибуты:
— выгребаем по-порядку адреса из атрибутного стека, и вливаем по ним цвет фона;
— затем выгребаем «тройки» из второго стека и выводим на экран пустые прямоугольники: адрес в экране знаем, размер спрайта знаем.

Такие размеры стеков были выбраны исходя из того, что на экране не может быть более 16 динамических объектов одновременно (и то — это с большим запасом; в 3.5 Мгц столько не влезет). Средний размер одного спрайта 3x2 = 6 знакомест. Бывают также спрайты размерами по 2 (оружие), 4 (враг, приз) или 8 знакомест.

Помнить, что было под спрайтом, не нужно. Каждый раз всё заново перерисовывается.
Движок — это конвеер, который в каждом кадре делает одну и ту же работу.

Сначала идёт обработчик прерывания, на нём висит музыка, звуковые эффекты, и глобальные счётчики фреймов.
Затем идёт блок рендера. На время вызова графических процедур, прерывания запрещаются.

Рендер состоит из следующих шагов:
— очищаются все динамические объекты на экране (герой, враги, призы, файлболлы, — всё, что движется);
— выводятся неподвижные блоки, причём очищать их не нужно, т.к. «с хвоста» блоки чистят сами себя;
— поверх блоков выводятся все динамические объекты, с занесением в стек информации для очистки в следующем фрейме;

Далее опрашивается user input (клавиатура или джойстик). На основе этого для главного героя выбирается спрайт, и придаётся ускорение по осям (разбег, прыжок, торможение, итд).

Затем запускается конвеер обработки всей логики. Она полностью одинакова для всех движущихся объектов в сцене. Каждый объект прогоняется по этому конвееру: — изменяется состояние, координаты, детектируются коллизии, срабатывают события и происходит обработка реакции на события (если они заданы).
Весь алгоритм линейный, т.е. обработка всех физических свойств, всех коллизий и событий для одного объекта всегда занимает примерно одинаковое время, независимо от игровой ситуации.

После прогонки всех объектов по конвееру, последним в очереди идёт проверка общеигровых событий, таких как: достижение конца уровня, переключение режимов ГГ (immunity, starman, итп), проверка возможности захода в «трубы», и т.п.

Затем просто ждём следующего прерывания, меняем экраны местами, и поехали с начала.

Если не успели обработать всю логику, и прерывание пришло раньше, — ничего страшного. Пытаемся компенсировать это время в следующем кадре (т.е. не ждём прерывания, а сразу начинаем готовить следующий кадр).

В целом, у движка есть три режима работы:
— обычный геймплей, когда работают и рендер и логика;
— анимация («взятие приза», «заход в трубу», «скатывание по флагу») — работает только рендер, а логика управляется специально написанным скриптом;
— распаковка данных в память, тут 100% CPU отдаётся на распаковку, а на экране в это время показываются попеременно два статичных кадра, и просто играет музыка.

Если интересно, могу более подробно расписать по любому пункту.
Gogin:

Binary Love 2
000f — 9
25e4 — 8
636d — 1
6715 — 1
766a — 3
7912 — 6
877e — 8
d87a — 6
da45 — 5
dbdd — 10
eaf7 — 7

Speccy 2
1070 — 6
1fe1 — 5
1ff3 — 3
3c66 — 9
5007 — 9
63c3 — 8
ad6b — 1
c210 — 5
c25f — 10
ceb1 — 5
d59c — 9