7f3e32ddd6
При пересечении нижней границы комнаты Kid переходит в комнату links.down, продолжая падать/спускаться (порт SDLPoP goto_other_room/leave_room). - pop_map check_leave_below (порт leave_room, seg002): триггер по Kid.y>=211 (не curr_row) — единый для провала И спуска-зацепа/climbdown; репроекция координат в кадр комнаты снизу (y-=189, curr_row=y_to_row_mod4) + сигнал pop_fell_out. Убран прежний преждевременный триггер y>=189 из do_fall (из-за него climbdown с curr_row=3 ждал y_land[4]=244 → пролёт через комнату). - roomtest: enter_room(room) — загрузка комнаты в рабочие массивы + отрисовка фона в обе страницы; обработчик pop_fell_out переключает комнату по pop_room_link(down) или респавнит (нет комнаты снизу). cur_room-трекинг. - pop_loose_reset (pop_map) + pop_loose_mob_reset (pop_bg): сброс loose-состояния (индексировано позицией тайла) при смене комнаты — иначе течёт в новую. Фиксы окклюзии при висе/спуске (сверено с SDLPoP): - other_overlay_tile: пустой тайл НЕ окклюдирует — draw_tile для него рисует лишь фоновую сетку (BLUELINE «силуэт кладки»), которая в оригинале уходит в y-сортируемый midtable ПОЗАДИ Kid; у нас клалась поверх. Пропускаем. - pop_fore_over_kid: порт set_char_collision (seg006:0723) — char_bottom_row = y_to_row_mod4(obj_y), обёртка -1 → ряд 3 (Kid НИЖЕ комнаты при спуске), а не ряд 0. Прежний кламп в 0 давал rT>rB → цикл окклюзии не выполнялся, нога рисовалась поверх пола. single-room: ряд 3 клампится в 2 (передняя грань пола). Проверено в MAME: провал вниз, спуск-зацеп/climbdown с кромки, окклюзия ноги. Известно (позже): осколки упавшего loose в комнате снизу (перенос mob), per-room modified-tile tracking (re-entry восстанавливает исходные тайлы), HP. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
83 lines
5.6 KiB
C
83 lines
5.6 KiB
C
/*
|
||
* pop_bg.h — отрисовка СТАТИЧЕСКОГО фона комнаты PoP композицией слоёв
|
||
* (порт seg008.c draw_tile/wall_pattern, Шаг 3). Рисует прямо в текущую
|
||
* страницу (banked GFX_BANK_TRANSPARENT — в видео-ОЗУ + теневую копию,
|
||
* 0xFF прозрачен), ОДИН раз при входе в комнату.
|
||
*
|
||
* Данные: getimage-спрайты в атласах pop_env0..4/pop_wall/pop_fore
|
||
* (toolchain/pop_pack_bg.py), палитра pop_bg.pal. Прямая адресация
|
||
* id: env[id>>5] idx id&31, wall idx=id, fore idx=id — ноль remap-таблиц.
|
||
*/
|
||
#ifndef POP_BG_H
|
||
#define POP_BG_H
|
||
|
||
#include <stdint.h>
|
||
|
||
/* ---- Вертикальный layout (PoP-экран 320×200 в нашем 320×256) --------- *
|
||
* Игровой экран 200px центрируем по высоте: сдвиг всего рисунка вниз на
|
||
* POP_YOFF = (256-200)/2 = 28px (чёрные борта сверху/снизу). Внутри 200px
|
||
* верхние POP_PLAYFIELD_H = 192 — поле тайлов/спрайтов (комната = 3 ряда),
|
||
* нижние 8 — статус-полоса (жизни/сообщения): тайлы/спрайты туда НЕ лезут.
|
||
* Сдвиг применяется на границе примитивов (blit/heal) — логика рисования
|
||
* остаётся в «room-space» y=0..191. */
|
||
#define POP_YOFF 28
|
||
#define POP_PLAYFIELD_H 192
|
||
/* Экранный y нижней границы поля (ниже — статус-полоса + борт → клип). */
|
||
#define POP_CLIP_BOTTOM (POP_YOFF + POP_PLAYFIELD_H)
|
||
|
||
/* Загрузить 7 атласов фона. Звать ДО initgraph (как poc.c — atlas_load
|
||
* трогает W3; проверенный порядок). Палитру pop_bg.pal грузит ПРИЛОЖЕНИЕ
|
||
* после initgraph (gfx_pal_fload). 0 — OK, -1 — ошибка. */
|
||
int pop_bg_load(void);
|
||
|
||
/* Освободить EMM-страницы атласов. */
|
||
void pop_bg_free(void);
|
||
|
||
/* Нарисовать комнату: fg[30]/bg[30] — foretable-коды/backtable-модификаторы
|
||
* (по строкам, row*10+col). lcol_fg/lcol_bg — 3 тайла правого столбца
|
||
* ЛЕВОЙ соседней комнаты (для границы, напр. решётки ворот), или 0 —
|
||
* тогда левая кромка = стена. room_num — номер комнаты (зерно стен). */
|
||
void pop_room_draw(uint8_t room_num,
|
||
const uint8_t *fg, const uint8_t *bg,
|
||
const uint8_t *lcol_fg, const uint8_t *lcol_bg);
|
||
|
||
/* Задать ряд 0 комнаты СНИЗУ (fg-коды, 10 шт.) — для draw_tile_topright,
|
||
* когда тайл нижнего ряда стал empty (после падения loose): «стена вниз»
|
||
* рисуется по коду room_B(0, col-1). 0 — нет комнаты снизу. */
|
||
void pop_room_set_below(const uint8_t *below_row0_fg);
|
||
|
||
/* Перерисовать передний слой (fore) тайлов футпринта Kid ПОВЕРХ него —
|
||
* звать ПОСЛЕ kid_draw. obj_x — ЛОГИЧЕСКАЯ X кадра (до ×8/7), obj_y — низ
|
||
* спрайта, 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, uint8_t action);
|
||
|
||
/* Loose floors — динамическая отрисовка (состояние pop_loose_modif в
|
||
* pop_map). Звать на ТЕКУЩЕЙ (back) странице из pop_loose_tick.
|
||
* shake_draw — дрожащий кадр (heal+SPRITE); bake_empty — запечь пустоту
|
||
* после падения (NORMAL, в ОЗУ-копию). */
|
||
void pop_loose_shake_draw(int row, int col);
|
||
void pop_loose_bake_empty(int row, int col);
|
||
|
||
/* Падающий кусок loose (mob, seg007 move_loose): спавн при падении тайла
|
||
* (row,col) и покадровое продвижение+отрисовка на back-странице. tick
|
||
* зовётся каждый кадр (внутри pop_loose_tick); клип низа делает clip. */
|
||
void pop_loose_mob_spawn(int row, int col);
|
||
void pop_loose_mob_tick(void);
|
||
void pop_loose_mob_reset(void); /* остановить кусок (смена комнаты) */
|
||
|
||
/* Детектор выхода спрайта за поле: если спрайт [x,w] с ЭКРАННЫМ верхом
|
||
* sy_top и высотой h заходит ниже поля (статус-полоса/борт) или выше
|
||
* верхнего борта — взводит внутренний флаг «борта грязные» на 2 кадра.
|
||
* Звать СРАЗУ после блита падающего объекта (Kid/кусок). */
|
||
void pop_clip_sprite(int x, int w, int sy_top, int h);
|
||
|
||
/* Почистить борта (верхний + статус-полоса/нижний) — но ТОЛЬКО в кадрах,
|
||
* где кто-то реально вышел за поле (гейт по флагу от pop_clip_sprite):
|
||
* даром в покое, O(1) при падении (не зависит от числа спрайтов). Звать
|
||
* КАЖДЫЙ кадр ПОСЛЕ kid_draw+fore на back-странице. */
|
||
void pop_room_clip_borders(void);
|
||
|
||
#endif
|