3dbad6120c
Шаги 1-2 из плана стражей: 1. Спрайты (chtab_5_guard, база 750). Новый упаковщик pop_pack_guard.py: data/GUARD/res751..784 -> GUARD\g0..g4.atl (5 EMM-страниц, адресация id>>3 / id&7, как у Kid). Палитра берётся НЕ из PNG, а из res10.bin (guard_palettes: 7 палитр по 16 цветов, 6-бит) по level.guards_color — на уровне 1 у обоих стражей color = 2; группа слотов 0x90..0x9F добавлена в общий kid.pal. 2. Таблица кадров стража у оригинала СВОЯ (frame_tbl_guard, seg006:372, 41 запись) и индексируется как frame + add_frame - 149, где add_frame = 70 для кадров 102..106. Она дописана в kid_data.bin (3515 -> 3720 Б, смещение в KID_BIN_GFRAMES_OFF); pop_kid получил pop_kid_data_frame() — чтение кадра из ЛЮБОЙ таблицы страницы данных. 3. Появление: pop_level_guard() читает guards_tile/dir/color/skill из уровня, pop_guard_enter() ставит стража по enter_guard (seg002:0112) + pos_guards (seg003): row из тайла, y = y_land[row+1], x из колонки, charid = guard, sword сложен, alive = -1, HP = 3. Отрисовка pop_guard_draw() — та же математика, что kid_draw (load_frame_to_obj + calc_screen_x_coord), но атлас стража и своя таблица кадров; heal по странице дабл-буфера, как у Kid. Интерпретатора последовательностей у стража ПОКА НЕТ: кадр ставится напрямую (166 = frame_166_stand_inactive, что и даёт seq_77 при входе в комнату). play_seq для произвольного персонажа + ИИ — следующая фаза. Проверено в MAME: в комнате 3 страж появляется на своём месте (ряд 1, кол 7) и рисуется; цвета совпадают с эталонным рендером спрайта в палитре color=2. ВНИМАНИЕ по памяти: куча W2 просела до 805 Б (было 2349). Перед ИИ стражей нужен шаг 5 плана (данные: room_modif 720 Б, dl1/dl2 512 Б, _kbdraw_down 512 Б) либо вынос кода отрисовки стража в резидент W3. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
106 lines
5.5 KiB
C
106 lines
5.5 KiB
C
/*
|
|
* pop_kid.h — движок анимации/движения Kid (Фаза K1): интерпретатор
|
|
* seqtbl (play_seq) + frame_table. Порт SDLPoP seg006.c. Данные —
|
|
* kid_data.h (pop_extract_kid_data.py).
|
|
*
|
|
* K1: только проигрывание последовательностей кадров с авторскими
|
|
* смещениями (движение = SEQ_DX/DY + frame.dx/dy). Управление (K2) и
|
|
* коллизия карты (K3) — отдельно.
|
|
*/
|
|
#ifndef POP_KID_H
|
|
#define POP_KID_H
|
|
|
|
#include <stdint.h>
|
|
|
|
/* Состояние персонажа (подмножество char_type, types.h). */
|
|
typedef struct {
|
|
uint8_t frame;
|
|
uint8_t x, y;
|
|
int8_t direction; /* -1 влево, 0 вправо */
|
|
int8_t curr_col, curr_row;
|
|
uint8_t action;
|
|
int8_t fall_x, fall_y;
|
|
uint8_t repeat;
|
|
uint16_t curr_seq; /* адрес в seqtbl (база SEQTBL_BASE) */
|
|
} kid_t;
|
|
|
|
extern kid_t Kid;
|
|
|
|
/* Флаг сотрясения (seg006 knock): +1 = KNOCK_UP (ряд выше), -1 = KNOCK_DOWN
|
|
* (свой ряд). Ставит play_seq, читает/сбрасывает pop_check_knock. */
|
|
extern int8_t knock;
|
|
|
|
/* Загрузить npages атласов Kid (kid0..kid{npages-1}.atl). ДО initgraph.
|
|
* 0 — OK, -1 — ошибка. */
|
|
int pop_kid_load(uint8_t npages);
|
|
|
|
/* Данные анимации (таблица кадров + seqtbl) — отдельная EMM-страница
|
|
* (kid_data.bin): в _CODE окна W1/W2 они занимали 3.5 КБ. Грузить ДО
|
|
* первого kid_init/play_seq. 0 — OK, -1 — ошибка (без них Kid не оживёт).
|
|
* Страница маппится в W0 внутри play_seq, раз за тик. */
|
|
int pop_kid_data_load(const char *path);
|
|
|
|
/* Прочитать кадр из таблицы страницы данных: tbl_off — KID_BIN_FRAMES_OFF
|
|
* (Kid) или KID_BIN_GFRAMES_OFF (страж, своя таблица frame_tbl_guard).
|
|
* Маппит страницу сама; для горячего цикла есть cur_frame. */
|
|
void pop_kid_data_frame(uint16_t tbl_off, uint8_t idx, uint8_t *out5);
|
|
void pop_kid_data_free(void);
|
|
|
|
/* Атлас chtab_0 «меч в руке» (sword.atl) — спрайт клинка поверх Kid в кадрах
|
|
* подъёма меча/убирания в ножны (add_sword_to_objtable, seg006:1798).
|
|
* Грузить ДО initgraph, как и страницы Kid. 0 — OK, -1 — ошибка (тогда
|
|
* кадры рисуются без клинка). */
|
|
int pop_sword_load(void);
|
|
void pop_kid_free(void);
|
|
|
|
/* Инициализировать Kid: последовательность seq_id, клетка col/row,
|
|
* направление dir (-1/0). Ставит x/y по x_bump/y_land. */
|
|
void kid_init(uint8_t seq_id, int8_t col, int8_t row, int8_t dir);
|
|
|
|
/* Один логический тик: play_seq() — продвинуть последовательность до
|
|
* следующего кадра (применить SEQ_DX/DY/ACTION/...). */
|
|
void kid_tick(void);
|
|
|
|
/* play_seq напрямую (для pop_map start_fall — переход в fall-seq в тот же
|
|
* physics-шаг, как оригинал). */
|
|
void play_seq(void);
|
|
|
|
/* Поля текущего кадра kid_frames[Kid.frame] (pop_map, без дублирования
|
|
* таблицы во втором TU). */
|
|
int8_t kid_cur_dx(void);
|
|
uint8_t kid_cur_flags(void);
|
|
|
|
/* Сменить последовательность (Kid.curr_seq = kid_seq_off[seq_id]) — единая
|
|
* точка для pop_ctrl/pop_map (иначе каждый дублировал бы kid_seqtbl ~2.3КБ). */
|
|
void kid_set_seq(uint8_t seq_id);
|
|
|
|
/* Рендер-смещение Kid по ЛОГИЧЕСКОЙ X (порт xpos_in_drawn_room, seg004):
|
|
* когда комната Kid ≠ отрисованной (straddle у шва), спрайт рисуется со
|
|
* сдвигом ∓140 (левый сосед −140 / правый +140), при этом Kid.x/коллизия
|
|
* остаются в кадре комнаты Kid. 0 — комнаты совпадают (обычный случай).
|
|
* Влияет на kid_draw и метрики футпринта (fore) — heal берёт запомненный
|
|
* прямоугольник, поэтому согласован автоматически. */
|
|
void pop_kid_set_render_dx(int dx);
|
|
|
|
/* Нарисовать текущий кадр Kid (банк GFX_BANK_SPRITE — видео-ОЗУ, без
|
|
* теневой копии; запоминает прямоугольник для kid_heal). */
|
|
void kid_draw(void);
|
|
|
|
/* draw_hurt_splash (seg006:2003): «брызги» урона (image 218) поверх Kid —
|
|
* звать СРАЗУ после kid_draw в кадре, когда HP убавилось (pop_kid_hurt). */
|
|
void kid_draw_splash(void);
|
|
|
|
/* Восстановить фон (из теневой копии) на месте ПРЕДЫДУЩЕГО кадра Kid —
|
|
* вместо перерисовки всего экрана. Звать ПЕРЕД kid_tick/kid_draw. */
|
|
void kid_heal(void);
|
|
|
|
/* Метрики последнего kid_draw для футпринта fore-over-Kid (pop_bg
|
|
* pop_fore_over_kid): obj_x — ЛОГИЧЕСКАЯ X кадра (до ×8/7), obj_y — низ
|
|
* спрайта, w/h — размер кадра. */
|
|
int kid_fp_obj_x(void);
|
|
int kid_fp_obj_y(void);
|
|
uint16_t kid_fp_width(void);
|
|
uint16_t kid_fp_height(void);
|
|
|
|
#endif
|