PoP roomtest: интерпретатор последовательностей стал общим (Char) — стражи
Пункт 1 плана стражей. play_seq был прибит к Киду, поэтому страж стоял на захардкоженном кадре 166. Теперь как в оригинале: интерпретатор работает с АКТИВНЫМ персонажем Char, а вокруг стоят loadkid/savekid и loadshad/saveshad (порт seg006:809..825). Почему копия, а не указатель: так в оригинале, и на Z80 это быстрее — горячий цикл обращается к глобалу абсолютной адресацией, а 16-байтовое копирование платится один раз на переключение персонажа, тогда как указатель дал бы индексную адресацию в каждом обращении. Сопутствующее: - kid_t и pop_char_t слиты в один pop_char_t (pop_char.h): в оригинале char_type один на всех, и без этого общий интерпретатор невозможен. Kid получил поля room/charid/sword/alive — они и так нужны боёвке; - load_frame выбирает таблицу кадров по Char.charid (у стража своя, frame_tbl_guard с индексом frame + add_frame − 149, seg006:0293); - cur_frame разведён на два кэша: страж тикает ПОСЛЕ Кида, и без этого kid_draw брал бы кадр стража. savekid/saveshad раскладывают кадр по своему персонажу; - kid_set_seq пишет ИМЕННО Kid (его зовут pop_ctrl/pop_map вне окна Char, иначе loadkid затёр бы), для окна Char добавлен pop_char_set_seq — порт seqtbl_offset_char; - в pop_map 9 голых play_seq() заменены на pop_kid_play() (load+play+save); - страж входит в комнату через seq_77_guard_stand_inactive (seg002:0208), а не через прибитый кадр. Проверено в MAME: Kid бегает и упирается в стену как прежде, в комнате 12 плиты проваливаются со щебнем (правка задела 9 вызовов play_seq в физике), страж в комнате 3 рисуется в той же позе, но теперь curr_seq=0x19A9 и charid=2 — кадр получен прокруткой последовательности, а не константой. Бюджет (комната 3, 150 кадров): 380 292..381 282 тактов против 370 140..371 160 до правки, то есть +10 150 (+2.7 %). Основное — не копии Char, а то, что страж теперь реально крутит интерпретатор каждый кадр, а раньше стоял замороженным. 0.887 кадра, запас 48 718. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -14,9 +14,13 @@
|
||||
* seg004 fight/collision) добавляются сюда.
|
||||
*/
|
||||
#include "pop_guard.h"
|
||||
#include "pop_kid.h"
|
||||
|
||||
void pop_guard_tick(void) __banked
|
||||
{
|
||||
if (Guard.charid == 0) return; /* стража в комнате нет */
|
||||
/* Анимация: та же seqtbl, что у Кида, но своя таблица кадров —
|
||||
* выбирается по Char.charid внутри load_frame (seg006:0293). */
|
||||
pop_guard_play();
|
||||
/* TODO: порт control_guard/fight (seg005/seg004) — состояние в Guard. */
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* pop_char.h — состояние ПЕРСОНАЖА, общее для Кида, стража и активной
|
||||
* копии Char. Порт char_type (types.h:302).
|
||||
*
|
||||
* Зачем отдельным заголовком: интерпретатор последовательностей в
|
||||
* оригинале один на всех (работает с Char, а вокруг стоят
|
||||
* loadkid/savekid и loadshad/saveshad, seg006:809). Пока у Кида был свой
|
||||
* усечённый тип, а у стража свой, общий интерпретатор был невозможен.
|
||||
* Поля и их порядок — как в char_type, чтобы порт seg005/seg006 ложился
|
||||
* один в один.
|
||||
*/
|
||||
#ifndef POP_CHAR_H
|
||||
#define POP_CHAR_H
|
||||
|
||||
#include <stdint.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 room;
|
||||
uint8_t repeat;
|
||||
uint8_t charid; /* 0 = Kid, 2 = страж (см. CHARID_* в pop_guard.h) */
|
||||
uint8_t sword;
|
||||
int8_t alive; /* -1 = жив (как в оригинале), 0 = убит */
|
||||
uint16_t curr_seq; /* адрес в seqtbl (база SEQTBL_BASE) */
|
||||
} pop_char_t;
|
||||
|
||||
#endif
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "pop_guard.h"
|
||||
#include "pop_geom.h"
|
||||
#include "pop_level.h"
|
||||
#include "pop_kid.h" /* pop_kid_data_frame — таблицы в EMM-странице */
|
||||
#include "pop_kid.h" /* Char/play_seq — интерпретатор общий */
|
||||
#include "kid_data.h"
|
||||
|
||||
pop_char_t Guard;
|
||||
@@ -80,12 +80,13 @@ void pop_guard_enter(uint8_t room)
|
||||
Guard.alive = -1;
|
||||
Guard.action = 1; /* actions_1_run_jump */
|
||||
Guard.fall_x = Guard.fall_y = 0;
|
||||
/* seq_77_guard_stand_inactive даёт кадр 166 (frame_166_stand_inactive,
|
||||
* seqtbl.c:266). Интерпретатор последовательностей для стража придёт
|
||||
* вместе с ИИ (следующая фаза) — сейчас ставим кадр напрямую, чтобы
|
||||
* страж просто СТОЯЛ и было что рисовать/убивать читом. */
|
||||
Guard.frame = 166;
|
||||
guardhp_max = guardhp_curr = 3; /* get_guard_hp: skill 0, уровень 1 */
|
||||
guardhp_delta = 0;
|
||||
pop_guard_load_frame();
|
||||
/* enter_guard (seg002:0208): seqtbl_offset_char(seq_77_guard_stand_inactive).
|
||||
* Последовательность крутит общий интерпретатор (pop_guard_play), а
|
||||
* таблицу кадров он выбирает по Char.charid — у стража своя. */
|
||||
pop_loadshad();
|
||||
pop_char_set_seq(SEQ_77_GUARD_STAND_INACTIVE);
|
||||
pop_saveshad();
|
||||
pop_guard_play(); /* до первого кадра */
|
||||
}
|
||||
|
||||
@@ -19,6 +19,10 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include "kid_data.h" /* kframe */
|
||||
#include "pop_char.h"
|
||||
|
||||
/* seqids (types.h:1070) — последовательности стража. */
|
||||
#define SEQ_77_GUARD_STAND_INACTIVE 77
|
||||
|
||||
/* charids (types.h:320) — нужны хотя бы для «скелет не убивается читом». */
|
||||
#define CHARID_0_KID 0
|
||||
@@ -27,20 +31,7 @@
|
||||
#define CHARID_4_SKELETON 4
|
||||
#define CHARID_5_PRINCESS 5
|
||||
|
||||
typedef struct {
|
||||
uint8_t frame;
|
||||
uint8_t x, y;
|
||||
int8_t direction;
|
||||
int8_t curr_col, curr_row;
|
||||
uint8_t action;
|
||||
int8_t fall_x, fall_y;
|
||||
uint8_t room;
|
||||
uint8_t repeat;
|
||||
uint8_t charid;
|
||||
uint8_t sword;
|
||||
int8_t alive; /* -1 = жив (как в оригинале), 0 = убит */
|
||||
uint16_t curr_seq;
|
||||
} pop_char_t;
|
||||
/* Тип персонажа — в pop_char.h (общий с Кидом и Char). */
|
||||
|
||||
extern pop_char_t Guard; /* страж ТЕКУЩЕЙ комнаты (как в оригинале) */
|
||||
extern uint8_t guardhp_curr, guardhp_max;
|
||||
|
||||
@@ -10,12 +10,13 @@
|
||||
#include <gfx.h>
|
||||
#include <sprite.h>
|
||||
#include "pop_kid.h"
|
||||
#include "pop_guard.h" /* Guard/pop_gframe/CHARID_* — интерпретатор общий */
|
||||
#include "pop_bg.h" /* POP_YOFF — вертикальное центрирование */
|
||||
#include "pop_map.h" /* pop_clip_char_top (clip_char) */
|
||||
#include "pop_geom.h"
|
||||
#include "kid_data.h"
|
||||
|
||||
kid_t Kid;
|
||||
pop_char_t Kid;
|
||||
|
||||
/* Флаг сотрясения (seg006 knock): ставится seqtbl-командой KNOCK_UP/DOWN
|
||||
* в play_seq, потребляется pop_check_knock (pop_map) — трясёт loose-полы. */
|
||||
@@ -98,6 +99,16 @@ static const uint8_t *kd_frame_ptr(uint8_t i)
|
||||
off += (uint16_t)(KD_DATA_OFF + KID_BIN_FRAMES_OFF);
|
||||
return (const uint8_t *)off;
|
||||
}
|
||||
|
||||
/* То же для таблицы кадров СТРАЖА (frame_tbl_guard дописана в ту же
|
||||
* страницу данных, см. pop_extract_kid_data.py). */
|
||||
static const uint8_t *kd_gframe_ptr(uint8_t i)
|
||||
{
|
||||
uint16_t off = (uint16_t)i;
|
||||
off += (uint16_t)(off << 2);
|
||||
off += (uint16_t)(KD_DATA_OFF + KID_BIN_GFRAMES_OFF);
|
||||
return (const uint8_t *)off;
|
||||
}
|
||||
#define KD_SEQ(cs) (*((const uint8_t *)(KD_DATA_OFF + KID_BIN_SEQTBL_OFF) + \
|
||||
(uint16_t)((cs) - SEQTBL_BASE)))
|
||||
/* Байт seqtbl по адресу оригинала (база SEQTBL_BASE); ТОЛЬКО под замапленной
|
||||
@@ -106,8 +117,25 @@ static const uint8_t *kd_frame_ptr(uint8_t i)
|
||||
|
||||
static uint8_t kdat_blk, kdat_page, kdat_ok;
|
||||
|
||||
/* Текущий кадр (порт глобала cur_frame, seg006): 5 байт вместо таблицы. */
|
||||
/* Текущий кадр (порт глобала cur_frame, seg006): 5 байт вместо таблицы.
|
||||
* Заполняется load_frame для АКТИВНОГО персонажа (Char), поэтому на
|
||||
* выходе из play_seq его надо сохранить в кэш своего персонажа: страж
|
||||
* тикает ПОСЛЕ Кида, и без разделения kid_draw взял бы кадр стража. */
|
||||
static kframe cur_frame;
|
||||
static kframe kid_frame; /* кадр Kid для kid_draw */
|
||||
|
||||
/* Char (seg006): АКТИВНЫЙ персонаж. Интерпретатор последовательностей в
|
||||
* оригинале работает не с Kid и не с Guard, а с этой копией, а вокруг
|
||||
* стоят loadkid/savekid и loadshad/saveshad (seg006:809..825). Копия, а
|
||||
* не указатель, — и так же, как в оригинале, и быстрее на Z80: обращения
|
||||
* в горячем цикле идут абсолютной адресацией глобала, а 16-байтовое
|
||||
* копирование платится один раз на переключение персонажа. */
|
||||
pop_char_t Char;
|
||||
|
||||
void pop_loadkid(void) { Char = Kid; }
|
||||
void pop_savekid(void) { Kid = Char; kid_frame = cur_frame; }
|
||||
void pop_loadshad(void) { Char = Guard; }
|
||||
void pop_saveshad(void) { Guard = Char; pop_gframe = cur_frame; }
|
||||
|
||||
int pop_kid_data_load(const char *path)
|
||||
{
|
||||
@@ -166,7 +194,19 @@ void pop_kid_data_frame(uint16_t tbl_off, uint8_t idx, uint8_t *out5)
|
||||
* cur_frame. Звать ТОЛЬКО когда страница данных замаплена в W0. */
|
||||
static void load_frame(void)
|
||||
{
|
||||
const uint8_t *f = kd_frame_ptr(Kid.frame);
|
||||
/* Таблица кадров зависит от персонажа (seg006:0293): у Kid своя, у
|
||||
* стража frame_tbl_guard с индексом frame + add_frame − 149, где
|
||||
* add_frame = 70 для кадров 102..106 (seg006:535). */
|
||||
const uint8_t *f;
|
||||
if (Char.charid == CHARID_2_GUARD) {
|
||||
int16_t idx = (int16_t)Char.frame;
|
||||
if (idx >= 102 && idx < 107) idx += 70;
|
||||
idx -= 149;
|
||||
if (idx < 0 || idx >= KID_NGFRAMES) { cur_frame.image = 255; return; }
|
||||
f = kd_gframe_ptr((uint8_t)idx);
|
||||
} else {
|
||||
f = kd_frame_ptr(Char.frame);
|
||||
}
|
||||
cur_frame.image = f[0];
|
||||
cur_frame.dx = (int8_t)f[1];
|
||||
cur_frame.dy = (int8_t)f[2];
|
||||
@@ -176,8 +216,8 @@ static void load_frame(void)
|
||||
|
||||
static uint8_t char_dx_forward(int8_t dx)
|
||||
{
|
||||
if (Kid.direction < 0) dx = (int8_t)-dx;
|
||||
return (uint8_t)(Kid.x + dx);
|
||||
if (Char.direction < 0) dx = (int8_t)-dx;
|
||||
return (uint8_t)(Char.x + dx);
|
||||
}
|
||||
|
||||
/* Аксессоры к текущему кадру (для pop_map): читают cur_frame, НЕ таблицу —
|
||||
@@ -189,6 +229,11 @@ uint8_t kid_cur_flags(void) { return cur_frame.flags; }
|
||||
* pop_ctrl/pop_map зовут ЕЁ, а не дублируют kid_seq_off/kid_seqtbl). */
|
||||
void kid_set_seq(uint8_t seq_id) { Kid.curr_seq = kid_seq_off[seq_id]; }
|
||||
|
||||
/* То же для АКТИВНОГО персонажа — внутри окна Char (порт
|
||||
* seqtbl_offset_char, seg006). Нужен стражу: его последовательность
|
||||
* ставится, когда Char уже загружен из Guard. */
|
||||
void pop_char_set_seq(uint8_t seq_id) { Char.curr_seq = kid_seq_off[seq_id]; }
|
||||
|
||||
/* play_seq (seg006.c:570): крутит опкоды до КАДРА (байт < 0xF0).
|
||||
* Страница данных маппится в W0 на ВЕСЬ разбор — один map/unmap за вызов
|
||||
* (в тике, до отрисовки: конфликта с атласом в W0 нет). В конце —
|
||||
@@ -198,42 +243,42 @@ void play_seq(void)
|
||||
if (!kdat_ok) return;
|
||||
gfx_w0_map(kdat_page);
|
||||
for (;;) {
|
||||
uint8_t cmd = SEQ(Kid.curr_seq);
|
||||
Kid.curr_seq++;
|
||||
uint8_t cmd = SEQ(Char.curr_seq);
|
||||
Char.curr_seq++;
|
||||
switch (cmd) {
|
||||
case 0xFB: /* DX */
|
||||
Kid.x = char_dx_forward((int8_t)SEQ(Kid.curr_seq));
|
||||
Kid.curr_seq++;
|
||||
Char.x = char_dx_forward((int8_t)SEQ(Char.curr_seq));
|
||||
Char.curr_seq++;
|
||||
break;
|
||||
case 0xFA: /* DY */
|
||||
Kid.y = (uint8_t)(Kid.y + (int8_t)SEQ(Kid.curr_seq));
|
||||
Kid.curr_seq++;
|
||||
Char.y = (uint8_t)(Char.y + (int8_t)SEQ(Char.curr_seq));
|
||||
Char.curr_seq++;
|
||||
break;
|
||||
case 0xFE: /* FLIP */
|
||||
Kid.direction = (int8_t)~Kid.direction;
|
||||
Char.direction = (int8_t)~Char.direction;
|
||||
break;
|
||||
case 0xF7: /* JMP_IF_FEATHER: нет пера -> пропустить адрес */
|
||||
Kid.curr_seq += 2;
|
||||
Char.curr_seq += 2;
|
||||
break;
|
||||
case 0xFF: { /* JMP */
|
||||
uint16_t a = (uint16_t)(SEQ(Kid.curr_seq) |
|
||||
((uint16_t)SEQ((uint16_t)(Kid.curr_seq + 1)) << 8));
|
||||
Kid.curr_seq = a;
|
||||
uint16_t a = (uint16_t)(SEQ(Char.curr_seq) |
|
||||
((uint16_t)SEQ((uint16_t)(Char.curr_seq + 1)) << 8));
|
||||
Char.curr_seq = a;
|
||||
break;
|
||||
}
|
||||
case 0xFD: /* UP */
|
||||
Kid.curr_row--;
|
||||
Char.curr_row--;
|
||||
break;
|
||||
case 0xFC: /* DOWN */
|
||||
Kid.curr_row++;
|
||||
Char.curr_row++;
|
||||
break;
|
||||
case 0xF9: /* ACTION */
|
||||
Kid.action = SEQ(Kid.curr_seq);
|
||||
Kid.curr_seq++;
|
||||
Char.action = SEQ(Char.curr_seq);
|
||||
Char.curr_seq++;
|
||||
break;
|
||||
case 0xF8: /* SET_FALL */
|
||||
Kid.fall_x = (int8_t)SEQ(Kid.curr_seq); Kid.curr_seq++;
|
||||
Kid.fall_y = (int8_t)SEQ(Kid.curr_seq); Kid.curr_seq++;
|
||||
Char.fall_x = (int8_t)SEQ(Char.curr_seq); Char.curr_seq++;
|
||||
Char.fall_y = (int8_t)SEQ(Char.curr_seq); Char.curr_seq++;
|
||||
break;
|
||||
case 0xF5: /* KNOCK_UP: сотрясение трясёт loose РЯДОМ ВЫШЕ (check_knock) */
|
||||
knock = 1;
|
||||
@@ -242,20 +287,20 @@ void play_seq(void)
|
||||
knock = -1;
|
||||
break;
|
||||
case 0xF2: /* SOUND — потребить 1 байт */
|
||||
Kid.curr_seq++;
|
||||
Char.curr_seq++;
|
||||
break;
|
||||
case 0xF1: /* END_LEVEL */
|
||||
break;
|
||||
case 0xF3: /* GET_ITEM: аргумент 1 — применить эффект предмета
|
||||
* (порт play_seq -> proc_get_object, seg006) */
|
||||
if (SEQ(Kid.curr_seq) == 1)
|
||||
if (SEQ(Char.curr_seq) == 1)
|
||||
pop_proc_get_object();
|
||||
Kid.curr_seq++;
|
||||
Char.curr_seq++;
|
||||
break;
|
||||
case 0xF6: /* DIE nop */
|
||||
break;
|
||||
default: /* КАДР */
|
||||
Kid.frame = cmd;
|
||||
Char.frame = cmd;
|
||||
load_frame(); /* cur_frame := таблица[frame] (страница ещё в W0) */
|
||||
gfx_w0_unmap();
|
||||
return;
|
||||
@@ -263,6 +308,12 @@ void play_seq(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* Прокрутить последовательность КОНКРЕТНОГО персонажа (порт связки
|
||||
* loadkid/play_seq/savekid, seg006). Звать вместо голого play_seq: тот
|
||||
* работает с Char и сам по себе не знает, чей это персонаж. */
|
||||
void pop_kid_play(void) { pop_loadkid(); play_seq(); pop_savekid(); }
|
||||
void pop_guard_play(void) { pop_loadshad(); play_seq(); pop_saveshad(); }
|
||||
|
||||
void kid_init(uint8_t seq_id, int8_t col, int8_t row, int8_t dir)
|
||||
{
|
||||
Kid.curr_col = col;
|
||||
@@ -272,13 +323,14 @@ void kid_init(uint8_t seq_id, int8_t col, int8_t row, int8_t dir)
|
||||
Kid.y = (uint8_t)pop_y_land[row + 1];
|
||||
Kid.fall_x = Kid.fall_y = 0;
|
||||
Kid.repeat = 0;
|
||||
Kid.charid = 0; /* charid_0_kid: своя таблица кадров */
|
||||
Kid.curr_seq = kid_seq_off[seq_id];
|
||||
play_seq(); /* до первого кадра */
|
||||
pop_kid_play(); /* до первого кадра */
|
||||
}
|
||||
|
||||
void kid_tick(void)
|
||||
{
|
||||
play_seq();
|
||||
pop_kid_play();
|
||||
}
|
||||
|
||||
/* Отрисовка текущего кадра: obj_x=(char_x+dx)*2-116, obj_y=char_y+dy
|
||||
@@ -387,7 +439,7 @@ void kid_heal(void)
|
||||
|
||||
void kid_draw(void)
|
||||
{
|
||||
kframe fr = cur_frame; /* load_frame уже положил кадр (play_seq) */
|
||||
kframe fr = kid_frame; /* кадр Kid, сохранённый savekid */
|
||||
int fwd, obj_x, obj_y, top;
|
||||
uint8_t page, idx;
|
||||
const uint8_t *img;
|
||||
|
||||
@@ -11,20 +11,10 @@
|
||||
#define POP_KID_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "pop_char.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;
|
||||
/* Состояние персонажа — общий тип для Кида, стража и Char (pop_char.h). */
|
||||
extern pop_char_t Kid;
|
||||
|
||||
/* Флаг сотрясения (seg006 knock): +1 = KNOCK_UP (ряд выше), -1 = KNOCK_DOWN
|
||||
* (свой ряд). Ставит play_seq, читает/сбрасывает pop_check_knock. */
|
||||
@@ -63,7 +53,22 @@ void kid_tick(void);
|
||||
|
||||
/* play_seq напрямую (для pop_map start_fall — переход в fall-seq в тот же
|
||||
* physics-шаг, как оригинал). */
|
||||
void play_seq(void);
|
||||
void play_seq(void); /* работает с Char — см. pop_kid_play ниже */
|
||||
|
||||
/* Активный персонаж (порт Char, seg006) и его загрузка/выгрузка.
|
||||
* Интерпретатор последовательностей общий для Kid и стража: у них общая
|
||||
* seqtbl, но РАЗНЫЕ таблицы кадров (load_frame выбирает по Char.charid). */
|
||||
extern pop_char_t Char;
|
||||
void pop_loadkid(void);
|
||||
void pop_savekid(void);
|
||||
void pop_loadshad(void);
|
||||
void pop_saveshad(void);
|
||||
|
||||
/* Прокрутить последовательность персонажа целиком (load + play_seq +
|
||||
* save). Звать вместо голого play_seq. */
|
||||
void pop_char_set_seq(uint8_t seq_id); /* seq активного персонажа */
|
||||
void pop_kid_play(void);
|
||||
void pop_guard_play(void);
|
||||
|
||||
/* Поля текущего кадра kid_frames[Kid.frame] (pop_map, без дублирования
|
||||
* таблицы во втором TU). */
|
||||
|
||||
@@ -442,7 +442,7 @@ static void land(void)
|
||||
if (deadly || take_hp(1)) { /* 3+ этажа или последнее HP */
|
||||
take_hp(100);
|
||||
kid_set_seq(SEQ_22_CRUSHED);
|
||||
play_seq();
|
||||
pop_kid_play();
|
||||
determine_col();
|
||||
pop_kid_dead = 1;
|
||||
return;
|
||||
@@ -451,7 +451,7 @@ static void land(void)
|
||||
}
|
||||
Kid.fall_x = Kid.fall_y = 0;
|
||||
kid_set_seq(seq);
|
||||
play_seq();
|
||||
pop_kid_play();
|
||||
determine_col();
|
||||
}
|
||||
|
||||
@@ -465,7 +465,7 @@ static void start_fall(void)
|
||||
else if (frame == 44) seq = SEQ_21_FALL_RUNJUMP;
|
||||
else seq = SEQ_7_FALL; /* frame 9 + stand/step/crouch */
|
||||
kid_set_seq(seq);
|
||||
play_seq();
|
||||
pop_kid_play();
|
||||
determine_col();
|
||||
/* Проверки «упал в стену» — ТОЛЬКО пока персонаж В комнате (curr_row<=2).
|
||||
* Ниже нижнего ряда (curr_row=3 после inc — падение сквозь дыру loose)
|
||||
@@ -531,7 +531,7 @@ static void check_grab(void)
|
||||
Kid.y = (uint8_t)pop_y_land[Kid.curr_row + 1];
|
||||
Kid.fall_y = 0;
|
||||
kid_set_seq(SEQ_15_GRAB_LEDGE_MIDAIR);
|
||||
play_seq();
|
||||
pop_kid_play();
|
||||
determine_col();
|
||||
grab_timer = 12; /* (TODO: sound grab) */
|
||||
}
|
||||
@@ -886,7 +886,7 @@ static void bumped_fall(void)
|
||||
Kid.fall_x = 0;
|
||||
} else {
|
||||
kid_set_seq(SEQ_45_BUMPFALL); /* (TODO: bumped_sound) */
|
||||
play_seq();
|
||||
pop_kid_play();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -920,7 +920,7 @@ static void bumped_floor(void)
|
||||
kid_set_seq(SEQ_46_HARDBUMP);
|
||||
else
|
||||
kid_set_seq(SEQ_47_BUMP); /* (TODO: bumped_sound) */
|
||||
play_seq();
|
||||
pop_kid_play();
|
||||
}
|
||||
|
||||
/* check_bumped (seg004): если передний край ЗАШЁЛ за грань стены — выровнять
|
||||
@@ -1157,14 +1157,14 @@ static void fell_on_your_head(void)
|
||||
pop_kid_hurt = 1; /* hitp_delta<0 → draw_hurt_splash */
|
||||
if (take_hp(1)) {
|
||||
kid_set_seq(SEQ_22_CRUSHED);
|
||||
play_seq();
|
||||
pop_kid_play();
|
||||
determine_col();
|
||||
pop_kid_dead = 1;
|
||||
} else if (frame != FRAME_109_CROUCH) {
|
||||
if (get_tile_behind_char() == TILE_EMPTY)
|
||||
Kid.x = (uint8_t)char_dx_forward(-2);
|
||||
kid_set_seq(SEQ_52_LOOSE_FELL_ON_KID);
|
||||
play_seq();
|
||||
pop_kid_play();
|
||||
determine_col();
|
||||
}
|
||||
}
|
||||
@@ -1430,7 +1430,7 @@ static void spiked(uint8_t tilepos)
|
||||
Kid.fall_y = 0;
|
||||
take_hp(100); /* (TODO: sound_48_spiked) */
|
||||
kid_set_seq(SEQ_51_SPIKED);
|
||||
play_seq();
|
||||
pop_kid_play();
|
||||
determine_col();
|
||||
pop_kid_dead = 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user