roomtest: L2 — переход в комнату снизу (провал/спуск) + фиксы окклюзии

При пересечении нижней границы комнаты Kid переходит в комнату links.down,
продолжая падать/спускаться (порт SDLPoP goto_other_room/leave_room).

- pop_map check_leave_below (порт leave_room, seg002): триггер по Kid.y>=211
  (не curr_row) — единый для провала И спуска-зацепа/climbdown; репроекция
  координат в кадр комнаты снизу (y-=189, curr_row=y_to_row_mod4) + сигнал
  pop_fell_out.  Убран прежний преждевременный триггер y>=189 из do_fall
  (из-за него climbdown с curr_row=3 ждал y_land[4]=244 → пролёт через комнату).
- roomtest: enter_room(room) — загрузка комнаты в рабочие массивы + отрисовка
  фона в обе страницы; обработчик pop_fell_out переключает комнату по
  pop_room_link(down) или респавнит (нет комнаты снизу).  cur_room-трекинг.
- pop_loose_reset (pop_map) + pop_loose_mob_reset (pop_bg): сброс loose-состояния
  (индексировано позицией тайла) при смене комнаты — иначе течёт в новую.

Фиксы окклюзии при висе/спуске (сверено с SDLPoP):
- other_overlay_tile: пустой тайл НЕ окклюдирует — draw_tile для него рисует
  лишь фоновую сетку (BLUELINE «силуэт кладки»), которая в оригинале уходит в
  y-сортируемый midtable ПОЗАДИ Kid; у нас клалась поверх.  Пропускаем.
- pop_fore_over_kid: порт set_char_collision (seg006:0723) — char_bottom_row =
  y_to_row_mod4(obj_y), обёртка -1 → ряд 3 (Kid НИЖЕ комнаты при спуске), а не
  ряд 0.  Прежний кламп в 0 давал rT>rB → цикл окклюзии не выполнялся, нога
  рисовалась поверх пола.  single-room: ряд 3 клампится в 2 (передняя грань пола).

Проверено в MAME: провал вниз, спуск-зацеп/climbdown с кромки, окклюзия ноги.
Известно (позже): осколки упавшего loose в комнате снизу (перенос mob),
per-room modified-tile tracking (re-entry восстанавливает исходные тайлы), HP.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-20 20:22:52 +03:00
parent 21f978d441
commit 7f3e32ddd6
5 changed files with 114 additions and 32 deletions
+35 -4
View File
@@ -360,10 +360,9 @@ static void do_fall(void)
land();
else if (Kid.curr_row < 2)
inc_curr_row(); /* следующий ряд ВНУТРИ комнаты */
else
pop_fell_out = 1; /* упал за низ комнаты (нет пола,
комнаты снизу нет) — приложение
сбросит Kid (K-later: переход) */
/* curr_row==2, нет пола: продолжает падать (fall_speed двигает y);
* пересечение нижней границы комнаты ловит check_leave_below (y>=211,
* порт leave_room) — общий путь для провала И спуска-зацепа. */
}
}
@@ -689,6 +688,20 @@ void pop_check_knock(void)
}
}
/* Сброс состояния loose (при смене комнаты): pop_loose_modif/bake/rest
* индексируются позицией тайла и не должны утечь из старой комнаты в новую.
* Плюс останавливает падающий кусок (pop_bg). */
void pop_loose_reset(void)
{
int i;
for (i = 0; i < 30; i++) {
pop_loose_modif[i] = 0;
loose_bake[i] = 0;
loose_rest[i] = 0;
}
pop_loose_mob_reset();
}
/* animate_loose (seg007:0CBA) + перерисовка изменившихся тайлов на ТЕКУЩЕЙ
* (back) странице. Звать из основного цикла ПОСЛЕ set_draw_page(back). */
void pop_loose_tick(void)
@@ -737,6 +750,23 @@ void pop_loose_tick(void)
pop_loose_mob_tick(); /* продвинуть+нарисовать падающий кусок (после тайлов) */
}
/* y_to_row_mod4 (seg006): ряд по y с оборотом mod4 (TILE_SIZEY=63). */
static int8_t y_to_row(int16_t y) { return (int8_t)(((y + 60) / 63) % 4 - 1); }
/* check_leave_below (порт leave_room, seg002: leave_dir=3 при chary>=211):
* Kid пересёк нижнюю границу комнаты (провал в дыру ИЛИ спуск-зацеп/climbdown
* — единый триггер по y). Репроекция в кадр комнаты снизу (goto_other_room
* down: y-=189, curr_row=y_to_row_mod4) + сигнал pop_fell_out — приложение
* решит: переход (links.down) или выпал из уровня (нет комнаты снизу). */
static void check_leave_below(void)
{
if (Kid.y >= 211) {
Kid.y = (uint8_t)(Kid.y - 189);
Kid.curr_row = y_to_row((int16_t)Kid.y);
pop_fell_out = 1;
}
}
void pop_phys_tick(void)
{
if (grab_timer) grab_timer--;
@@ -747,4 +777,5 @@ void pop_phys_tick(void)
check_action();
check_press(); /* seg006: стойка/пробой loose → make_loose_fall */
pop_check_knock(); /* seg003: сотрясение приземления → тряска loose в ряду */
check_leave_below(); /* seg002: y>=211 → переход в комнату снизу */
}