docs: loose_floors_plan — конкретика SDLPoP + подход интеграции
Дополнен точными данными из SDLPoP (сверено): кадровые таблицы loose_fram_left/right/bottom, get_loose_frame, y_loose_land, delay=11; триггеры с call-sites (check_press->make_loose_fall при стоянии на 11, frame79-сверху; do_knock на жёстком приземлении; animate каждый кадр); tile_is_floor(11)=1. Плюс подход интеграции в наш движок: общая мутабельная копия комнаты pop_map<->pop_bg + per-page запекание пустоты после падения; тонкое место — перерисовка динамического тайла в дабл-буфере. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -89,6 +89,53 @@
|
||||
- L4: mob (падающий кусок → debris снизу).
|
||||
- L5: урон Киду от падающего куска.
|
||||
|
||||
## Конкретика из SDLPoP (сверено 2026-07-18, готово к реализации)
|
||||
|
||||
Таблицы (seg008.c), индекс = `get_loose_frame(modif)`:
|
||||
- `loose_fram_left[] = {41,69,41,70,70,41,41,41,70,70,70,0}`
|
||||
- `loose_fram_right[] = {42,71,42,72,72,42,42,42,72,72,72,0}`
|
||||
- `loose_fram_bottom[]= {43,73,43,74,74,43,43,43,74,74,74,0}`
|
||||
- `get_loose_frame(m)`: если `(m&0x80)` (или delay>11) → `m&=0x7F; if(m>10) return 1;` → `return m;`
|
||||
- `y_loose_land[] = {2,65,128,191,254}` (mob), `loose_floor_delay = 11`.
|
||||
|
||||
Триггеры (call-sites):
|
||||
- **make_loose_fall(modifier=1)** — из `check_press()` (seg006): когда Kid
|
||||
СТОИТ на тайле (FRAME_NEEDS_FLOOR, action < hang_climb / turn / bumped) и
|
||||
`get_tile_at_char()==11`; ИЛИ `frame==79` (прыжок вверх) и
|
||||
`get_tile_above_char()==11` (пробой сверху). `tile_is_floor(11)==1` —
|
||||
Kid стоит на loose (start_fall НЕ зовётся). Тело:
|
||||
`if(!(tile&0x20) && (sbyte)modif<=0){ modif=modifier; add_trob(type0); }`
|
||||
- **do_knock(row)** — на ЖЁСТКОМ приземлении (SEQ_KNOCK_DOWN→check_knock,
|
||||
seg003): по всем колонкам ряда `if(tile==11) loose_make_shake()`
|
||||
(`if(modif==0){ modif=0x80; add_trob(type1); }`).
|
||||
- **animate_loose** (каждый кадр, seg007:816): `++modif`; если `&0x80`
|
||||
(тряска): `if(modif>=0x84){modif=0; trob=-1;}`; иначе (отсчёт):
|
||||
`if(modif>=11){ remove_loose(tile→0); trob=-1; add_mob(); } else shake`.
|
||||
|
||||
## Интеграция в наш движок (roomtest) — подход
|
||||
|
||||
Наш движок ПЕКЁТ комнату один раз (двойной буфер: своя ОЗУ-копия на
|
||||
страницу). Loose требует динамики + общего состояния pop_map↔pop_bg:
|
||||
1. **Общая МУТАБЕЛЬНАЯ копия комнаты**: roomtest.c держит `uint8_t
|
||||
room_fg[30]` (копия room1_fg) и передаёт ОДИН указатель и в
|
||||
`pop_room_draw`, и в `pop_map_set` → мутации loose видны обоим.
|
||||
(Сейчас g_fg — `const`; сделать неконстантным.)
|
||||
2. **Состояние**: `uint8_t pop_loose_modif[30]` (0 / 0x80.. / 1..11).
|
||||
3. **Модель** (pop_map): `check_press()` в `pop_phys_tick` (make_loose_fall
|
||||
при стоянии на 11), `animate` каждый кадр.
|
||||
4. **Перерисовка** (pop_bg, на back-странице каждый кадр):
|
||||
- тряска/отсчёт (код всё ещё 11): `gfx_heal(tile rect)` (вернуть
|
||||
печёный фон) + нарисовать loose-кадр (left/right/bottom по
|
||||
get_loose_frame) банком SPRITE;
|
||||
- падение (11→0): mutate `g_fg[pos]=0` + «запечь пустоту» на ОБЕИХ
|
||||
страницах (bake-счётчик 2: чёрный bar + draw_tile empty банком NORMAL
|
||||
на текущей странице 2 кадра подряд) → дальше heal показывает пусто.
|
||||
5. **L4 mob**: падающий кусок → debris(14) снизу (y_loose_land); пока
|
||||
отложено — упавший loose = пусто. **L5** урон — позже.
|
||||
|
||||
Риск: перерисовка динамического тайла в двойном буфере (per-page heal +
|
||||
bake) — единственное тонкое место; остальное — прямой порт логики выше.
|
||||
|
||||
## Связанные
|
||||
|
||||
Триггеры завязаны на физику Kid ([[pop_hang_state]] check_press/check_grab,
|
||||
|
||||
Reference in New Issue
Block a user