Repository navigation
Menu and controls
Меню - это не отдельная программа и не «состояние конечного автомата» в
современном смысле. В оригинале это две глобальные переменные: g_appMode
(0x00026340, 0 - игра, 1 - меню) и g_screen, номер экрана. Порт держит их в
jb_mode и jb_menu.screen_id.
| Экран | screen_id |
Пункты |
|---|---|---|
| главный | 0 | Play · Settings · About · Exit |
| выбор уровня | 1 | Level 1 · Level 2 · Level 3 · Back |
| About | 2 | нет кнопок, десять строк текста |
| настройки | 4 | Sound · Auto-Jump · Controls · Back |
Тройки в нумерации нет, а настройки - четвёрка: так было в оригинале
(Menu_DrawFrame 0x0001a7d0), и порт не «нормализует» это. Пунктов на каждом
экране ровно четыре, индекс крутится по кругу 0..3.
DrawChrome собирает раму из пяти блитов, и порядок важен:
- фон меню (
g_backdropMenu 0x00061b48) без ключа; - тонкая полоска, размноженная по всей высоте
0x140шагом 10; - заголовок - в раскладке 176x220 берётся из
src(0x32, 0x14)высотой0x3c, иначе целиком высотой0x4d; - панель-градиент по низу,
view_h - 0x30; - логотип PocketNew - маской, тинтом
0xff,0xff,0xffв точкеview_center_x - 0x57, 0x11e.
Кнопки (DrawButtons) - узкая для каждого пункта шириной
0xa0 - (layout_mode >> 1) и широкая для выбранного шириной
200 - layout_mode со сдвигом src_x 10. На экране About не рисуются вообще.
Выбранный пункт дополнительно сдвигается по X: (index == i) * 0x10 + 0x23.
Заблокированный уровень нарисован, выбираем его свободно, просто он тусклый:
n[0] = 1;
n[1] = (max < 1) ? max : 1;
n[2] = ((max < 0) ? max + 1 : max) >> 1;
n[3] = 1;
/* цвет: r = (n + 1) * 0x7f, g = b = (n + 1) * 0x7d */При max_unlocked 0 второй и третий уровни получают n = 0, то есть цвет
(0x7f, 0x7d, 0x7d) вместо (0xfe, 0xfa, 0xfa) - ровно вдвое темнее. Запрет
живёт отдельно, в Confirm: index <= max_unlocked. Странная арифметика с
max < 0 - это >> над знаковым числом в оригинале; порт повторяет её
буквально, хотя отрицательным max_unlocked быть не может.
-
Sound - «подтвердить» на этом пункте прибавляет громкость, «влево»
убавляет (
Audio_VolumeStep(±1)), см. Audio-and-TKM. Полоска рисуется ширинойvol * 2, при этомsrc_xравен(0x20 - vol) * 2- полоска не растягивается, а выезжает из спрайта. -
Auto-Jump - текст пункта меняется на месте:
Auto-Jump [ ]/Auto-Jump [X], значение1 - auto_jump. Это тот самый флаг, из-за которого мяч на краю трассы либо подпрыгивает, либо падает - см. Physics. - Controls - запускает мастер переназначения (ниже).
- Back - на главный экран.
Десять строк с жёстко прошитыми координатами и выравниванием, цвет (0,0,0).
Здесь же авторство оригинала: Coder : Osaris, using Hekkus Sound System,
Graphics : Team PocketNew, тестеры Kisswert, FMARC, и www.pocketnew.net.
Кнопок нет, поэтому Step() принудительно держит index = 3, а любое
«подтвердить» уводит на главный экран.
Игра знает не клавиши, а шесть действий (jb_platform.h), и порядок этого
перечисления - контракт: по нему пишется и читается keys.cfg.
| # | Действие | По умолчанию | В меню | В игре |
|---|---|---|---|---|
| 0 | LEFT | SDLK_LEFT |
назад / убавить громкость | разгон влево |
| 1 | RIGHT | SDLK_RIGHT |
подтвердить | разгон вправо |
| 2 | UP | SDLK_UP |
пункт выше | вперёд |
| 3 | DOWN | SDLK_DOWN |
пункт ниже | тормоз |
| 4 | JUMP | SDLK_SPACE |
подтвердить | прыжок |
| 5 | MENU | SDLK_RETURN |
- | выход в меню |
«Подтвердить» - это и RIGHT, и JUMP: оригинал считал подтверждением
g_gxKeyStart, g_keyRight, g_gxKeyRight, g_gxKeyA, g_gxKeyB,
g_gxKeyC и g_keyJump сразу, то есть все аппаратные кнопки КПК плюс
«вправо». «Отмены» как таковой нет: её роль играет LEFT на вложенных экранах.
Опрос - по фронтам, не по состоянию (PumpKeys в jb_main.c): нажатие
обрабатывается только когда held != jb_key_prev[k]. В меню отпускания
игнорируются целиком, в игре они идут в Player_KeyUp - именно там ставятся
флаги *_released, на которых висит торможение (см. Physics).
KeyConfig_Begin обнуляет все шесть привязок и включает режим, в котором
кадровый цикл больше ничего не делает - все нажатия уходят в
KeyConfig_KeyDown, шаг за шагом. Проверка одна: код, уже занятый другим
действием, отбрасывается и шаг не двигается. Дошли до шести - привязки
сохраняются в keys.cfg.
Экран мастера рисуется тремя блитами из одного спрайта-полосы:
x = (view_w - 0xb0) / 2; /* с поправкой на отрицательное */
Blit(..., x, 0xf, 0xb0, 0x2a, panel, 0, 0);
Blit(..., x, view_center_x + 0x14, 0xb0, 0x19, panel, step * 0x19 + 0x2f);
Blit(..., x, view_h - 0x14, 0xb0, 0x14, panel, 0xde);Средняя полоса - подсказка текущего шага: шесть кусков по 0x19 = 25 пикселей,
начиная с 0x2f = 47. Обратите внимание на view_center_x + 0x14 в
координате Y - это не опечатка вики, а буквальный перенос оригинала.
Шесть десятичных кодов SDL, по одному в строке, в порядке таблицы выше. Файл
лежит рядом с Platform_PrefPath(). Загрузка недоверчивая: если любой код
равен нулю (не привязан) или совпадает с другим, файл отбрасывается целиком
и остаются значения по умолчанию. Частично применённой раскладки не бывает - это
защита от файла, после которого игрой нельзя управлять.
1073741904
1073741903
1073741906
1073741905
32
13
Сенсорная панель - добавление порта, в оригинале её нет (там КПК с
аппаратными кнопками). Живёт в jb_touch_sdl2.c и знает только те же шесть
действий.
Раскладка считается от размеров окна, а не от жёстких координат:
cell = min(win_w, win_h) / 7;
if (cell > win_h / 9) cell = win_h / 9;
margin = cell / 4;
side = cell + cell / 2; /* кнопка прыжка в 1.5 раза больше */
pad_h = 3 * cell + 2 * margin;
view_h = win_h - pad_h;Кадр игры вписывается в остаток по высоте с сохранением пропорции 240x320: сначала по ширине окна, и если не влезло - по высоте. Крестовина слева внизу, прыжок справа, меню - маленькая кнопка над прыжком.
Мультитач честный: до восьми пальцев, каждый помнит свой SDL_FingerID и свою
кнопку, SDL_FINGERMOTION переназначает кнопку под пальцем (можно
проскользить с «влево» на «вправо» не отрывая палец), а состояние кнопок
пересобирается из списка пальцев целиком, а не инкрементально - поэтому потерять
«залипшую» кнопку невозможно.
Рисуется панель уже после копирования кадра в окно, средствами SDL_Renderer:
прямоугольник, рамка, и шеврон из трёх точек (у меню - три полоски). Нажатая
кнопка подсвечивается 0x60,0x90,0xd0. Из-за этого порядка панель не попадает
в дампы кадров - см. Build-and-CI.
Устройство порта
Сборка и происхождение