roomtest: fore-окклюзия пола/стены над Kid (порт redraw_at_char/char2)
Kid — высокий спрайт: голова/руки торчат в ряд выше опорного, floor/wall там должны перекрывать его. Сверено с SDLPoP (seg003 redraw_at_char2 + seg008 draw_tile_fore/draw_other_overlay/draw_floor_overlay): - fore_tile (draw_tile_fore): стена рисует и WALL_FRAM_BOTTOM (нижняя грань-решётка), не только MAIN — руки при прыжке в потолок [2,7]->[1,7] уходят за стену; - диапазон рядов форсит включение ряда над опорным (y_to_row верха спрайта мог схлопнуться из-за +60-сдвига); - other_overlay_tile (draw_other_overlay): на КРОМКЕ пола (сосед слева пуст) перерисовать весь тайл поверх Kid — но ТОЛЬКО в позах захвата (78-79), виса (action 2/6), полёта (3/4), старта падения (bumped 102-106) и начала подъёма (135/136, до SEQ_UP на 141 Kid ещё в ряду ПОД полом). Гейтинг как в redraw_at_char2 — при стоянии/беге ложной окклюзии нет; - отладочный стоп-кадр: '1' заморозить / '2' продолжить (для разбора поз). Проверено в MAME (пользователь): прыжок-в-потолок, короткий прыжок, спрыгивание, подъём на [0,3] — окклюзия корректна. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -420,12 +420,18 @@ static void fore_tile(int row, int col) /* передний слой одно
|
||||
const piece *t = &tile_table[code];
|
||||
int x = COL_XH[col] * 8;
|
||||
int dmy = 63 * row + 62;
|
||||
if (code == 20) { /* стена: основная грань (foretable, */
|
||||
uint8_t wmod = wall_modifier(row, col); /* draw_tile_fore seg008:690) — */
|
||||
wall_b(WALL_FRAM_MAIN[wmod], x, dmy); /* перекрывает Kid как передний */
|
||||
int dby = dmy + 3; /* = 63*row+65 (draw_tile_bottom) */
|
||||
if (code == 20) { /* стена: ОБЕ грани перекрывают Kid */
|
||||
uint8_t wmod = wall_modifier(row, col);
|
||||
wall_b(WALL_FRAM_BOTTOM[wmod], x, dby); /* нижняя грань-решётка (draw_tile_bottom): */
|
||||
wall_pattern(row, col, 0); /* перекрывает голову/руки в НИЖНЕЙ части ячейки */
|
||||
wall_b(WALL_FRAM_MAIN[wmod], x, dmy); /* основная грань (draw_tile_fore) */
|
||||
wall_pattern(row, col, 1);
|
||||
} else if (t->fore_id) {
|
||||
fore_b(t->fore_id, t->fore_x * 8 + x, t->fore_y + dmy);
|
||||
} else {
|
||||
if (t->bottom_id) /* передняя кромка пола (draw_tile_bottom) */
|
||||
env_b(t->bottom_id, x, dby);
|
||||
if (t->fore_id) /* передние объекты: колонны/ворота/щебень */
|
||||
fore_b(t->fore_id, t->fore_x * 8 + x, t->fore_y + dmy);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -451,8 +457,21 @@ static void climb_overlay_tile(int row, int col, uint8_t fidx)
|
||||
if (t->bottom_id) env_b(t->bottom_id, x, dby); /* draw_tile_bottom */
|
||||
}
|
||||
|
||||
/* draw_other_overlay (seg008:1492): для поз виса/прыжка/падения/захвата на
|
||||
* КРОМКЕ (сосед слева пуст, либо тайл через один слева пуст) — перерисовать
|
||||
* ВЕСЬ тайл поверх Kid. Тело пола перекрывает висящего/прыгающего/падающего
|
||||
* ПОД ним. Срабатывает только в этих позах (см. redraw_at_char2 ниже) —
|
||||
* поэтому при стоянии/залезании ложной окклюзии нет. */
|
||||
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))
|
||||
draw_tile(row, col);
|
||||
}
|
||||
|
||||
void pop_fore_over_kid(int obj_x, int obj_y, uint16_t w, uint16_t h,
|
||||
int8_t dir, uint8_t frame)
|
||||
int8_t dir, uint8_t frame, uint8_t action)
|
||||
{
|
||||
int wh = (int)((w + 1) >> 1); /* char_width_half */
|
||||
int xl = obj_x / 2 + 58; /* char_x_left (58-база) */
|
||||
@@ -464,6 +483,12 @@ void pop_fore_over_kid(int obj_x, int obj_y, uint16_t w, uint16_t h,
|
||||
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;
|
||||
/* Голова/руки почти всегда торчат в ряд НАД опорным (Kid выше тайла).
|
||||
* y_to_row(верх спрайта) из-за +60-сдвига может схлопнуться в опорный
|
||||
* ряд (rT==rB) — тогда ряд над ним не попадёт в перебор и его окклюдер
|
||||
* (нижняя грань стены / кромка пола) не перерисуется поверх Kid. Форсим
|
||||
* включение ряда rB-1. */
|
||||
if (rB > 0 && rT >= rB) rT = rB - 1;
|
||||
gfx_set_bank(GFX_BANK_SPRITE); /* видео-ОЗУ, heal восстановит */
|
||||
for (r = rT; r <= rB; r++)
|
||||
for (c = cL; c <= cR; c++)
|
||||
@@ -473,6 +498,24 @@ void pop_fore_over_kid(int obj_x, int obj_y, uint16_t w, uint16_t h,
|
||||
for (r = rT; r <= rB; r++)
|
||||
for (c = cL; c <= cR; c++)
|
||||
climb_overlay_tile(r, c, fidx);
|
||||
} else {
|
||||
/* redraw_at_char2 (seg003:449) — путь set_redraw2/draw_other_overlay:
|
||||
* тело пола на кромке перекрывает Kid в позах захвата (78-79), виса
|
||||
* (action 2/6), полёта (3/4) и старта падения (bumped 102-106).
|
||||
* Верхний ряд — всегда; опорный — кроме action 2 (hang_climb). */
|
||||
uint8_t do_ov = 0;
|
||||
if (frame >= 78 && frame < 80) do_ov = 1; /* захват */
|
||||
else if (action == 2 || action == 3 || action == 4 || action == 6) do_ov = 1;
|
||||
else if (action == 5 && frame >= 102 && frame <= 106) do_ov = 1;
|
||||
else if (frame == 135 || frame == 136) do_ov = 1; /* начало подъёма (SEQ_UP */
|
||||
/* на 141 — до него Kid ещё */
|
||||
/* в ряду 1 ПОД полом [0,3]) */
|
||||
if (do_ov) {
|
||||
for (c = cR; c >= cL; c--) {
|
||||
if (action != 2) other_overlay_tile(rB, c); /* опорный ряд */
|
||||
if (rT != rB) other_overlay_tile(rT, c); /* верхний ряд */
|
||||
}
|
||||
}
|
||||
}
|
||||
gfx_set_bank(GFX_BANK_NORMAL);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user