BUG-CTRL-FRAME-1: геометрия Кида считалась по кадру стража
cur_frame — один глобал на всех персонажей (как в оригинале), владелец — тот, кто последним прошёл load_frame. Последним в кадре тикает страж, поэтому к моменту control() Кида там лежал кадр СТРАЖА, а через kid_cur_dx/dy/flags по нему считается вся геометрия управления: dx_weight -> determine_col -> distance_to_edge_weight -> get_edge_distance -> выбор ветки в check_jump_up. Оригинал зовёт load_fram_det_col() (seg006:0144) сразу после loadkid/loadshad и ДО control() — play_kid_frame (seg000:1211) и play_guard_frame (seg000:1248). У нас этого не было. Замерено брейкпоинтом на pop_jump_up_seq: Kid x=156 col=6 кадр 15 (dx=0 weight_x=3) при кадре стража image17 (dx=-1 weight_x=8) дал curr_col=7 и distance=2 вместо 6 и 10 — то есть jump_up_plain (вернулось A=28, пустой прыжок) вместо «шаг назад на x=160 + зацеп». Предсказание по кадру стража совпало с намеренным до единицы. Отсюда же плавающее поведение: кадр стража меняется каждый тик, distance Кида скакал через порог 6 — то прыжок, то попытка зацепа с неверной X. И «голова Кида поверх плиты (1,6)» — не баг отрисовки, а следствие позы, которой в оригинале в этом месте не бывает. Фикс: pop_load_fram_det_col() (pop_kid.c) + вызовы в pop_ctrl_tick и pop_guard_tick. determine_col — только на ветке Кида: у нас он существует лишь для него (pop_map работает с Kid, а не с Char). Разбор с числами — bug_closed.md. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -450,6 +450,40 @@ void play_seq(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* load_fram_det_col (seg006:0144) = load_frame() + determine_col().
|
||||
*
|
||||
* Зачем это отдельной публичной точкой. cur_frame — ОДИН глобал на всех
|
||||
* персонажей (так и в оригинале), и его владелец — тот, кто последним
|
||||
* прошёл load_frame. В кадре последним тикает страж, поэтому к моменту
|
||||
* управления Кидом в cur_frame лежит кадр СТРАЖА. А через cur_frame
|
||||
* считается вся геометрия: dx_weight -> determine_col ->
|
||||
* distance_to_edge_weight -> get_edge_distance, то есть буквально выбор
|
||||
* ветки в check_jump_up.
|
||||
*
|
||||
* Оригинал от этого страхуется явно: play_kid_frame (seg000:1209) и
|
||||
* play_guard_frame (seg000:1246) сразу после loadkid/loadshad зовут
|
||||
* load_fram_det_col() — ДО control(). У нас этого не было, и Кид считал
|
||||
* свой прыжок по кадру стража (BUG-CTRL-FRAME-1): при distance 2 вместо 10
|
||||
* check_jump_up уходил в «пустой прыжок вверх» вместо «шаг назад и
|
||||
* зацеп». Результат менялся от кадра к кадру — вместе с анимацией стража.
|
||||
*
|
||||
* determine_col у нас существует только для Кида: pop_map работает с Kid
|
||||
* напрямую, а не с абстрактным Char. Поэтому вторую половину связки делаем
|
||||
* только на его ветке — стражу пока хватает перезагрузки самого кадра (его
|
||||
* колонку ведёт pop_guard_enter/leave). Char.curr_col синхронизируем
|
||||
* руками: окно Char — копия Kid. */
|
||||
void pop_load_fram_det_col(void)
|
||||
{
|
||||
if (!kdat_ok) return;
|
||||
gfx_w0_map(kdat_page);
|
||||
load_frame();
|
||||
gfx_w0_unmap();
|
||||
if (Char.charid == CHARID_0_KID) {
|
||||
pop_determine_col();
|
||||
Char.curr_col = Kid.curr_col;
|
||||
}
|
||||
}
|
||||
|
||||
/* Прокрутить последовательность КОНКРЕТНОГО персонажа (порт связки
|
||||
* loadkid/play_seq/savekid, seg006). Звать вместо голого play_seq: тот
|
||||
* работает с Char и сам по себе не знает, чей это персонаж. */
|
||||
|
||||
Reference in New Issue
Block a user