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];
|
const piece *t = &tile_table[code];
|
||||||
int x = COL_XH[col] * 8;
|
int x = COL_XH[col] * 8;
|
||||||
int dmy = 63 * row + 62;
|
int dmy = 63 * row + 62;
|
||||||
if (code == 20) { /* стена: основная грань (foretable, */
|
int dby = dmy + 3; /* = 63*row+65 (draw_tile_bottom) */
|
||||||
uint8_t wmod = wall_modifier(row, col); /* draw_tile_fore seg008:690) — */
|
if (code == 20) { /* стена: ОБЕ грани перекрывают Kid */
|
||||||
wall_b(WALL_FRAM_MAIN[wmod], x, dmy); /* перекрывает 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);
|
wall_pattern(row, col, 1);
|
||||||
} else if (t->fore_id) {
|
} else {
|
||||||
fore_b(t->fore_id, t->fore_x * 8 + x, t->fore_y + dmy);
|
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 */
|
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,
|
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 wh = (int)((w + 1) >> 1); /* char_width_half */
|
||||||
int xl = obj_x / 2 + 58; /* char_x_left (58-база) */
|
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;
|
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;
|
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;
|
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 восстановит */
|
gfx_set_bank(GFX_BANK_SPRITE); /* видео-ОЗУ, heal восстановит */
|
||||||
for (r = rT; r <= rB; r++)
|
for (r = rT; r <= rB; r++)
|
||||||
for (c = cL; c <= cR; c++)
|
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 (r = rT; r <= rB; r++)
|
||||||
for (c = cL; c <= cR; c++)
|
for (c = cL; c <= cR; c++)
|
||||||
climb_overlay_tile(r, c, fidx);
|
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);
|
gfx_set_bank(GFX_BANK_NORMAL);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,6 @@ void pop_room_draw(uint8_t room_num,
|
|||||||
* спрайта, w/h — размер кадра, dir — направление Kid (<0 влево). Метрики
|
* спрайта, w/h — размер кадра, dir — направление Kid (<0 влево). Метрики
|
||||||
* берутся из pop_kid (kid_fp_*). См. redraw_at_char/set_char_collision. */
|
* берутся из pop_kid (kid_fp_*). См. redraw_at_char/set_char_collision. */
|
||||||
void pop_fore_over_kid(int obj_x, int obj_y, uint16_t w, uint16_t h,
|
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);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ int main(void)
|
|||||||
/* Дабл-буфер: front — видимая страница, back — куда рисуем. dbuf=1
|
/* Дабл-буфер: front — видимая страница, back — куда рисуем. dbuf=1
|
||||||
* по умолчанию (без мерцания); SPACE переключает в однобуфер для
|
* по умолчанию (без мерцания); SPACE переключает в однобуфер для
|
||||||
* отладки багов рисования (edge по sp_prev, чтоб не дёргать). */
|
* отладки багов рисования (edge по sp_prev, чтоб не дёргать). */
|
||||||
uint8_t pg, front = 0, back, dbuf = 1, sp_prev = 0;
|
uint8_t pg, front = 0, back, dbuf = 1, sp_prev = 0, frozen = 0;
|
||||||
|
|
||||||
if (pop_bg_load() != 0) { /* атласы — ДО initgraph */
|
if (pop_bg_load() != 0) { /* атласы — ДО initgraph */
|
||||||
puts("pop_bg_load failed");
|
puts("pop_bg_load failed");
|
||||||
@@ -58,7 +58,8 @@ int main(void)
|
|||||||
kid_init(SEQ_STAND, 1, 1, 0);
|
kid_init(SEQ_STAND, 1, 1, 0);
|
||||||
kid_draw();
|
kid_draw();
|
||||||
pop_fore_over_kid(kid_fp_obj_x(), kid_fp_obj_y(),
|
pop_fore_over_kid(kid_fp_obj_x(), kid_fp_obj_y(),
|
||||||
kid_fp_width(), kid_fp_height(), Kid.direction, Kid.frame);
|
kid_fp_width(), kid_fp_height(),
|
||||||
|
Kid.direction, Kid.frame, Kid.action);
|
||||||
|
|
||||||
if (pop_ctrl_init() != 0) { /* raw-канал клавиатуры (забирает ввод у DSS) */
|
if (pop_ctrl_init() != 0) { /* raw-канал клавиатуры (забирает ввод у DSS) */
|
||||||
closegraph();
|
closegraph();
|
||||||
@@ -79,6 +80,16 @@ int main(void)
|
|||||||
}
|
}
|
||||||
sp_prev = sp;
|
sp_prev = sp;
|
||||||
|
|
||||||
|
/* Отладочный стоп-кадр: '1' (PS/2 0x16) — заморозить, '2' (0x1E) —
|
||||||
|
* продолжить. В заморозке пропускаем весь tick/draw/flip: картинка
|
||||||
|
* стоит, можно спокойно разбирать позу Kid и окклюзию. */
|
||||||
|
if (kbd_raw_down(0x16)) frozen = 1;
|
||||||
|
if (kbd_raw_down(0x1E)) frozen = 0;
|
||||||
|
if (frozen) {
|
||||||
|
gfx_wait_vsync();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* Рисуем в СКРЫТУЮ страницу (при dbuf); в однобуфере — в 0. */
|
/* Рисуем в СКРЫТУЮ страницу (при dbuf); в однобуфере — в 0. */
|
||||||
back = dbuf ? (uint8_t)(front ^ 1) : 0;
|
back = dbuf ? (uint8_t)(front ^ 1) : 0;
|
||||||
gfx_set_draw_page(back);
|
gfx_set_draw_page(back);
|
||||||
@@ -93,7 +104,8 @@ int main(void)
|
|||||||
}
|
}
|
||||||
kid_draw(); /* нарисовать новый кадр */
|
kid_draw(); /* нарисовать новый кадр */
|
||||||
pop_fore_over_kid(kid_fp_obj_x(), kid_fp_obj_y(),
|
pop_fore_over_kid(kid_fp_obj_x(), kid_fp_obj_y(),
|
||||||
kid_fp_width(), kid_fp_height(), Kid.direction, Kid.frame);
|
kid_fp_width(), kid_fp_height(),
|
||||||
|
Kid.direction, Kid.frame, Kid.action);
|
||||||
|
|
||||||
/* Пейсинг 3 кадра, затем tear-free флип на vblank: draw уже
|
/* Пейсинг 3 кадра, затем tear-free флип на vblank: draw уже
|
||||||
* сделан (скрытая страница), wait_vsync ловит начало кадра,
|
* сделан (скрытая страница), wait_vsync ловит начало кадра,
|
||||||
|
|||||||
Reference in New Issue
Block a user