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:
@@ -27,7 +27,7 @@ __sfr __at (0xFE) io_border;
|
||||
* row2, шахта col3). Kid на полу row0 col1, идёт вправо → падает в шахту →
|
||||
* пики. TODO: вернуть на pop_level_start_room (комната 1) после отладки. */
|
||||
#define START_ROOM 6
|
||||
#define START_COL 1
|
||||
#define START_COL 4
|
||||
#define START_ROW 0
|
||||
#define RESPAWN_DELAY 400 /* авто-респавн (фолбэк), если не нажали ↑ */
|
||||
#define RESPAWN_SETTLE 20 /* тиков до приёма ↑ (труп успел лечь) */
|
||||
@@ -67,34 +67,47 @@ static uint8_t seam_redraw; /* оставшиеся кадры редроя (
|
||||
static uint8_t room_label_sig = 0xFF;
|
||||
static uint8_t room_label_redraw;
|
||||
|
||||
/* Персистентные debris-переопределения (упавший loose-кусок приземлился в
|
||||
* комнате снизу → floor стал debris). Минимальный per-room override: живёт
|
||||
* между переходами, применяется в enter_room поверх загруженных тайлов.
|
||||
* (Полноценное per-room modifier-состояние — в docs/gates_spikes_plan.md, P0.) */
|
||||
/* Персистентные переопределения тайлов уровня: упавший loose-кусок оставил
|
||||
* щебень (floor → debris), а на месте самой плиты — пусто (в т.ч. в комнате
|
||||
* СВЕРХУ: провалившийся потолок = колодец). Минимальный per-room override:
|
||||
* живёт между переходами, применяется в enter_room поверх загруженных тайлов
|
||||
* (и для ряда 2 верхнего соседа). (Полноценное 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;
|
||||
#define TILE_EMPTY 0x00
|
||||
#define OVR_MAX 8
|
||||
static uint8_t ovr_room[OVR_MAX], ovr_pos[OVR_MAX], ovr_tile[OVR_MAX], ovr_cnt;
|
||||
|
||||
static void add_debris_override(uint8_t room, uint8_t pos)
|
||||
static void add_tile_override(uint8_t room, uint8_t pos, uint8_t tile)
|
||||
{
|
||||
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++;
|
||||
for (i = 0; i < ovr_cnt; i++)
|
||||
if (ovr_room[i] == room && ovr_pos[i] == pos) { ovr_tile[i] = tile; return; }
|
||||
if (ovr_cnt < OVR_MAX) {
|
||||
ovr_room[ovr_cnt] = room; ovr_pos[ovr_cnt] = pos;
|
||||
ovr_tile[ovr_cnt] = tile; ovr_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Применить переопределения комнаты room к массиву тайлов: base = tilepos
|
||||
* первого элемента (0 для полной комнаты, 20 для ряда 2 верхнего соседа). */
|
||||
static void apply_overrides(uint8_t room, uint8_t *tiles, uint8_t base, uint8_t n)
|
||||
{
|
||||
uint8_t i;
|
||||
for (i = 0; i < ovr_cnt; i++)
|
||||
if (ovr_room[i] == room && ovr_pos[i] >= base && ovr_pos[i] < base + n)
|
||||
tiles[ovr_pos[i] - base] = ovr_tile[i];
|
||||
}
|
||||
|
||||
/* Загрузить комнату room в рабочие массивы и отрисовать её фон в ОБЕ
|
||||
* страницы дабл-буфера (у каждой своя видео-ОЗУ/теневая копия). Оставляет
|
||||
* активной страницу 1 — вызывающий восстанавливает нужную draw-страницу. */
|
||||
static void enter_room(uint8_t room)
|
||||
{
|
||||
uint8_t pg, i;
|
||||
uint8_t pg;
|
||||
uint8_t *room_mod;
|
||||
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;
|
||||
apply_overrides(room, room_fg, 0, 30); /* щебень/пустота от упавших плит */
|
||||
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),
|
||||
@@ -109,10 +122,13 @@ static void enter_room(uint8_t room)
|
||||
pop_level_access_begin();
|
||||
for (c = 0; c < 10; c++) above_fg[c] = pop_level_tile_raw(up, (uint8_t)(20 + c));
|
||||
pop_level_access_end();
|
||||
apply_overrides(up, above_fg, 20, 10); /* провалившийся потолок = колодец */
|
||||
for (c = 0; c < 10; c++) above_mod[c] = um[20 + c];
|
||||
pop_room_set_above(above_fg, above_mod);
|
||||
pop_map_set_above(above_fg); /* плита-потолок: пробой снизу + провал */
|
||||
} else {
|
||||
pop_room_set_above(0, 0); /* нет комнаты сверху → пол (кромка) */
|
||||
pop_map_set_above(0);
|
||||
}
|
||||
}
|
||||
pop_map_set_room(room);
|
||||
@@ -232,6 +248,7 @@ int main(void)
|
||||
|
||||
pop_ctrl_tick(); /* ввод -> control(): смена seq */
|
||||
kid_heal(); /* стереть прошлый кадр ЭТОЙ страницы */
|
||||
pop_fore_heal(); /* + следы оверлея (шире прямоугольника Kid) */
|
||||
kid_tick(); /* play_seq: следующий кадр */
|
||||
pop_phys_tick(); /* K3: падение/приземление/стена */
|
||||
if (pop_fell_out) { /* Kid пересёк нижнюю границу комнаты */
|
||||
@@ -295,18 +312,35 @@ int main(void)
|
||||
}
|
||||
io_border = 6; /* голубой */
|
||||
if (pop_loose_fell) { /* упавший кусок → debris в комнате снизу */
|
||||
uint8_t fcol = (uint8_t)((pop_loose_fell - 1) % 10);
|
||||
uint8_t fpos = (uint8_t)(pop_loose_fell - 1);
|
||||
uint8_t fcol = (uint8_t)(fpos % 10);
|
||||
uint8_t down = pop_room_link(cur_room, LINK_DOWN);
|
||||
pop_loose_fell = 0;
|
||||
io_border = 2; /* синий */
|
||||
add_tile_override(cur_room, fpos, TILE_EMPTY); /* сама плита исчезла */
|
||||
if (down) {
|
||||
int8_t lrow = pop_room_col_landing(down, fcol);
|
||||
if (lrow >= 0) add_debris_override(down, (uint8_t)(lrow * 10 + fcol));
|
||||
if (lrow >= 0) add_tile_override(down, (uint8_t)(lrow * 10 + fcol), TILE_DEBRIS);
|
||||
}
|
||||
}
|
||||
if (pop_ceil_fell) { /* провалилась плита-ПОТОЛОК (ряд 2 комнаты сверху) */
|
||||
uint8_t ccol = (uint8_t)(pop_ceil_fell - 1);
|
||||
uint8_t up = pop_room_link(cur_room, 2);
|
||||
pop_ceil_fell = 0;
|
||||
if (up) add_tile_override(up, (uint8_t)(20 + ccol), TILE_EMPTY); /* колодец */
|
||||
}
|
||||
if (pop_debris_at) { /* кусок лёг в ЭТОЙ комнате → щебень */
|
||||
add_tile_override(cur_room, (uint8_t)(pop_debris_at - 1), TILE_DEBRIS);
|
||||
pop_debris_at = 0;
|
||||
}
|
||||
io_border = 4; /* зеленый */
|
||||
update_kid_render_dx(); /* straddle: смещение спрайта, если kid_room≠cur_room */
|
||||
kid_draw(); /* нарисовать новый кадр (детект выхода за поле) */
|
||||
pop_loose_mob_draw_over(); /* падающая плита НИЖЕ Kid → поверх него (y-порядок) */
|
||||
if (pop_kid_hurt) { /* HP убавилось → «брызги» удара (draw_hurt_splash) */
|
||||
kid_draw_splash();
|
||||
pop_kid_hurt = 0;
|
||||
}
|
||||
io_border = 0; /* черный */
|
||||
pop_fore_over_kid(kid_fp_obj_x(), kid_fp_obj_y(),
|
||||
kid_fp_width(), kid_fp_height(),
|
||||
@@ -324,15 +358,15 @@ int main(void)
|
||||
* а не каждый кадр (обход sdcc_z80_cmp_store_a_bug: сначала сохранить). */
|
||||
{
|
||||
uint8_t r = cur_room;
|
||||
if (r != room_label_sig) { room_label_sig = r; room_label_redraw = 2; }
|
||||
if (room_label_redraw) {
|
||||
char roomLabel[] = "Room ##";
|
||||
roomLabel[5] = (char)(r / 10 + '0');
|
||||
roomLabel[6] = (char)(r % 10 + '0');
|
||||
setcolor(WHITE);
|
||||
outtextxy(100, 0, roomLabel);
|
||||
room_label_redraw--;
|
||||
}
|
||||
// if (r != room_label_sig) { room_label_sig = r; room_label_redraw = 2; }
|
||||
// if (room_label_redraw) {
|
||||
// char roomLabel[] = "Room ##";
|
||||
// roomLabel[5] = (char)(r / 10 + '0');
|
||||
// roomLabel[6] = (char)(r % 10 + '0');
|
||||
// setcolor(WHITE);
|
||||
// outtextxy(100, 0, roomLabel);
|
||||
// room_label_redraw--;
|
||||
// }
|
||||
}
|
||||
|
||||
gfx_wait_vsync();
|
||||
|
||||
Reference in New Issue
Block a user