diff --git a/applications/PoP/roomtest/pop_level.c b/applications/PoP/roomtest/pop_level.c index 4dde111..9b30372 100644 --- a/applications/PoP/roomtest/pop_level.c +++ b/applications/PoP/roomtest/pop_level.c @@ -137,6 +137,23 @@ int pop_room_load(uint8_t room, uint8_t *fg, uint8_t *bg, return 0; } +int8_t pop_room_col_landing(uint8_t room, uint8_t col) +{ + const uint8_t *rf; + int8_t row, res = -1; + if (!lvl_ok || room < 1 || room > 24 || col > 9) return -1; + gfx_w0_map(lvl_page); + rf = room_fg_ptr(room); + for (row = 0; row < 3; row++) { /* кусок пролетает пустые ряды */ + uint8_t t = (uint8_t)(rf[row * 10 + col] & 0x1F); + if (t == 0) continue; /* empty — дальше вниз */ + if (t == 1) res = row; /* floor — приземление → debris */ + break; /* первый не-пустой тайл — стоп */ + } + gfx_w0_unmap(); + return res; +} + uint8_t pop_room_link(uint8_t room, uint8_t side) { uint8_t v; diff --git a/applications/PoP/roomtest/pop_level.h b/applications/PoP/roomtest/pop_level.h index ed581a4..2af1aea 100644 --- a/applications/PoP/roomtest/pop_level.h +++ b/applications/PoP/roomtest/pop_level.h @@ -41,6 +41,11 @@ int pop_room_load(uint8_t room, uint8_t *fg, uint8_t *bg, * 0, если стороны нет. Для переходов между комнатами (L2/L3). */ uint8_t pop_room_link(uint8_t room, uint8_t side); +/* Ряд приземления падающего loose-куска в колонке col комнаты room: первый + * НЕ-пустой тайл сверху вниз; возвращает его ряд, если это floor (→ debris), + * иначе -1 (пролетел/крушение о стену). */ +int8_t pop_room_col_landing(uint8_t room, uint8_t col); + /* Стартовая позиция уровня (блок @2112): комната / поза / направление. */ uint8_t pop_level_start_room(void); uint8_t pop_level_start_pos(void); diff --git a/applications/PoP/roomtest/pop_map.c b/applications/PoP/roomtest/pop_map.c index b1c3575..37ecae8 100644 --- a/applications/PoP/roomtest/pop_map.c +++ b/applications/PoP/roomtest/pop_map.c @@ -86,6 +86,7 @@ static int8_t g_infrontx; /* колонка «перед персонаже /* ---- Карта комнаты ------------------------------------------------- */ uint8_t pop_fell_out; /* 1 = Kid пересёк НИЖНЮЮ границу (см. pop_map.h) */ uint8_t pop_leave_dir; /* уход вбок/вверх: 0=нет; 1=left,2=right,3=up (side+1) */ +uint8_t pop_loose_fell; /* 0=нет; иначе tilepos+1 упавшего loose (кусок улетел вниз) */ static uint8_t *g_fg; /* fg[30], row*10+col (МУТАБЕЛЬНАЯ — loose→empty) */ static uint8_t g_curr_tile; /* = curr_tile2: тайл последнего get_tile */ static uint8_t g_obj_xl; /* позиция внутри тайла (get_tile_div_mod) */ @@ -763,6 +764,7 @@ void pop_loose_tick(void) pop_loose_bake_empty(pos / 10, pos % 10); /* запечь пусто на ТЕКУЩЕЙ странице сразу */ loose_bake[pos] = 1; /* + вторая страница следующим кадром */ pop_loose_mob_spawn(pos / 10, pos % 10); /* отрыв падающего куска (L4) */ + pop_loose_fell = (uint8_t)(pos + 1); /* сигнал приложению: кусок улетел */ continue; } pop_loose_shake_draw(pos / 10, pos % 10); /* дрожащий кадр */ diff --git a/applications/PoP/roomtest/pop_map.h b/applications/PoP/roomtest/pop_map.h index 693f56f..e19c8f9 100644 --- a/applications/PoP/roomtest/pop_map.h +++ b/applications/PoP/roomtest/pop_map.h @@ -39,6 +39,10 @@ extern uint8_t pop_loose_modif[30]; void pop_loose_tick(void); void pop_loose_reset(void); /* сброс loose-состояния при смене комнаты */ +/* Установлен в tilepos+1 в кадре, когда loose-пол упал (кусок улетел ВНИЗ). + * Приложение: определить debris-приземление в комнате снизу. Снять (=0). */ +extern uint8_t pop_loose_fell; + /* check_knock (seg003): по флагу knock (play_seq) тряхнуть loose-полы ряда * приземления/удара. Зовётся из pop_phys_tick. */ void pop_check_knock(void); diff --git a/applications/PoP/roomtest/roomtest.c b/applications/PoP/roomtest/roomtest.c index 96a8deb..64b62e0 100644 --- a/applications/PoP/roomtest/roomtest.c +++ b/applications/PoP/roomtest/roomtest.c @@ -27,13 +27,33 @@ static uint8_t room_fg[30], room_bg[30]; static uint8_t lcol_fg[3], lcol_bg[3], rcol_fg[3], rcol_bg[3], below_fg[10]; static uint8_t cur_room; /* номер текущей комнаты (для переходов) */ +/* Персистентные debris-переопределения (упавший loose-кусок приземлился в + * комнате снизу → floor стал debris). Минимальный per-room override: живёт + * между переходами, применяется в enter_room поверх загруженных тайлов. + * (Полноценное per-room modifier-состояние — в docs/gates_spikes_plan.md, P0.) */ +#define TILE_DEBRIS 0x0E +#define DEBRIS_OVR_MAX 4 +static uint8_t dbr_room[DEBRIS_OVR_MAX], dbr_pos[DEBRIS_OVR_MAX], dbr_cnt; + +static void add_debris_override(uint8_t room, uint8_t pos) +{ + uint8_t i; + for (i = 0; i < dbr_cnt; i++) + if (dbr_room[i] == room && dbr_pos[i] == pos) return; /* уже есть */ + if (dbr_cnt < DEBRIS_OVR_MAX) { + dbr_room[dbr_cnt] = room; dbr_pos[dbr_cnt] = pos; dbr_cnt++; + } +} + /* Загрузить комнату room в рабочие массивы и отрисовать её фон в ОБЕ * страницы дабл-буфера (у каждой своя видео-ОЗУ/теневая копия). Оставляет * активной страницу 1 — вызывающий восстанавливает нужную draw-страницу. */ static void enter_room(uint8_t room) { - uint8_t pg; + uint8_t pg, i; pop_room_load(room, room_fg, room_bg, lcol_fg, lcol_bg, rcol_fg, rcol_bg, below_fg); + for (i = 0; i < dbr_cnt; i++) /* применить debris-переопределения */ + if (dbr_room[i] == room) room_fg[dbr_pos[i]] = TILE_DEBRIS; pop_map_set(room_fg); pop_map_set_edges(pop_room_link(room, 0), pop_room_link(room, 1), pop_room_link(room, 2), pop_room_link(room, 3), @@ -151,6 +171,15 @@ int main(void) } pop_loose_tick(); /* loose-полы: анимация + перерисовка (СЛОЙ ФОНА */ /* — ДО Kid, чтобы Kid всегда был поверх плиты) */ + if (pop_loose_fell) { /* упавший кусок → debris в комнате снизу */ + uint8_t fcol = (uint8_t)((pop_loose_fell - 1) % 10); + uint8_t down = pop_room_link(cur_room, LINK_DOWN); + pop_loose_fell = 0; + if (down) { + int8_t lrow = pop_room_col_landing(down, fcol); + if (lrow >= 0) add_debris_override(down, (uint8_t)(lrow * 10 + fcol)); + } + } kid_draw(); /* нарисовать новый кадр (детект выхода за поле) */ pop_fore_over_kid(kid_fp_obj_x(), kid_fp_obj_y(), kid_fp_width(), kid_fp_height(),