PoP roomtest: clip_char (верхняя обрезка спрайта) + подстановка нажатой кнопки
Спуск Кида с кнопки (room8, кромка (0,6)) рисовался неверно: Кид просвечивал в щель между кнопкой и ближним столбом, а ближняя рука была срезана до одного оторванного пикселя. Две независимые причины. 1. Не был портирован clip_char() (seg006:1749) — оригинал перед add_objtable обрезает спрайт персонажа сверху по y_clip[curr_row+1], когда тайл над головой стена или пол. Порт: pop_clip_char_top() (pop_map.c, метрики по set_char_collision) + новый примитив gfx_blit_cols_part() в libbgi (блит column-major с пропуском skip верхних строк; обрезка сверху бесплатна — колонка непрерывна в ОЗУ, сдвигается только старт). gfx_blit_cols стал тонкой обёрткой над ним. kid_heal чистит уже ОБРЕЗАННЫЙ прямоугольник, иначе стирается кромка пола над срезом. 2. climb_overlay_tile (порт draw_floor_overlay, seg008:1E3A) выбирал ветку по СЫРОМУ коду тайла, а get_tile_to_draw (seg008:240) подменяет нажатую кнопку на floor/stuck. Тайл-кнопка не проходил тест floor → уходил в draw_other_overlay, который кладёт поверх Кида ВЕСЬ тайл вместо узкой кромки floor_left_overlay[frame-137]. Фикс — tile_code_drawn(): одна подстановка на все слои (fore_only_tile/overlay_mid_tile перестали её дублировать, W3 −293 Б). Проверено покадрово в MAME (шаг gv + снимок): кадры спуска 148..138 чистые, после приземления на кнопке мусора нет. Заодно: gfx_heal_noclip() (пара к gfx_blit_noclip; heal 11658 -> 8982 тактов) и rest_pending в pop_trob — холостой проход по 30 тайлам только когда есть отложенные редрои пик/кнопок (pop_process_trobs 89-111К -> 70-92К тактов). START_ROOM временно = 8 (отладка спуска с кнопки), вернуть на 6/старт уровня. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
#include <sprite.h>
|
||||
#include "pop_kid.h"
|
||||
#include "pop_bg.h" /* POP_YOFF — вертикальное центрирование */
|
||||
#include "pop_map.h" /* pop_clip_char_top (clip_char) */
|
||||
#include "kid_data.h"
|
||||
|
||||
kid_t Kid;
|
||||
@@ -292,18 +293,32 @@ void kid_draw(void)
|
||||
if (w && h) {
|
||||
uint8_t flip = (Kid.direction >= 0); /* dir_0_right -> зеркало */
|
||||
int bx = obj_x + KID_XOFF;
|
||||
int skip = 0; /* строк спрайта срезано сверху */
|
||||
int ct;
|
||||
if (flip)
|
||||
bx -= (int)w; /* seg008: xpos -= image->w */
|
||||
top = obj_y - (int)h + 1 + KID_YOFF;
|
||||
uint8_t dp = gfx_get_draw_page(); /* в какую страницу рисуем */
|
||||
/* clip_char (seg006:1749): тайл над головой = стена/пол → всё выше
|
||||
* линии полосы своего ряда НЕ рисуется. Иначе Kid просвечивает
|
||||
* сквозь щели кладки при спуске/висе. */
|
||||
ct = pop_clip_char_top(kid_fp_x, obj_y, w, h);
|
||||
if (ct > top) {
|
||||
skip = ct - top;
|
||||
if (skip >= (int)h) skip = (int)h; /* обрезан целиком */
|
||||
}
|
||||
gfx_set_bank(GFX_BANK_SPRITE); /* видео-ОЗУ, без теневой копии */
|
||||
gfx_blit_cols(bx, top + POP_YOFF, img, flip); /* +YOFF: центрирование */
|
||||
if (skip < (int)h) /* +YOFF: центрирование */
|
||||
gfx_blit_cols_part(bx, top + skip + POP_YOFF, img, flip, skip, 0);
|
||||
gfx_set_bank(GFX_BANK_NORMAL);
|
||||
/* клип СВОЕГО выхода за поле (падение ниже поля / верхний борт) —
|
||||
* узко, только по прямоугольнику Кида и только при выходе. */
|
||||
pop_clip_sprite(bx, w, top + POP_YOFF, (int)h);
|
||||
kid_lx[dp] = bx; kid_ly[dp] = top;
|
||||
kid_lw[dp] = w; kid_lh[dp] = h; kid_lvalid[dp] = 1;
|
||||
pop_clip_sprite(bx, w, top + skip + POP_YOFF, (int)h - skip);
|
||||
/* heal чистит ТОЛЬКО нарисованное: иначе стирается кромка пола над
|
||||
* срезом (мусор/дыра в кладке на второй странице дабл-буфера). */
|
||||
kid_lx[dp] = bx; kid_ly[dp] = top + skip;
|
||||
kid_lw[dp] = w; kid_lh[dp] = (uint16_t)((int)h - skip);
|
||||
kid_lvalid[dp] = (skip < (int)h);
|
||||
kid_fp_w = w; kid_fp_h = h; /* размер кадра для футпринта fore */
|
||||
}
|
||||
gfx_w0_unmap();
|
||||
|
||||
Reference in New Issue
Block a user