И сразу вопрос — «с занесением в стек информации для очистки в следующем фрейме» — что именно тут подразумевается? Т.е. вопрос вот в чём, что лежит под спрайтом вроде легче выяснить при выводе статических объектов. Но у тебя это разнесено. Т.е. ты либо должен восстанавливать, что у тебя под спрайтом ещё раз, либо сохранять экранные данные, либо?
Движок — это конвеер, который в каждом кадре делает одну и ту же работу.
Сначала идёт обработчик прерывания, на нём висит музыка, звуковые эффекты, и глобальные счётчики фреймов.
Затем идёт блок рендера. На время вызова графических процедур, прерывания запрещаются.
Рендер состоит из следующих шагов:
— очищаются все динамические объекты на экране (герой, враги, призы, файлболлы, — всё, что движется);
— выводятся неподвижные блоки, причём очищать их не нужно, т.к. «с хвоста» блоки чистят сами себя;
— поверх блоков выводятся все динамические объекты, с занесением в стек информации для очистки в следующем фрейме;
Далее опрашивается user input (клавиатура или джойстик). На основе этого для главного героя выбирается спрайт, и придаётся ускорение по осям (разбег, прыжок, торможение, итд).
Затем запускается конвеер обработки всей логики. Она полностью одинакова для всех движущихся объектов в сцене. Каждый объект прогоняется по этому конвееру: — изменяется состояние, координаты, детектируются коллизии, срабатывают события и происходит обработка реакции на события (если они заданы).
Весь алгоритм линейный, т.е. обработка всех физических свойств, всех коллизий и событий для одного объекта всегда занимает примерно одинаковое время, независимо от игровой ситуации.
После прогонки всех объектов по конвееру, последним в очереди идёт проверка общеигровых событий, таких как: достижение конца уровня, переключение режимов ГГ (immunity, starman, итп), проверка возможности захода в «трубы», и т.п.
Затем просто ждём следующего прерывания, меняем экраны местами, и поехали с начала.
Если не успели обработать всю логику, и прерывание пришло раньше, — ничего страшного. Пытаемся компенсировать это время в следующем кадре (т.е. не ждём прерывания, а сразу начинаем готовить следующий кадр).
В целом, у движка есть три режима работы:
— обычный геймплей, когда работают и рендер и логика;
— анимация («взятие приза», «заход в трубу», «скатывание по флагу») — работает только рендер, а логика управляется специально написанным скриптом;
— распаковка данных в память, тут 100% CPU отдаётся на распаковку, а на экране в это время показываются попеременно два статичных кадра, и просто играет музыка.
Если интересно, могу более подробно расписать по любому пункту.
Очень интересно было бы почитать (я где то слышал что на профильных форумах обсуждение было) как движок работает.
Я в эмуляторе немного анализировал что в экранной области происходит — как понял основная идея, что пустые области попиксельно никак не обрабатываются, а скроллится только активное содержимое. Но всё равно интересно какие структуры и т.п.
Ибо действительно fps и отзывчивость фантастические для спектрума.
Нет, не стоит. Потому что это всё, во-1, необязательно признак неумелости, а во-2, не настолько большинство, как линейный буфер. Контрпримеры легче найти гораздо, чем примеры с буфером в юлашной раскладке.
Подавляющее большинство игрушек не умеют делать vsync. Подавляющее большинство игрушек обновляют экран раз в 3 фрейма или даже медленнее (offscreen buffer — одна из важных причин этого). Подавляющее большинство игрушек shipped с артефактами изображения. Мне продолжать?
В подавляющем, абсолютном большинстве игрушек линейный буфер, так что и умеющие так делали. Для игродела плюсов в спековской раскладке весьма немного и они только в очень частных случаях проявляются. А вот неудобства намного чаще.
Это очень хороший анекдот. Непонимание раскладки ULA — натурально, бич начинающих кодеров. Она действительно не всегда удобна, но думаю многие со мной согласятся, что с опытом приходит понимание, что она намного эффективнее линейной раскладки.
Нет. У меня сейчас на самом деле денди с маппером MMC3 голова забита если про хобби говорить. Про Next получилось просто что одна предыдущая статья была написана уже давно, а система команд ну очень уж немного и интересно, перевести так и просилось.
Бегло взглянул на zxnDMA сейчас — оно как я понял является даже усечением Z80 DMA и насколько я понял из упрощений только то что раньше количество итераций вбивалось как X+1 (и в режиме совместимости это сохранено), а сейчас можно как X передавать в новом режиме. А в остальном вроде всё такое же, но там уже куча битовых флагов и адресов и перевод уже дело нудненькое.
aa-dav, а планируется ли такая же обзорно-поучительная статья по преимуществам zxnDMA в отличии от Z80DMA? Но на великом и могучем, а не как у них в dev.
xD
Тут явно надо родить анекдот класса «стадии смирения»…
Наподобие такого:
Есть три стадии развития программиста на спектруме:
1. ты не понимаешь как раскладку видеопамяти ULA
2. ты понимаешь раскладку видеопамяти ULA
3. ты не понимаешь раскладки видеопамяти не как в ULA
В Z80N на самом деле в разное время присутствовали еще некоторые команды, о назначении (и полезности?) которых можно лишь догадываЦЦа.
LD_ACC32_DEHL, EXXACC32, LD_DEHL_ACC32, INC_DEHL, DEC_DEHL, ADD_DEHL_A, SUB_DEHL_A, ADD_DEHL_BC, SUB_DEHL_BC, MIRROR_DE, PIXELTOATTR, ATTRTOPIXEL и т.д.
За статью — спасибо. Полезно.
Каждый раз ор и рукалицо с этих костылей. А вы думали, вот что надо сделать, чтоб исправить неудобство адресации оригинальной юлы? Ага, точно — надо «исправлять» другой и самый сложный компонент — процессор, вместо простого. С результатом всё равно неудобнее, чем у старых самопальных компов советских. Вот казалось бы, всё равно со спеком несовместимо, ну запилите вы прозрачную трансляцию адреса. Но нет, эти люди лёгких путей не ищут.
Сначала идёт обработчик прерывания, на нём висит музыка, звуковые эффекты, и глобальные счётчики фреймов.
Затем идёт блок рендера. На время вызова графических процедур, прерывания запрещаются.
Рендер состоит из следующих шагов:
— очищаются все динамические объекты на экране (герой, враги, призы, файлболлы, — всё, что движется);
— выводятся неподвижные блоки, причём очищать их не нужно, т.к. «с хвоста» блоки чистят сами себя;
— поверх блоков выводятся все динамические объекты, с занесением в стек информации для очистки в следующем фрейме;
Далее опрашивается user input (клавиатура или джойстик). На основе этого для главного героя выбирается спрайт, и придаётся ускорение по осям (разбег, прыжок, торможение, итд).
Затем запускается конвеер обработки всей логики. Она полностью одинакова для всех движущихся объектов в сцене. Каждый объект прогоняется по этому конвееру: — изменяется состояние, координаты, детектируются коллизии, срабатывают события и происходит обработка реакции на события (если они заданы).
Весь алгоритм линейный, т.е. обработка всех физических свойств, всех коллизий и событий для одного объекта всегда занимает примерно одинаковое время, независимо от игровой ситуации.
После прогонки всех объектов по конвееру, последним в очереди идёт проверка общеигровых событий, таких как: достижение конца уровня, переключение режимов ГГ (immunity, starman, итп), проверка возможности захода в «трубы», и т.п.
Затем просто ждём следующего прерывания, меняем экраны местами, и поехали с начала.
Если не успели обработать всю логику, и прерывание пришло раньше, — ничего страшного. Пытаемся компенсировать это время в следующем кадре (т.е. не ждём прерывания, а сразу начинаем готовить следующий кадр).
В целом, у движка есть три режима работы:
— обычный геймплей, когда работают и рендер и логика;
— анимация («взятие приза», «заход в трубу», «скатывание по флагу») — работает только рендер, а логика управляется специально написанным скриптом;
— распаковка данных в память, тут 100% CPU отдаётся на распаковку, а на экране в это время показываются попеременно два статичных кадра, и просто играет музыка.
Если интересно, могу более подробно расписать по любому пункту.
Я в эмуляторе немного анализировал что в экранной области происходит — как понял основная идея, что пустые области попиксельно никак не обрабатываются, а скроллится только активное содержимое. Но всё равно интересно какие структуры и т.п.
Ибо действительно fps и отзывчивость фантастические для спектрума.
Бегло взглянул на zxnDMA сейчас — оно как я понял является даже усечением Z80 DMA и насколько я понял из упрощений только то что раньше количество итераций вбивалось как X+1 (и в режиме совместимости это сохранено), а сейчас можно как X передавать в новом режиме. А в остальном вроде всё такое же, но там уже куча битовых флагов и адресов и перевод уже дело нудненькое.
Тут явно надо родить анекдот класса «стадии смирения»…
Наподобие такого:
Есть три стадии развития программиста на спектруме:
1. ты не понимаешь как раскладку видеопамяти ULA
2. ты понимаешь раскладку видеопамяти ULA
3. ты не понимаешь раскладки видеопамяти не как в ULA
LD_ACC32_DEHL, EXXACC32, LD_DEHL_ACC32, INC_DEHL, DEC_DEHL, ADD_DEHL_A, SUB_DEHL_A, ADD_DEHL_BC, SUB_DEHL_BC, MIRROR_DE, PIXELTOATTR, ATTRTOPIXEL и т.д.
За статью — спасибо. Полезно.
Тут небольшие дополнения что бы OS эмулировать.