PoP roomtest: отрисовка стража в резидент W3 + fore-окклюзия + off-by-one спрайта
Разгрузка W1/W2 перед ИИ стражей (вариант 2 из двух обсуждённых). 1. pop_guard.c разделён по окнам: состояние/логика (Guard, HP, enter, kill, load_frame) остаются в W1/W2 — их обязан видеть банк guards.c; ОТРИСОВКА уехала в новый pop_gdraw.c, собираемый как --w3 (резидент). Правило границы: резидент = только то, что рисует и зовётся исключительно из главного цикла. Кадр стража стал глобальным (pop_gframe): заполняет логика, читает резидент. 2. Страж не окклюдировался передними гранями тайлов — рисовался поверх столба. В оригинале любой Char это запись midtable, а foretable рисуется после всех midtable (draw_tile_fore, seg008:690), т.е. столб перекрывает всех одинаково. Футпринт персонажа выделен из pop_fore_over_kid в char_footprint(), поверх него добавлен pop_fore_over_char() — слой fore + полоса потолка, без оверлеев поз виса/полёта/подъёма (у стража их нет; появятся — портируем redraw_at_char2 общим кодом, а не догадками). 3. Упаковщик стража: тот же off-by-one, что уже ловили у Kid. load_chtab_from_file(id_chtab_5_guard, 750) даёт images[0] = res751, а рисование индексирует images[frame.image] — значит image=N это res(751+N), а не res(750+N). Из-за сдвига frame_166_stand_inactive рисовался как res767 (выпад) вместо res768 (стойка). Проверено в MAME: страж в комнатах 3 и 21 стоит в правильной позе; окклюзия подтверждена патчем Guard.x в живой сессии — при заходе за столб спрайт корректно срезается его передней гранью. Память: _CODE 26 149 -> 25 703, куча W2 805 -> 1245 Б, резидент W3 11 656 -> 12 819 (свободно 3565 Б), банк 1 236/16384 Б. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -28,12 +28,20 @@ PAL_BASE = 0x90 # слоты палитры Sprinter под страж
|
||||
COLOR = 2 # level.guards_color обоих стражей уровня 1
|
||||
SHIFT = 3 # g[id>>3], idx id&7 (спрайты крупные)
|
||||
MASK = (1 << SHIFT) - 1
|
||||
MAX_ID = 34 # res751..res784
|
||||
MAX_ID = 33 # атлас-индексы 0..33 = res751..res784
|
||||
|
||||
|
||||
def load_guard(id):
|
||||
"""id -> res(750+id).png -> (w, h, 8bpp COLUMN-MAJOR); 0 -> 0xFF (прозр.)."""
|
||||
path = os.path.join(GUARD_DIR, f"res{750 + id}.png")
|
||||
"""Атлас-индекс id (== frame.image) -> res(751+id).png -> (w, h, 8bpp
|
||||
COLUMN-MAJOR); 0 -> 0xFF (прозрачность).
|
||||
|
||||
Off-by-one как у Kid (см. pop_pack_kid.load_kid): load_chtab_from_file
|
||||
зовётся с ресурсом 750, а images[i-1] = res(750+i), то есть images[0] =
|
||||
res751. Рисование берёт get_image(chtab, obj_id+1 − 1) = images[image],
|
||||
значит frame.image=N -> res(751+N). С res(750+N) страж стоял в позе
|
||||
предыдущего кадра (замечено на frame_166_stand_inactive: image 17
|
||||
рисовался как res767 — выпад — вместо res768). """
|
||||
path = os.path.join(GUARD_DIR, f"res{751 + id}.png")
|
||||
if not os.path.exists(path):
|
||||
return None
|
||||
im = Image.open(path)
|
||||
@@ -55,7 +63,7 @@ def main():
|
||||
os.makedirs(OUT_DIR, exist_ok=True)
|
||||
pages = {}
|
||||
n = 0
|
||||
for id in range(1, MAX_ID + 1):
|
||||
for id in range(0, MAX_ID + 1):
|
||||
g = load_guard(id)
|
||||
if g is None:
|
||||
continue
|
||||
|
||||
Reference in New Issue
Block a user