PoP roomtest: полный порт bumped (seg004) — прижатие Y к полу + hardbump
Комната 5, прыжок в решётку: Kid оставался стоять на 6 пикселей выше
пола и без приземления-приседания. Шесть пикселей — это dy(-6) кадра
frame_25_standing_jump_10: удар обрывал standjump ровно между кадрами
25 и 26, парный dy(+6) не выполнялся.
От оригинального bumped() у нас был портирован только хвост (выровнять
X к грани + seq_47_bump). Добавлены недостающие ветки:
- bumped() — исход удара выбирается по тайлу, НА КОТОРОМ персонаж
оказался после отжатия (сквозь стену/верх двери это
соседняя клетка, для ворот/зеркала — сама клетка);
- bumped_floor — прижимает Y к y_land, ветка fall_y>=22 (только отжать
на 5) и выбор сиквенса по кадру: 24/25/40..42/102..106
-> seq_46_hardbump (отскок с приседанием), иначе 47;
- bumped_fall — удар выше пола на 15+ px (беззнаковое сравнение
оригинала) или не над полом: seq_45, в свободном
падении — только гашение fall_x.
Гард «уже в отскоке — не рестартить» (наш, от edge-триггера коллизий)
перенесён внутрь bumped_floor: выравнивание X/Y идёт всегда, рестарта
анимации нет. Проверено в MAME.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -431,7 +431,7 @@ Kid ставится на первый пол, `pop_trob_reset()` возвращ
|
|||||||
| 2 | | |
|
| 2 | | |
|
||||||
| 3 | | |
|
| 3 | | |
|
||||||
| 4 | | |
|
| 4 | | |
|
||||||
| 5 | | |
|
| 5 | пофикшено | прыжок в решётку: Kid оставался стоять на 6 px ВЫШЕ пола и без приземления-приседания — от `bumped()` (seg004) был портирован только хвост (`seq_47`), не хватало `bumped_floor` (прижатие Y к полу + `seq_46_hardbump` на кадрах прыжка 24/25/40..42/102..106) и `bumped_fall` |
|
||||||
| 6 | | |
|
| 6 | | |
|
||||||
| 7 | | |
|
| 7 | | |
|
||||||
| 8 | | |
|
| 8 | | |
|
||||||
|
|||||||
@@ -50,6 +50,8 @@
|
|||||||
#define SEQ_19_FALL 19 /* stepfall2 (run frames 9/13) */
|
#define SEQ_19_FALL 19 /* stepfall2 (run frames 9/13) */
|
||||||
#define SEQ_20_MEDIUM_LAND 20
|
#define SEQ_20_MEDIUM_LAND 20
|
||||||
#define SEQ_21_FALL_RUNJUMP 21
|
#define SEQ_21_FALL_RUNJUMP 21
|
||||||
|
#define SEQ_45_BUMPFALL 45 /* удар В ВОЗДУХЕ: отскок и падение */
|
||||||
|
#define SEQ_46_HARDBUMP 46 /* удар после прыжка: отскок + ПРИСЕДАНИЕ */
|
||||||
#define SEQ_47_BUMP 47 /* удар в стену: dx(-4) отскок + 50-52 + stand */
|
#define SEQ_47_BUMP 47 /* удар в стену: dx(-4) отскок + 50-52 + stand */
|
||||||
/* K4 — зацеп/вис/подтягивание/спуск */
|
/* K4 — зацеп/вис/подтягивание/спуск */
|
||||||
#define SEQ_8_GRAB_STRAIGHT 8 /* прыжок вверх и зацеп (прямо) */
|
#define SEQ_8_GRAB_STRAIGHT 8 /* прыжок вверх и зацеп (прямо) */
|
||||||
@@ -762,11 +764,58 @@ static void check_action(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* bumped_fall (seg004:0522): удар, когда под персонажем НЕ пол ИЛИ он высоко
|
||||||
|
* над полом — отскок назад и падение (seq_45). В свободном падении сиквенс
|
||||||
|
* не меняем, только гасим горизонтальную составляющую. */
|
||||||
|
static void bumped_fall(void)
|
||||||
|
{
|
||||||
|
Kid.x = (uint8_t)char_dx_forward(-4);
|
||||||
|
if (Kid.action == ACT_FREEFALL) {
|
||||||
|
Kid.fall_x = 0;
|
||||||
|
} else {
|
||||||
|
kid_set_seq(SEQ_45_BUMPFALL); /* (TODO: bumped_sound) */
|
||||||
|
play_seq();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* bumped_floor (seg004:053B): удар о стену, когда под персонажем ПОЛ.
|
||||||
|
* Портируется целиком — раньше у нас был только хвост (seq_47), из-за чего
|
||||||
|
* терялись ДВЕ вещи: прижатие Y к полу и «жёсткий» вариант удара. Симптом
|
||||||
|
* (комната 5, прыжок в решётку): standjump бампится на кадре 25 — том самом,
|
||||||
|
* где сиквенс уже сделал dy(−6), а парного dy(+6) ещё не было, — и Kid
|
||||||
|
* оставался стоять на 6 пикселей ВЫШЕ пола, без приземления-приседания. */
|
||||||
|
static void bumped_floor(void)
|
||||||
|
{
|
||||||
|
uint8_t frame;
|
||||||
|
/* Оригинал сравнивает БЕЗЗНАКОВО: если персонаж НИЖЕ уровня пола,
|
||||||
|
* разность заворачивается в большое число и тоже даёт «падать». */
|
||||||
|
if ((uint16_t)(y_land[Kid.curr_row + 1] - (int16_t)Kid.y) >= 15) {
|
||||||
|
bumped_fall(); /* высоко над полом — в воздухе */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Kid.y = (uint8_t)y_land[Kid.curr_row + 1]; /* ПРИЖАТЬ к полу */
|
||||||
|
if (Kid.fall_y >= 22) { /* влетел быстро — только отжать */
|
||||||
|
Kid.x = (uint8_t)char_dx_forward(-5);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Kid.fall_y = 0;
|
||||||
|
if (Kid.action == ACT_BUMPED) return; /* уже в отскоке — не рестартить */
|
||||||
|
frame = Kid.frame;
|
||||||
|
/* Кадры прыжков и начала падения — «жёсткий» удар с приседанием
|
||||||
|
* (24/25 = standjump, 40..42 = runjump, 102..106 = start_fall). */
|
||||||
|
if (frame == 24 || frame == 25 || (frame >= 40 && frame < 43) ||
|
||||||
|
(frame >= 102 && frame < 107))
|
||||||
|
kid_set_seq(SEQ_46_HARDBUMP);
|
||||||
|
else
|
||||||
|
kid_set_seq(SEQ_47_BUMP); /* (TODO: bumped_sound) */
|
||||||
|
play_seq();
|
||||||
|
}
|
||||||
|
|
||||||
/* check_bumped (seg004): если передний край ЗАШЁЛ за грань стены — выровнять
|
/* check_bumped (seg004): если передний край ЗАШЁЛ за грань стены — выровнять
|
||||||
* к грани И проиграть отскок seq_47_bump (dx−4 назад + кадры 50-52 + stand),
|
* к грани и отдать исход в bumped_floor/bumped_fall (порт bumped, seg004).
|
||||||
* как в оригинале (bumped_floor). Это даёт «шаг назад со звуком» при беге/
|
* Это даёт «шаг назад со звуком» при беге/шаге в стену вместо падения. Уже
|
||||||
* шаге в стену вместо падения. Уже в отскоке (action bumped) — только
|
* в отскоке (action bumped) — только выравниваем, без рестарта сиквенса.
|
||||||
* выравниваем, без рестарта. В падении/висе не трогаем. */
|
* В падении/висе не трогаем. */
|
||||||
static void check_bumped(void)
|
static void check_bumped(void)
|
||||||
{
|
{
|
||||||
uint8_t t, wt; int8_t tcol; int d;
|
uint8_t t, wt; int8_t tcol; int d;
|
||||||
@@ -842,10 +891,23 @@ static void check_bumped(void)
|
|||||||
if (d >= 0) return; /* ещё не зашёл за грань */
|
if (d >= 0) return; /* ещё не зашёл за грань */
|
||||||
Kid.x = (uint8_t)char_dx_forward((int8_t)d); /* край -> грань */
|
Kid.x = (uint8_t)char_dx_forward((int8_t)d); /* край -> грань */
|
||||||
determine_col();
|
determine_col();
|
||||||
if (Kid.action == ACT_BUMPED) return; /* уже в отскоке — не рестартить */
|
/* Хвост bumped (seg004:04E4): чем КОНЧИТСЯ удар, решает тайл, на котором
|
||||||
Kid.fall_y = 0;
|
* персонаж оказался после отжатия от грани. Сквозь стену/верх двери он
|
||||||
kid_set_seq(SEQ_47_BUMP); /* отскок (TODO: bumped_sound) */
|
* стоит на СОСЕДНЕЙ клетке (в сторону толчка), для прочих препятствий
|
||||||
play_seq();
|
* (ворота, зеркало, кусаки) — на клетке самого препятствия (у ворот пол
|
||||||
|
* есть, поэтому tile_is_floor их считает полом). */
|
||||||
|
{
|
||||||
|
uint8_t ct = t;
|
||||||
|
if (Kid.direction < 0) { /* смотрит влево => толчок ВПРАВО */
|
||||||
|
if (ct == TILE_DOORTOP || ct == TILE_DOORTOP_FLOOR || ct == TILE_WALL)
|
||||||
|
ct = get_tile((int8_t)(tcol + 1), Kid.curr_row);
|
||||||
|
} else { /* смотрит вправо => толчок ВЛЕВО */
|
||||||
|
if (ct == TILE_WALL)
|
||||||
|
ct = get_tile((int8_t)(tcol - 1), Kid.curr_row);
|
||||||
|
}
|
||||||
|
if (tile_is_floor(ct)) bumped_floor();
|
||||||
|
else bumped_fall();
|
||||||
|
}
|
||||||
determine_col();
|
determine_col();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user