From c4dd2c7a873c9f6e47428cb090c20965a2a2368f Mon Sep 17 00:00:00 2001 From: Alexander Petrov Date: Wed, 12 Aug 2026 22:39:55 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A4=D0=B8=D0=BA=D1=81=20=D0=BF=D0=B5=D1=80?= =?UTF-8?q?=D0=B5=D0=B2=D0=BE=D1=80=D0=BE=D1=82=D0=B0:=20=D0=BE=D1=82?= =?UTF-8?q?=D1=81=D0=B5=D0=B2=20=D1=82=D0=B0=D0=B9=D0=BB=D0=BE=D0=B2=20?= =?UTF-8?q?=D0=BF=D0=BE=20fore-=D0=BE=D0=BA=D0=BD=D1=83=20=E2=80=94=20?= =?UTF-8?q?=D0=B2=20=D0=9B=D0=9E=D0=93=D0=98=D0=A7=D0=95=D0=A1=D0=9A=D0=98?= =?UTF-8?q?=D0=A5=20=D0=BA=D0=BE=D0=BE=D1=80=D0=B4=D0=B8=D0=BD=D0=B0=D1=82?= =?UTF-8?q?=D0=B0=D1=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Симптом (нашёл пользователь, ур. 9): в перевёрнутом виде Кид рисуется ПЕРЕД передней колонной — передние грани его больше не перекрывают. Причина: окно fore-клипа задаётся прямоугольником уже перевёрнутого спрайта, то есть в ЭКРАННЫХ координатах, а весь отсев «задевает ли ТАЙЛ окно» считает позицию тайла из его РЯДА (63*row + …) — величину логическую, от переворота не зависящую. Сравнивались разные системы координат, и выбрасывались ровно те тайлы, что должны лечь поверх персонажа. Заведена вторая пара границ того же окна — pop_t_fclip_ly0/ly1 (логические, ставятся в pop_fore_set_clip). По ней теперь идут ВСЕ отсевы по тайлам: tile_in_fclip, грубый отсев в pop_blit_b, wp_vis, wpp_fill и отсев кладки в pop_wall_b, а также выбор диапазона рядов в pop_fore_over_char. Экранная пара осталась там, где режется сам блит (он работает с уже перевёрнутым прямоугольником). Проверено в MAME: колонна снова перекрывает перевёрнутого Кида. tests-host 6/6. --- applications/PoP/roomtest/pop_bg.c | 23 ++++++++++++++--------- applications/PoP/roomtest/pop_tile.c | 18 ++++++++++++++++-- applications/PoP/roomtest/pop_tile.h | 5 +++++ 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/applications/PoP/roomtest/pop_bg.c b/applications/PoP/roomtest/pop_bg.c index 893a567..a7939ed 100644 --- a/applications/PoP/roomtest/pop_bg.c +++ b/applications/PoP/roomtest/pop_bg.c @@ -297,13 +297,15 @@ static void wall_rnd_palace(int row, int col) } } -/* Прямоугольник [x, x+w) x [ytop, ybot] (ЭКРАННЫЕ) задевает окно fore-клипа? - * Клипа нет — задевает всегда. */ +/* Прямоугольник [x, x+w) x [ytop, ybot] задевает окно fore-клипа? Клипа + * нет — задевает всегда. Координаты сюда приходят посчитанными ИЗ РЯДА + * (63*row + …), то есть логические — значит и рамка нужна логическая + * (pop_tile.h, пара fclip_l*): переворот применяется позже, при блите. */ static uint8_t wp_vis(int x, int w, int ytop, int ybot) { if (!pop_t_fclip_on) return 1; return (uint8_t)(x < pop_t_fclip_x1 && x + w > pop_t_fclip_x0 && - ytop < pop_t_fclip_y1 && ybot >= pop_t_fclip_y0); + ytop < pop_t_fclip_ly1 && ybot >= pop_t_fclip_ly0); } /* Декаль кладки: ybot — БЕЗ POP_YOFF (как ждёт pop_wall_b), w/h — реальный @@ -331,9 +333,9 @@ static void wpp_fill(int x, int ytop, int w, int h, uint8_t colour) int x2 = x + w - 1, y2 = ytop + h - 1; if (pop_t_fclip_on) { if (x < pop_t_fclip_x0) x = pop_t_fclip_x0; - if (ytop < pop_t_fclip_y0) ytop = pop_t_fclip_y0; + if (ytop < pop_t_fclip_ly0) ytop = pop_t_fclip_ly0; if (x2 >= pop_t_fclip_x1) x2 = pop_t_fclip_x1 - 1; - if (y2 >= pop_t_fclip_y1) y2 = pop_t_fclip_y1 - 1; + if (y2 >= pop_t_fclip_ly1) y2 = pop_t_fclip_ly1 - 1; /* клип ДО переворота */ } if (pop_t_clip_top && ytop < pop_t_clip_top) ytop = pop_t_clip_top; if (x < 0) x = 0; @@ -374,7 +376,7 @@ static void wall_pattern_palace(int row, int col, int which_part) if (pop_t_fclip_on) { int x0 = xh * 8; if (x0 >= pop_t_fclip_x1 || x0 + 32 <= pop_t_fclip_x0 || - dmy - 59 >= pop_t_fclip_y1 || dby + 1 <= pop_t_fclip_y0) + dmy - 59 >= pop_t_fclip_ly1 || dby + 1 <= pop_t_fclip_ly0) return; } /* Цвета лежат по рядам 0..2; полоса у потолка (row −1) — это ряд 2 @@ -620,8 +622,10 @@ static uint8_t tile_in_fclip(int row, int col) if (!pop_t_fclip_on) return 1; x0 = POP_COL_XH[col] * 8; y0 = POP_YOFF + 63 * row; + /* По ЛОГИЧЕСКОЙ рамке: y0 тайла считается из его ряда и переворотом не + * меняется (см. pop_tile.h про пару fclip_l*). */ return (uint8_t)(x0 < pop_t_fclip_x1 && x0 + 40 > pop_t_fclip_x0 && - y0 - 8 < pop_t_fclip_y1 && y0 + 70 > pop_t_fclip_y0); + y0 - 8 < pop_t_fclip_ly1 && y0 + 70 > pop_t_fclip_ly0); } static void fore_tile(int row, int col) /* передний слой одного тайла */ @@ -891,8 +895,9 @@ void pop_fore_over_char(const pop_char_t *ch, int obj_x, int obj_y, * достаточно сравнить с границами полос. * 63r > y0 − POP_YOFF − 70 и 63r < y1 − POP_YOFF + 8 */ { - int a = pop_t_fclip_y0 - POP_YOFF - 70; - int b = pop_t_fclip_y1 - POP_YOFF + 8; + /* Ряды — величина ЛОГИЧЕСКАЯ, поэтому по логической рамке. */ + int a = pop_t_fclip_ly0 - POP_YOFF - 70; + int b = pop_t_fclip_ly1 - POP_YOFF + 8; lo = a < 0 ? 0 : (a < 63 ? 1 : 2); hi = b > 126 ? 2 : (b > 63 ? 1 : 0); if (a < 126 && b > 0 && lo <= hi) { diff --git a/applications/PoP/roomtest/pop_tile.c b/applications/PoP/roomtest/pop_tile.c index 7db8baf..a22c6dc 100644 --- a/applications/PoP/roomtest/pop_tile.c +++ b/applications/PoP/roomtest/pop_tile.c @@ -34,6 +34,14 @@ pop_rnd_t pop_t_seed; int pop_t_clip_top; int pop_t_fclip_x0, pop_t_fclip_y0, pop_t_fclip_x1, pop_t_fclip_y1; +/* ТО ЖЕ ОКНО В ЛОГИЧЕСКИХ (неперевёрнутых) координатах. Экранная пара нужна + * для клипа самого блита — он режет уже перевёрнутый прямоугольник; а вот + * ОТСЕВ ТАЙЛОВ идёт по позиции тайла в комнате (63*row + …), и она от + * переворота не зависит. Пока пара была одна, при pop_upside отсев сравнивал + * логический y тайла с зеркальным окном и выбрасывал именно те тайлы, что + * должны лечь ПОВЕРХ персонажа: передняя грань колонны переставала рисоваться + * и Кид оказывался перед ней (найдено пользователем на уровне 9). */ +int pop_t_fclip_ly0, pop_t_fclip_ly1; uint8_t pop_t_fclip_on; uint8_t pop_t_bake_rest; @@ -332,8 +340,8 @@ void pop_blit_b(atlas_t *a, uint8_t idx, int x, int ybottom) * atlas_image, ни за map/unmap. */ if (pop_t_fclip_on && (x >= pop_t_fclip_x1 || x + 64 <= pop_t_fclip_x0 || - ybottom + POP_YOFF + 1 <= pop_t_fclip_y0 || - ybottom + POP_YOFF - 64 >= pop_t_fclip_y1)) + ybottom + POP_YOFF + 1 <= pop_t_fclip_ly0 || + ybottom + POP_YOFF - 64 >= pop_t_fclip_ly1)) return; img = (const uint8_t *)atlas_image(a, idx); gfx_w0_map(a->page); @@ -476,6 +484,12 @@ void pop_fore_set_clip(int x, int y, int w, int h) { pop_t_fclip_x0 = x; pop_t_fclip_y0 = y; pop_t_fclip_x1 = x + w; pop_t_fclip_y1 = y + h; + if (pop_upside) { /* вернуть окно в неперевёрнутый вид */ + pop_t_fclip_ly0 = 2 * POP_YOFF + POP_PLAYFIELD_H - (y + h); + pop_t_fclip_ly1 = 2 * POP_YOFF + POP_PLAYFIELD_H - y; + } else { + pop_t_fclip_ly0 = y; pop_t_fclip_ly1 = y + h; + } } /* Ряд 0 комнаты СНИЗУ (fg-коды) — нужен draw_tile_topright/floorright, когда diff --git a/applications/PoP/roomtest/pop_tile.h b/applications/PoP/roomtest/pop_tile.h index 6fe509a..bb0450c 100644 --- a/applications/PoP/roomtest/pop_tile.h +++ b/applications/PoP/roomtest/pop_tile.h @@ -70,6 +70,11 @@ extern int pop_t_clip_top; * кадра при бюджете 430 000. С окном большинство кусков отсекается целиком, * остальные режутся до пересечения. */ extern int pop_t_fclip_x0, pop_t_fclip_y0, pop_t_fclip_x1, pop_t_fclip_y1; +/* Та же рамка в ЛОГИЧЕСКИХ координатах (без переворота). Всё, что решает + * «задевает ли ТАЙЛ окно», обязано сравнивать по ней: позиция тайла в + * комнате от переворота не зависит. Экранная пара — только для клипа + * блита, который режет уже перевёрнутый прямоугольник. */ +extern int pop_t_fclip_ly0, pop_t_fclip_ly1; extern uint8_t pop_t_fclip_on; /* ---- Таблица тайлов (piece, seg008.c:27) ---------------------------- */