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:
@@ -493,6 +493,10 @@ void pop_loose_mob_spawn(int row, int col)
|
||||
#define MOB_X0(mx) ((mx) - 4)
|
||||
#define MOB_W 64 /* mob_x-4 .. mob_x+59 (крышка +57 с запасом 2px) */
|
||||
|
||||
/* Остановить падающий кусок (при смене комнаты — состояние per-tile не
|
||||
* должно утечь в новую комнату). */
|
||||
void pop_loose_mob_reset(void) { mob_active = 0; }
|
||||
|
||||
void pop_loose_mob_tick(void)
|
||||
{
|
||||
if (!mob_active) return;
|
||||
@@ -586,7 +590,7 @@ static int8_t col_from_x(int xpos) /* get_tile_div_mod: колонка (
|
||||
return (int8_t)xh;
|
||||
}
|
||||
|
||||
static int8_t y_to_row(int y) /* y_to_row_mod4 (TILE_SIZEY=63) */
|
||||
static int8_t y_to_row(int y) /* y_to_row_mod4 (seg006, TILE_SIZEY=63) */
|
||||
{
|
||||
return (int8_t)((y + 60) / 63 % 4 - 1);
|
||||
}
|
||||
@@ -642,8 +646,16 @@ static void climb_overlay_tile(int row, int col, uint8_t fidx)
|
||||
static void other_overlay_tile(int row, int col)
|
||||
{
|
||||
uint8_t code = tile_code(row, col);
|
||||
uint8_t left = tile_code(row, col - 1);
|
||||
if (left == 0 || (code != 0 && col > 0 && tile_code(row, col - 2) == 0))
|
||||
uint8_t left;
|
||||
/* Пустой тайл НЕ окклюдирует: у него нет тела пола/стены, а draw_tile для
|
||||
* него рисует лишь ФОНОВУЮ сетку (BLUELINE «силуэт кладки» — правая грань
|
||||
* пустого соседа). В оригинале она уходит в y-сортируемый midtable и
|
||||
* ложится ПОЗАДИ Kid; у нас draw_tile кладёт её прямо поверх → сетка на
|
||||
* висящем/падающем Kid. Фон запечён один раз в pop_room_draw — над
|
||||
* спрайтом его перерисовывать не нужно. */
|
||||
if (code == 0) return;
|
||||
left = tile_code(row, col - 1);
|
||||
if (left == 0 || (col > 0 && tile_code(row, col - 2) == 0))
|
||||
draw_tile(row, col);
|
||||
}
|
||||
|
||||
@@ -658,8 +670,21 @@ void pop_fore_over_kid(int obj_x, int obj_y, uint16_t w, uint16_t h,
|
||||
xr = xl + wh;
|
||||
cL = col_from_x(xl); if (cL < 0) cL = 0; else if (cL > 9) cL = 9;
|
||||
cR = col_from_x(xr); if (cR < 0) cR = 0; else if (cR > 9) cR = 9;
|
||||
rB = y_to_row(obj_y); if (rB < 0) rB = 0; else if (rB > 2) rB = 2;
|
||||
rT = y_to_row(obj_y - (int)h + 1); if (rT < 0) rT = 0; else if (rT > 2) rT = 2;
|
||||
/* Порт set_char_collision (seg006:0723): нижний ряд = y_to_row_mod4(obj_y),
|
||||
* причём обёртка -1 (Kid НИЖЕ комнаты — climbdown/провал, obj_y в полосе
|
||||
* «ряд 3») трактуется как ряд 3, НЕ ряд 0. Верхний ряд считается от
|
||||
* char_top_y с ресетом в 0, если весь спрайт ниже комнаты (>=192). */
|
||||
{
|
||||
int top_y = obj_y - (int)h + 1;
|
||||
if (top_y >= 192) top_y = 0;
|
||||
rT = y_to_row(top_y);
|
||||
rB = y_to_row(obj_y);
|
||||
if (rB == -1) rB = 3; /* обёртка → ряд 3 (ниже комнаты) */
|
||||
}
|
||||
/* single-room roomtest: ряд 3 (комната снизу) в этом виде не рисуется →
|
||||
* окклюдер спереди = ряд 2 (передняя грань пола, за которой нога). */
|
||||
if (rB < 0) rB = 0; else if (rB > 2) rB = 2;
|
||||
if (rT < 0) rT = 0; else if (rT > 2) rT = 2;
|
||||
/* Голова/руки почти всегда торчат в ряд НАД опорным (Kid выше тайла).
|
||||
* y_to_row(верх спрайта) из-за +60-сдвига может схлопнуться в опорный
|
||||
* ряд (rT==rB) — тогда ряд над ним не попадёт в перебор и его окклюдер
|
||||
|
||||
Reference in New Issue
Block a user