L3-CHOMP: чомперы — анимация, отрисовка и смерть в челюстях

Порт SDLPoP:
  animate_chomper / start_chompers / start_anim_chomper /
  next_chomper_timing (seg007) -> pop_trob.c;
  draw_tile_anim + draw_tile_fore, ветка tiles_18_chomper (seg008) ->
  pop_room.c (низ/кровь/верх, backtable) и pop_bg.c (передний слой);
  check_chomped_kid / check_chomped_guard / chomped (seg004) -> pop_map.c.

Состояние — в room_modif, как у пик и ворот: младшие 7 бит фаза 1..N,
старший бит «перемололо кого-то» (кровь остаётся на тайле навсегда).
Номер позы chomper_fram1 и передние куски лежат в РЕЗИДЕНТЕ (pop_tile.c):
их читают обе половины слоя фона, а const-таблица банка из чужого банка
не видна.

start_chompers зовётся там же, где в оригинале: SEQ_UP/SEQ_DOWN в play_seq
(pop_kid.c), start_fall и land (pop_map.c), вход в комнату (roomtest.c).
Поэтому чомперы щёлкают только пока персонаж в ИХ ряду — так в оригинале.

check_chomped_guard у оригинала отдельное тело (страж не проходит через
check_collisions).  У нас та же формула уже есть в get_row_collision_data,
поэтому флаги ряда считаются во ВРЕМЕННЫЙ массив: coll_curr/above/below —
это кадр Кида, из них move_coll_to_prev берёт прошлые флаги, затирание
сломало бы ему бамп.

Период смыкания — POP_CHOMPER_SPEED в pop_tune.h (15, как в оригинале).

Заодно: устаревшая заглушка pop_fore_set_clip в tests-host была __banked,
хотя функция давно переехала в резидент — всплыло при пересборке.

Ассеты уже были упакованы (pop_pack_bg.py, 2026-08-07).  Банк 6: 20.0 %,
банк 7: 39.7 %, банк 3: 53.8 %.  tests-host зелёные (5 наборов).
Зубья в MAME рисуются; анимация и смерть — на ручной приёмке.
This commit is contained in:
2026-08-08 19:05:16 +03:00
parent 4310f94795
commit dc0bd47368
14 changed files with 238 additions and 3 deletions
+42
View File
@@ -54,6 +54,22 @@ void pop_bg_free(void) __banked
static const uint8_t SPIKES_FRAM_RIGHT[10] = {0, 134, 135, 136, 137, 138, 137, 135, 134, 0};
/* ---- Чомпер (seg008.c:0B2B draw_tile_anim, ветка tiles_18_chomper) ---- *
* Кадр берётся НЕ прямо из modif: chomper_fram1[min(modif & 0x7F, 6)] даёт
* номер позы 0..4, и уже он индексирует три набора кусков — нижнюю челюсть
* (backtable), верхнюю (backtable, со своим подъёмом) и передний слой
* (foretable, поверх персонажа). Кровь — тот же номер позы + 114 (back) /
* +119 (fore), рисуется mono-силуэтом цветом 12; в атласе она уже такой
* (pop_pack_bg.py, 2026-08-07).
* Старший бит modif (0x80) = «в этом чомпере кого-то перемололо».
*
* Номер позы (pop_chomp_pose) и передние куски живут в РЕЗИДЕНТЕ
* (pop_tile.c): их читает ещё и fore-проход из горячей половины, а
* const-таблицы банка из чужого банка не видны. */
static const uint8_t CHOMP_FRAM_BOT[5] = {101, 102, 103, 104, 105};
static const uint8_t CHOMP_FRAM_TOP[5] = {0, 0, 111, 112, 113};
static const uint8_t CHOMP_FRAM_Y[5] = {0, 0, 0x25, 0x2F, 0x32};
static const uint8_t BLUELINE_FRAM1[4] = {0, 124, 125, 126};
static const int8_t BLUELINE_FRAM_Y[4] = {0, -20, -20, 0};
static const uint8_t BLUELINE_FRAM3[4] = {44, 44, 45, 45};
@@ -258,6 +274,19 @@ static void draw_tile(int row, int col)
if (sf > 0 && sf < 10 && POP_SPIKES_FRAM_LEFT[sf])
pop_env_b(POP_SPIKES_FRAM_LEFT[sf], x, dmy - 2);
}
/* Чомпер (тот же draw_tile_anim, case tiles_18_chomper): нижняя челюсть
* на draw_main_y, поверх неё кровь (если кого-то перемололо), затем
* верхняя челюсть со своим подъёмом. Всё это BACKtable — то есть ПОД
* персонажем; передний слой рисует fore-проход. */
if (row >= 0 && code == 0x12) {
uint8_t cm = pop_tile_mod(row, col);
uint8_t pose = pop_chomp_pose(cm);
pop_env_b(CHOMP_FRAM_BOT[pose], x, dmy);
if (cm & 0x80)
pop_env_b((uint8_t)(pose + 114), x + 8, dmy - 6);
if (CHOMP_FRAM_TOP[pose])
pop_env_b(CHOMP_FRAM_TOP[pose], x, dmy - CHOMP_FRAM_Y[pose]);
}
/* Меч-предмет на полу (тот же draw_tile_anim, case tiles_22_sword):
* chtab_1 (наш pot-атлас), id = (modif==1)+10, низ на draw_main_y-3.
* В оригинале это midtable (рисуется вместе с объектами) — у нас статикой
@@ -326,6 +355,19 @@ void pop_spike_redraw(int row, int col) __banked
gfx_set_bank(GFX_BANK_NORMAL);
}
/* Чомпер: перерисовка кадра анимации (порт redraw_20h/draw_trob). Челюсти
* поднимаются высоко над линией пола (верхний кусок уходит на 0x32 = 50 px
* вверх от dmy), поэтому heal берём на всю высоту тайла. Правый сосед НЕ
* нужен: в отличие от пик, все куски чомпера рисуются в СВОЕЙ ячейке. */
void pop_chomp_redraw(int row, int col) __banked
{
int x = POP_COL_XH[col] * 8;
pop_heal_off(x, 63 * row + 2, 32, 64);
gfx_set_bank(GFX_BANK_SPRITE);
draw_tile(row, col);
gfx_set_bank(GFX_BANK_NORMAL);
}
/* Перерисовать ЛЕВЫЙ шов (col0) на back-странице по живому modif соседа —
* ворота соседней комнаты слева (portcullis room8) видны в col0 текущей
* комнаты через draw_gate_back (draw_tile ветка lcode==4, lmod = pop_t_lbg[0]).