Files
Sprinter-SDCC/applications/PoP/roomtest/pop_map.h
T
snark13 63a3b60524 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>
2026-07-27 17:35:25 +03:00

126 lines
8.4 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* pop_map.h — коллизия Kid с картой комнаты (Фаза K3): тайловые запросы
* + физика падения + приземление. Порт SDLPoP seg005/seg006
* (check_on_floor/start_fall/do_fall/fall_accel/fall_speed/land/in_wall).
*
* K3.2 (падение): Kid, сойдя/сбежав с края пола (тайл под ним не floor),
* начинает падать (fall_y-ускорение, Char.y растёт), приземляется на пол
* ниже (soft/medium land) или продолжает вниз. Стена под персонажем —
* in_wall (выталкивание). Бег В стену (check_bumped) — отдельным шагом.
*/
#ifndef POP_MAP_H
#define POP_MAP_H
#include <stdint.h>
/* Задать карту текущей комнаты: fg[30] = коды тайлов (row*10+col, 3×10).
* col<0/>9 или row<0/>2 трактуются как стена (край уровня). Массив
* МУТАБЕЛЬНЫЙ (loose-пол при падении → empty) — передавать ту же копию,
* что и в pop_room_draw, чтобы отрисовка видела изменения. */
void pop_map_set(uint8_t *fg);
/* Связи комнаты (0=нет соседа; иначе номер) + кромки швов для коллизии:
* lcol_fg = col9 левого соседа (за col0), rcol_fg = col0 правого соседа
* (за col9). Звать в enter_room. */
void pop_map_set_edges(uint8_t left, uint8_t right, uint8_t up, uint8_t down,
const uint8_t *lcol_fg, const uint8_t *rcol_fg);
/* Номер ТЕКУЩЕЙ комнаты (для доступа к room_modif пик/ворот в pop_trob).
* Звать в enter_room. */
void pop_map_set_room(uint8_t room);
/* HP/смерть. pop_kid_dead=1 когда Kid убит (пики); hitp_curr — текущее HP.
* pop_kid_hp_reset() ставит старт HP и снимает смерть (звать в kid_init/
* респавн). */
extern uint8_t pop_kid_dead;
extern uint8_t hitp_curr;
void pop_kid_hp_reset(void);
/* Уход из комнаты ВБОК/ВВЕРХ: 0=нет; 1=left,2=right,3=up (= side+1 для
* pop_room_link). Координаты Kid уже репроецированы (x∓140 / y+189).
* Приложение переключает комнату по соответствующей связи и снимает флаг. */
extern uint8_t pop_leave_dir;
/* exit_room_timer (порт seg002 exit_room): пока >0, боковой/нижний leave
* заблокирован (декремент в pop_phys_tick). Приложение ставит =2 при входе
* в комнату (enter_room) — 2 кадра защиты от повторного/транзиентного leave
* (ping-pong у шва, транзиент отскока о ворота, баг #4/BUG-2). */
extern uint8_t pop_leave_timer;
/* Loose floors (проваливающиеся полы). pop_loose_modif[30] — состояние на
* тайл (0 покой / 0x80.. тряска / 1..11 отсчёт падения); читает pop_bg при
* отрисовке. pop_loose_tick() — анимация + перерисовка изменившихся тайлов
* на ТЕКУЩЕЙ странице; звать в основном цикле ПОСЛЕ set_draw_page(back),
* рядом с kid-отрисовкой. */
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;
/* Плита-ПОТОЛОК: loose ряда 2 комнаты СВЕРХУ (в оригинале — тот же loose с
* отрицательным tilepos, seg006 check_press frame 79 / seg007 animate_loose).
* pop_map_set_above даёт МУТАБЕЛЬНУЮ копию ряда 2 верхнего соседа (ту же, что
* ушла в pop_room_set_above): провалившаяся плита становится в ней EMPTY —
* сверху открывается колодец. pop_ceil_modif[col] — состояние (как
* pop_loose_modif), читает pop_bg. Сигналы приложению (для персистентности
* между входами в комнату): pop_ceil_fell = col+1 провалившейся плиты,
* pop_debris_at = tilepos+1 щебня, оставшегося в ЭТОЙ комнате. Снимать (=0). */
void pop_map_set_above(uint8_t *above_row2_fg);
extern uint8_t pop_ceil_modif[10];
extern uint8_t pop_ceil_fell;
extern uint8_t pop_debris_at;
/* Взводится в кадре, когда Kid получил урон (hitp_delta<0 оригинала) —
* приложение рисует «брызги» kid_draw_splash() поверх Kid и снимает флаг. */
extern uint8_t pop_kid_hurt;
/* check_knock (seg003): по флагу knock (play_seq) тряхнуть loose-полы ряда
* приземления/удара. Зовётся из pop_phys_tick. */
void pop_check_knock(void);
/* Установлен в 1, когда Kid пересёк НИЖНЮЮ границу комнаты (провал в дыру
* или спуск-зацеп с кромки). Координаты Kid УЖЕ репроецированы в кадр
* комнаты снизу (y -= 189, curr_row = 0). Приложение решает: если есть
* links.down — сменить комнату (pop_room_load+перерисовка) и продолжить;
* иначе — выпал из уровня (респавн). Снять флаг после обработки. */
extern uint8_t pop_fell_out;
/* Пер-кадровая физика ПОСЛЕ kid_tick(play_seq): fall_accel + fall_speed +
* determine_col + check_action (триггер падения / do_fall / приземление).
* Порядок как в оригинале (seg000 play_kid_frame). */
void pop_phys_tick(void);
/* Тип препятствия/края ВПЕРЕДИ по направлению (pop_edge_type после
* pop_edge_distance): для control (бежать / осторожный шаг / стоп у стены). */
#define EDGE_CLOSER 0 /* край уступа над ямой (дистанция = до кромки) */
#define EDGE_WALL 1 /* стена впереди/под персонажем */
#define EDGE_FLOOR 2 /* пол (нет препятствия рядом, дистанция = 11) */
/* Расстояние до края/стены впереди + побочно g_edge_type (pop_edge_type). */
int pop_edge_distance(void);
uint8_t pop_edge_type(void);
/* Стена впереди в пределах стопа? Если да — прижимает Kid.x к корректной
* позиции (передний край у стены, симметрично) и возвращает 1. Для
* control_running (чистый стоп у стены). */
int pop_wall_ahead(void);
/* Прыжок вверх в стойке (↑): seq чистого прыжка (seq_28/seq_14) ЛИБО
* прыжка-с-зацепом за уступ выше (seq_8/24/16) + выравнивание Kid.x.
* check_jump_up/grab_up (K4.4). control_up гасит caller. */
uint8_t pop_jump_up_seq(void);
/* ---- Вис/зацеп/спуск (K4.2/K4.3) — тайловые решения для pop_ctrl --- *
* Управление (control_hanging/can_climb_up/hang_fall/down_pressed) в
* pop_ctrl; здесь — предикаты + выбор seq (+ выравнивание Kid.x). */
uint8_t pop_hang_grab_ready(void); /* grab_timer истёк — можно climb-up */
uint8_t pop_hang_climb_up_seq(void); /* seq_10 / seq_73 (подтягивание) */
int8_t pop_hang_wall(void); /* Shift в висе: 1=у стены,-1=fall,0=держ.*/
uint8_t pop_hang_fall_seq(void); /* seq_23 / seq_11 (сорваться), +Kid.x */
uint8_t pop_down_action(void); /* 1=обработано(спуск/отступ), 0=присед */
#endif