PoP roomtest: дверь уровня — створка, лестница и анимация открытия

Комната 9: портал на уровень 2 рисовался чёрным проёмом — не был
портирован draw_leveldoor (seg008:1D29).  Дверь рисуется при обработке
ПРАВОЙ половины (tile_left = 0x10), все куски со сдвигом +8 px:
  99  низ лестницы (всегда),
  144 марш лестницы за створкой (когда створка тронулась),
  33  слайс створки — повторяется вниз с шагом 4 px до y = ybottom-modif
      (modif 0 = закрыто на всю высоту, 43 = открыто, остаётся кромка),
  34  верх коробки.

Анимация: animate_leveldoor (seg007:05F1) — type 0..2 открытие (modif++
до 43), type>=3 быстрое закрытие со скоростями {0,5,17,99}.  Кнопка
заводит trob через trigger_1 (seg007:0999): дверь открывается ОДИН раз,
при modif != 0 кнопка уже ничего не делает.

Перерисовка створки — pop_leveldoor_redraw: draw_tile правой половины С
ЗАПЕЧКОЙ в ОЗУ-копию (банк TRANSPARENT), иначе kid_heal возвращал бы из
фона закрытую створку.  Куски двери непрозрачные, wipe не нужен.

Спрайты 33/34/99/144 не попадали в атлас: сбор идёт прогоном
render_room.py, а он draw_leveldoor не реализует — добавлены явным
набором LEVELDOOR_ENV_IDS (как STUCK_ENV_IDS для нажатой кнопки).

Проверено в MAME (комната 9): закрытая дверь = решётка как в оригинале;
после нажатия кнопки (0,0) створка едет вверх, открывая лестницу.
Вход в дверь (кадры 217..228 + переход на уровень 2) НЕ делался.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-29 18:05:57 +03:00
parent fb495ace42
commit 63a25530f5
72 changed files with 90 additions and 2 deletions
+40
View File
@@ -15,6 +15,7 @@
#define TILE_OPENER 0x0F
#define TILE_POTION 0x0A
#define TILE_SWORD 0x16 /* меч-предмет на полу */
#define TILE_LEVELDOOR 0x10 /* левая половина двери уровня (на ней modif) */
#define TILE_TORCH 0x13
#define TILE_TORCH_DEBRIS 0x1E
@@ -240,6 +241,13 @@ static int8_t trigger_1(uint8_t target_type, uint8_t room, uint8_t tilepos, uint
{
if (target_type == TILE_GATE)
return trigger_gate(room, tilepos, button_type);
if (target_type == TILE_LEVELDOOR) {
/* trigger_1 (seg007:0999): дверь уровня открывается ОДИН раз — если
* створка уже тронулась (modif != 0), кнопка ничего не делает. */
uint8_t *m = pop_trob_modif(room);
if (m && m[tilepos] == 0) return 1;
return -1;
}
return -1;
}
@@ -282,6 +290,27 @@ static void animate_button(uint8_t idx, int8_t *type)
}
}
/* animate_leveldoor (seg007:05F1): створка двери уровня. type 0..2 —
* открытие (modif 0 -> 43, по пикселю за кадр), type >= 3 — быстрое
* закрытие со скоростями {0,5,17,99} (после выхода из уровня). Готово ->
* type = -1. */
static const uint8_t leveldoor_close_speeds[5] = {0, 5, 17, 99, 0};
static void animate_leveldoor(uint8_t *m, int8_t *type)
{
if (*type < 0) return;
if (*type >= 3) {
uint8_t sp;
if (*type < 7) (*type)++;
sp = leveldoor_close_speeds[*type - 3];
if (sp >= *m) { *m = 0; *type = -1; }
else *m = (uint8_t)(*m - sp);
} else {
if (*m < 43) (*m)++;
if (*m >= 43) { *m = 43; *type = -1; }
}
}
/* animate_door (seg007:0522): openness по типу анимации. *m — modif ворот,
* *type — 0 закрытие / 1 открытие / 2 насовсем / 3..8 быстрое закрытие. */
static const uint8_t gate_close_speeds[9] = {0, 0, 0, 20, 40, 60, 80, 100, 120};
@@ -384,6 +413,9 @@ void pop_process_trobs(uint8_t cur_room)
case TILE_GATE:
animate_door(&mod[tp], &type);
break;
case TILE_LEVELDOOR:
animate_leveldoor(&mod[tp], &type);
break;
case TILE_TORCH:
case TILE_TORCH_DEBRIS:
/* animate_torch (seg007:03C1): кадр пламени; анимация вечная —
@@ -439,6 +471,14 @@ void pop_process_trobs(uint8_t cur_room)
* его уже никто не положит: ставим отложенный редрой. */
if (type < 0) { spike_rest[tp] = 1; rest_pending++; }
}
if (room == cur_room && code == TILE_LEVELDOOR) {
/* Створка едет каждый кадр — перерисовываем ПРАВУЮ половину (там
* её рисует draw_tile_anim_right) С ЗАПЕЧКОЙ в ОЗУ-копию: иначе
* kid_heal вернул бы из фона закрытую створку. Куски двери
* непрозрачны, поэтому wipe не нужен. */
uint8_t trow = tp / 10, tcol = tp % 10;
if (tcol + 1 < 10) pop_leveldoor_redraw(trow, tcol + 1);
}
if (room == cur_room && code == TILE_SWORD) {
/* МЕЧ — редрой только на смене видимого кадра (блеск = modif==1):
* спрайт запечён в фон (draw_tile), поэтому перерисовываем тайл