PoP roomtest: плита-потолок, порядок слоёв по SDLPoP, фиксы окклюзии и Y
Фича — плита-ПОТОЛОК (loose ряда 2 комнаты сверху, комн.5 (2,5) над комн.6): - check_press (seg006:1683) портирован целиком: кадры виса 87..99 и подъёма 135..140 «нажимают» тайл, за который Kid держится; кадр 79 — удар снизу (с проверкой action, как в оригинале); стояние — тайл под ним; - ряд −1 в pop_map.get_tile = ряд 2 комнаты сверху (порт find_room_of_tile), состояние тряски/падения — pop_ceil_modif[10]; do_knock(-1) трясёт потолок; - падение: mob переведён на координаты оригинала (y_loose_land/y_something), спавнится в ряду −1, по move_loose находит пол → loose_land: debris + do_knock; heal коридора — по прошлой позиции ДЛЯ КАЖДОЙ страницы; - урон: check_loose_fall_on_kid + fell_on_your_head (seq_52/seq_22, −1 HP) и «брызги» draw_hurt_splash (kid image 218); - колодец наверх: leave_room «вверх» проверяется ПЕРВЫМ (иначе y≈248 при подтягивании ловил check_leave_below и ронял Kid из уровня); - персистентность: общий tile-override (щебень внизу, пустота в комнате сверху) вместо debris-only. Окклюзия — приведена к оригиналу (найдено трассировкой собранного SDLPoP): - draw_tile_right/anim_right/draw_loose кладут спрайты в add_backtable НАПРЯМУЮ, минуя ptr_add_table → правая грань соседа («шахматка» столба 93), blueline и грани loose/пик соседа ВСЕГДА под персонажем. draw_other_overlay поверх Kid даёт только: 42 при левом соседе-поле, base, свои пики, bottom (overlay_mid_tile); - порядок объектов: тайл Kid (set_objtile_at_char) и порядок обхода (ряды 2→0, колонки 0→9), внутри тайла — сортировка по y (sort_curr_objs); то же правило для падающей плиты (pop_loose_mob_draw_over); - fore-слой рисуется ПОСЛЕ оверлеев (foretable после midtable), иначе тёмный скос floor_left_overlay ложился поверх колонны; - fore_tile больше не рисует bottom_id (в оригинале он в backtable) — минус 2..4 блита за кадр; - полоса потолка поверх Kid = draw_tile_bottom(1)+draw_loose(1)+draw_tile_fore (arg_0=1 добавляет в foretable), остальное — под ним; - следы оверлея восстанавливаются на ОБЕИХ страницах (pop_fore_heal). Прочее: - control(): при action bumped/in_freefall управление игнорируется целиком (seg005) — иначе прерванный присед терял dy(1)+dy(1) из medland и Kid навсегда оставался на 2px выше пола; - check_bumped: стена ищется по колонке переднего края (а не curr_col) + гард разворота — Kid больше не проходит сквозь опущенную решётку шва; - pop_floor_bake для смены floor→debris (bake_empty стирал верх стены ряда ниже — чёрный прямоугольник); - в pop_room_redraw_seam_left восстанавливается полоса потолка над решёткой. Проверено в MAME (bridge); эталон — собранный SDLPoP из applications/PoP/SDLPoP. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -58,6 +58,12 @@ void pop_room_set_above(const uint8_t *above_row2_fg, const uint8_t *above_row2_
|
||||
void pop_fore_over_kid(int obj_x, int obj_y, uint16_t w, uint16_t h,
|
||||
int8_t dir, uint8_t frame, uint8_t action);
|
||||
|
||||
/* Восстановить фон там, где в прошлых кадрах рисовался ОВЕРЛЕЙ
|
||||
* (draw_other_overlay/floor_overlay/полоса потолка): он выходит за
|
||||
* прямоугольник Kid, поэтому kid_heal его не убирает — на второй странице
|
||||
* дабл-буфера остаётся след и мерцает. Звать рядом с kid_heal. */
|
||||
void pop_fore_heal(void);
|
||||
|
||||
/* Loose floors — динамическая отрисовка (состояние pop_loose_modif в
|
||||
* pop_map). Звать на ТЕКУЩЕЙ (back) странице из pop_loose_tick.
|
||||
* shake_draw — дрожащий кадр (heal+SPRITE); bake_empty — запечь пустоту
|
||||
@@ -65,6 +71,16 @@ void pop_fore_over_kid(int obj_x, int obj_y, uint16_t w, uint16_t h,
|
||||
void pop_loose_shake_draw(int row, int col);
|
||||
void pop_loose_bake_empty(int row, int col);
|
||||
|
||||
/* Плита-ПОТОЛОК (loose ряда 2 комнаты СВЕРХУ, наш ряд −1): дрожащий кадр в
|
||||
* полосе у потолка / «запечь» пустоту (колодец наверх) после провала.
|
||||
* Состояние — pop_ceil_modif[10] в pop_map. */
|
||||
void pop_ceil_shake_draw(int col);
|
||||
void pop_ceil_bake_empty(int col);
|
||||
|
||||
/* Кусок приземлился (loose_land): 0 = нет, иначе tilepos+1 тайла, на который
|
||||
* он лёг. Ставит pop_loose_mob_tick, разбирает pop_loose_tick (debris+knock). */
|
||||
extern uint8_t pop_loose_landed;
|
||||
|
||||
/* Пики (spike) — перерисовка тайла (row,col) на back-странице по живому
|
||||
* modif (pop_trob). Звать из pop_process_trobs. См. pop_bg.c. */
|
||||
void pop_spike_redraw(int row, int col);
|
||||
@@ -74,9 +90,11 @@ void pop_spike_redraw(int row, int col);
|
||||
* на back-странице, когда сосед слева анимируется. См. pop_bg.c. */
|
||||
void pop_room_redraw_seam_left(void);
|
||||
|
||||
/* Кнопка (opener/closer) — перерисовать тайл (row,col) на back-странице:
|
||||
* нажата/отжата по таймеру связи. Звать из pop_process_trobs. */
|
||||
void pop_button_redraw(int row, int col);
|
||||
/* Перерисовать ПОЛ тайла (row,col) + правую грань в соседе на back-странице
|
||||
* (wipe по площади пола, БЕЗ стены ряда ниже). Для смены тайла на месте:
|
||||
* кнопка нажата/отжата, floor → debris от упавшей плиты. */
|
||||
void pop_floor_bake(int row, int col);
|
||||
void pop_button_redraw(int row, int col); /* = pop_floor_bake (кнопка) */
|
||||
|
||||
/* Падающий кусок loose (mob, seg007 move_loose): спавн при падении тайла
|
||||
* (row,col) и покадровое продвижение+отрисовка на back-странице. tick
|
||||
@@ -85,6 +103,13 @@ void pop_loose_mob_spawn(int row, int col);
|
||||
void pop_loose_mob_tick(void);
|
||||
void pop_loose_mob_reset(void); /* остановить кусок (смена комнаты) */
|
||||
|
||||
/* Кусок НИЖЕ Kid по obj_y → рисуется ПОВЕРХ него (порт sort_curr_objs,
|
||||
* seg008:1561). Звать после kid_draw, перед fore-слоем. */
|
||||
void pop_loose_mob_draw_over(void);
|
||||
|
||||
/* Позиция куска (колонка, y низа) для check_loose_fall_on_kid. 0 — нет. */
|
||||
uint8_t pop_loose_mob_pos(int *col, int *y);
|
||||
|
||||
/* Детектор выхода спрайта за поле: если спрайт [x,w] с ЭКРАННЫМ верхом
|
||||
* sy_top и высотой h заходит ниже поля (статус-полоса/борт) или выше
|
||||
* верхнего борта — взводит внутренний флаг «борта грязные» на 2 кадра.
|
||||
|
||||
Reference in New Issue
Block a user