cf06896dbd
Инфраструктура пункта 2. В оригинале у соперника НЕТ своего диспетчера: autocontrol_* (seg002) выставляет те же глобалы control_*, что и ввод игрока, а дальше исполняется тот же control() (seg005:252). Значит перед портом ИИ надо было привести к этому обе половины: - control_forward/backward/up/down/shift2 перестали быть static в pop_ctrl.c — это общая шина синтетического ввода, объявлена в pop_ctrl.h вместе с POP_CONTROL_*; - control() переименован в pop_control() и работает с Char, а не с Kid; - ввод игрока обёрнут в окно Char (loadkid/user_control/savekid), как в play_frame оригинала. Ловушка по дороге (ввод отвалился целиком, Kid не двигался): макрос seqtbl_offset_char вёл на kid_set_seq, который пишет прямо в Kid, а следом savekid затирал Kid копией Char со старой curr_seq. В оригинале seqtbl_offset_char работает именно с Char — макрос переведён на pop_char_set_seq. kid_set_seq остался для вызовов ВНЕ окна (pop_map). Добавлен pop_savekid_state (Kid = Char без кадра): control() кадр не трогает, а cur_frame в этот момент принадлежит тому, кто последним крутил play_seq. Проверено в MAME: бег и упор в стену работают как прежде. Бюджет (комната 3, 125 кадров): 382 584..383 064 против 380 292..381 282, то есть +2 300 тактов на копии окна. 0.891 кадра, запас 46 936. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
51 lines
2.9 KiB
C
51 lines
2.9 KiB
C
/*
|
|
* pop_ctrl.h — управление Kid (Фаза K2b): порт диспетчера control()
|
|
* (SDLPoP seg005.c) + модель ввода read_user_control/user_control
|
|
* (seg006.c) поверх held-state клавиатуры <kbd_raw.h>.
|
|
*
|
|
* Kid-only подмножество: без меча и стражи. Map-запросы (стена/край/
|
|
* захват) ЗАСТАБЛЕНЫ «открытый пол» — реальная коллизия (стоп у стены,
|
|
* падение в ямы, повисание) приходит в K3/K4. Даёт отклик на клавиши:
|
|
* бег влево/вправо, разворот, стоп, присед, прыжок с места, прыжок в
|
|
* беге, присед-прыжок.
|
|
*
|
|
* Раскладка (kbd_raw, PS/2 Set 2): ←/→ = движение, ↓ = присед, ↑ =
|
|
* прыжок вверх (с →), Shift = осторожный шаг (K3). ESC — выход (проверяет
|
|
* приложение сам, канал raw забирает весь ввод у DSS).
|
|
*/
|
|
#ifndef POP_CTRL_H
|
|
#define POP_CTRL_H
|
|
|
|
#include <stdint.h>
|
|
|
|
/* Открыть raw-канал клавиатуры и обнулить память авто-повтора.
|
|
* 0 — OK, -1 — ошибка (EBUSY и пр., см. kbd_raw_open). */
|
|
int pop_ctrl_init(void);
|
|
void pop_ctrl_close(void);
|
|
|
|
/* Один кадр ввода: прочитать клавиши -> обновить control_* -> прогнать
|
|
* диспетчер control() (может сменить Kid.curr_seq). Звать ПЕРЕД
|
|
* kid_tick() (play_seq продолжит с новой последовательности). */
|
|
void pop_ctrl_tick(void);
|
|
|
|
/* control_shift зажат ПРЯМО СЕЙЧАС? — для check_grab в физике (pop_map):
|
|
* зацеп за уступ в падении по Shift. Валидно после pop_ctrl_tick. */
|
|
int8_t pop_ctrl_shift_held(void);
|
|
|
|
/* ---- Шина синтетического ввода (порт глобалов control_* из seg005) ----
|
|
* В оригинале ИИ соперника (autocontrol_*, seg002) не имеет своего
|
|
* диспетчера: он ВЫСТАВЛЯЕТ эти переменные, а дальше исполняется тот же
|
|
* control(), что и для игрока. Значения — CONTROL_RELEASED/IGNORE/HELD. */
|
|
#define POP_CONTROL_RELEASED 0
|
|
#define POP_CONTROL_IGNORE 1
|
|
#define POP_CONTROL_HELD (-1)
|
|
extern int8_t control_forward, control_backward, control_up, control_down,
|
|
control_shift2;
|
|
|
|
/* Диспетчер (seg005:252) для АКТИВНОГО персонажа Char. Игрок идёт через
|
|
* pop_ctrl_tick (тот делает user_control с зеркалом «вперёд»), страж — из
|
|
* своего тика напрямую. */
|
|
void pop_control(void);
|
|
|
|
#endif
|