diff --git a/applications/PoP/roomtest/pop_bg.c b/applications/PoP/roomtest/pop_bg.c index 6945220..ee57edd 100644 --- a/applications/PoP/roomtest/pop_bg.c +++ b/applications/PoP/roomtest/pop_bg.c @@ -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); } diff --git a/applications/PoP/roomtest/pop_bg.h b/applications/PoP/roomtest/pop_bg.h index c335591..4ec6ac5 100644 --- a/applications/PoP/roomtest/pop_bg.h +++ b/applications/PoP/roomtest/pop_bg.h @@ -34,6 +34,6 @@ void pop_room_draw(uint8_t room_num, * спрайта, w/h — размер кадра, dir — направление Kid (<0 влево). Метрики * берутся из 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, - int8_t dir, uint8_t frame); + int8_t dir, uint8_t frame, uint8_t action); #endif diff --git a/applications/PoP/roomtest/roomtest.c b/applications/PoP/roomtest/roomtest.c index 280ec48..a0292b4 100644 --- a/applications/PoP/roomtest/roomtest.c +++ b/applications/PoP/roomtest/roomtest.c @@ -23,7 +23,7 @@ int main(void) /* Дабл-буфер: front — видимая страница, back — куда рисуем. dbuf=1 * по умолчанию (без мерцания); SPACE переключает в однобуфер для * отладки багов рисования (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 */ puts("pop_bg_load failed"); @@ -58,7 +58,8 @@ int main(void) kid_init(SEQ_STAND, 1, 1, 0); kid_draw(); 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) */ closegraph(); @@ -79,6 +80,16 @@ int main(void) } 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. */ back = dbuf ? (uint8_t)(front ^ 1) : 0; gfx_set_draw_page(back); @@ -93,7 +104,8 @@ int main(void) } kid_draw(); /* нарисовать новый кадр */ 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 уже * сделан (скрытая страница), wait_vsync ловит начало кадра,