roomtest: обломки упавшего loose в комнате снизу (debris)
Loose-пол room1(2,6) при падении даёт кусок, который в оригинале улетает в комнату снизу (links.down) и приземляется на первый floor, превращая его в debris (порт move_loose/loose_land seg007). Для room1(2,6): room2(0,6)=empty пролёт → room2(1,6)=floor приземление → debris. Минимальная реализация (без анимации полёта куска, только персистентный результат — мини-версия P0 из docs/gates_spikes_plan.md): - pop_map: сигнал pop_loose_fell (tilepos+1 упавшего loose). - pop_level: pop_room_col_landing(room,col) — ряд первого floor сверху вниз (пустые ряды пролетаются), иначе -1. - roomtest: при pop_loose_fell вычисляет debris-приземление в комнате снизу → персистентный override (dbr_room/dbr_pos, живёт между переходами) → enter_room применяет поверх загруженных тайлов (floor→debris 0x0E). Проверено в MAME: провал loose room1(2,6) → debris в room2(1,6), сохраняется при повторных входах. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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); /* дрожащий кадр */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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(),
|
||||
|
||||
Reference in New Issue
Block a user