SprPoP: заставку можно прервать в любой её точке, F10 — выход
Три места, где нажатие раньше не работало или работало наполовину. FADE. fade_run() был замкнутым циклом на 2,13 с без опроса клавиш, а на стыке экранов их два: пропуск работал внутри сценария, но не между его шагами, и заставка ощущалась невыключаемой. Добавлены прерываемые варианты (pop_ui_fade_*_skip, обёртки в pop_pal) — отдельными функциями, а не флагом в прежних: в меню паузы и на переходе уровня прерывать нечего, и менять там поведение молча не следует. Прерванный fade всё равно доводит палитру до конца, экран не остаётся на промежуточной ступени. Подключено в интерпретаторе сценария, сцене с принцессой, четырёх катсценах cut_*, титрах и таблице рекордов. ПРОЯВЛЕНИЕ ПОЛОСАМИ. pop_screen_present_ltr() была void и нажатие ГЛОТАЛА: полосы схлопывались, картинка появлялась целиком — и всё, вызывающий о нажатии не узнавал. На заставке это выглядело как «клавиша срабатывает наполовину». Теперь возвращает признак прерывания, и он проброшен по маршруту: первый экран истории, титры финала, логотип между «свадьбой» и титрами. Везде считается КРОМКА нажатия от входа, как в сценах: клавиша, которой закончили предыдущий экран, ещё зажата, и принимать её за новое нажатие нельзя — иначе весь маршрут заставки схлопывался бы сам собой. F10 — НЕМЕДЛЕННЫЙ ВЫХОД, откуда угодно. Проверка стоит в kbd_idle(), а этот хук висит на gfx_wait_vsync, то есть вызывается везде, где программа ждёт кадр: заставка, титры, fade, проявление полосами, меню, игра. Одна точка вместо десятка по циклам ожидания. Флаг pop_quit_req резидентный — взводится и читается без трамплина из любого банка. Проверка в НАЧАЛЕ витка автомата обязательна: заставку прерывает любая клавиша, и без неё F10 успевал уронить программу в загрузку уровня перед закрытием. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -119,9 +119,16 @@ uint8_t pop_menu_request;
|
||||
|
||||
/* Обёртка ради типа: хук — void(*)(void), а kbd_raw_poll возвращает
|
||||
* «было ли что вычерпано». Приводить указатель кастом не хочется. */
|
||||
/* F10 (PS/2 set 2 — 0x09): немедленный выход. Проверяем ЗДЕСЬ, а не в
|
||||
* каждом цикле ожидания: idle-хук висит на gfx_wait_vsync, то есть
|
||||
* вызывается везде, где программа ждёт кадр — заставка, титры, fade,
|
||||
* проявление полосами, меню, игра. Одна точка вместо десятка. */
|
||||
#define KBD_KEY_F10 0x09
|
||||
|
||||
static void kbd_idle(void)
|
||||
{
|
||||
kbd_raw_poll();
|
||||
if (kbd_raw_down(KBD_KEY_F10)) pop_quit_req = 1;
|
||||
}
|
||||
|
||||
/* seq_2_stand (types.h seqids) — Kid стоит, ждёт ввода. */
|
||||
@@ -282,6 +289,12 @@ int main(void)
|
||||
for (;;) {
|
||||
uint8_t is_demo;
|
||||
|
||||
/* F10 в любой точке — выходим, не начиная следующий маршрут. Проверка
|
||||
* стоит В НАЧАЛЕ витка: заставку и титры прерывает ЛЮБАЯ клавиша (это
|
||||
* штатный «пропустить в игру»), и без этой строки F10 успел бы уронить
|
||||
* нас в загрузку уровня перед тем, как программа закроется. */
|
||||
if (pop_quit_req) break;
|
||||
|
||||
/* Title -> intro -> demo — три самостоятельных состояния. Сцены не
|
||||
* вызывают gameplay рекурсивно: после каждого return следующий маршрут
|
||||
* выбирается только pop_app_dispatch(). */
|
||||
@@ -364,7 +377,7 @@ int main(void)
|
||||
demo_new_game = 0;
|
||||
demo_finished = 0;
|
||||
|
||||
while (!quit && (pop_app_state == POP_APP_PLAYING ||
|
||||
while (!quit && !pop_quit_req && (pop_app_state == POP_APP_PLAYING ||
|
||||
pop_app_state == POP_APP_DEMO)) {
|
||||
PROF(2); /* ввод + heal */
|
||||
|
||||
@@ -926,7 +939,7 @@ int main(void)
|
||||
if (is_demo && demo_finished) break;
|
||||
}
|
||||
|
||||
if (quit) break;
|
||||
if (quit || pop_quit_req) break;
|
||||
/* Restart Game завершает только игровой цикл. Следующая итерация
|
||||
* верхнего автомата начинает title/intro с самого первого экрана. */
|
||||
if (pop_app_state == POP_APP_TITLE) continue;
|
||||
|
||||
Reference in New Issue
Block a user