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
+39
View File
@@ -464,6 +464,32 @@ static uint8_t get_loose_frame(uint8_t m)
return m;
}
/* draw_leveldoor (seg008:1D29) — дверь уровня. Рисуется при обработке
* ПРАВОЙ половины (tile_left = 0x10), все куски со сдвигом +8px (xh+1):
* 99 низ лестницы (всегда),
* 144 марш лестницы за створкой (когда створка приподнята, modif != 0),
* 33 слайс створки — повторяется вниз с шагом 4px, пока не дойдёт до
* y = ybottom modif: modif 0 = закрыто (створка на всю высоту),
* 43 = открыто (остаётся только верхняя кромка),
* 34 верх коробки двери.
* Куски непрозрачные (blitters_0_no_transp) — как в оригинале. */
static void draw_leveldoor(uint8_t modif, int xh, int dmy)
{
int x = (xh + 1) * 8;
int ybottom = dmy - 13;
int ylo = ybottom - (int)(modif & 3) - 48; /* leveldoor_ybottom */
int y = ybottom - (int)modif;
env_b(99, x, ybottom);
if (modif)
env_b(144, x, ybottom - 4); /* лестница (комната ≠ стартовой) */
for (;;) {
env_b(33, x, ylo);
if (y > ylo) ylo += 4;
else break;
}
env_b(34, x, dmy - 64);
}
/* ---- draw_tile (seg008.c:155) — одна клетка ------------------------ */
static void draw_tile(int row, int col)
{
@@ -539,6 +565,8 @@ static void draw_tile(int row, int col)
uint8_t sf = (lmod & 0x80) ? 5 : lmod;
if (sf < 10 && SPIKES_FRAM_RIGHT[sf])
env_b(SPIKES_FRAM_RIGHT[sf], x, dmy - 7);
} else if (lcode == 16) { /* дверь уровня */
draw_leveldoor(lmod, xh, dmy);
}
/* Пламя факела (seg008:560, chtab_1 id modifier+1) в фон НЕ запекаем:
* оно анимируется каждый кадр, а heal вернул бы запечённый кадр из-под
@@ -769,6 +797,17 @@ void pop_floor_bake(int row, int col)
void pop_button_redraw(int row, int col) { pop_floor_bake(row, col); }
/* Перерисовать ПРАВУЮ половину двери уровня (в её ячейке рисуется створка,
* см. draw_leveldoor) на back-странице С ЗАПЕЧКОЙ в ОЗУ-копию: створка едет,
* а heal обязан возвращать её ТЕКУЩЕЕ положение, а не запечённое закрытое.
* Куски двери непрозрачные — wipe не нужен. */
void pop_leveldoor_redraw(int row, int col)
{
gfx_set_bank(GFX_BANK_TRANSPARENT);
draw_tile(row, col);
gfx_set_bank(GFX_BANK_NORMAL);
}
/* Запечь ПУСТОТУ на месте упавшего loose (текущая страница). Порт
* redraw_at_cur_mob (seg007:132C): перерисовать сам тайл (теперь empty) И
* тайл СПРАВА (его левая грань зависит от нашего кода: пока был loose —