Переворот: перерисовка вместо отражения, переключение на границе кадра, clip_char
Три правки по следам прогона пользователя на зелье инверсии. 1. ЛИШНИЕ ЯЗЫКИ ПЛАМЕНИ. pop_flip_screen отражал уже нарисованное копией акселератора, а пламя факела ЗАПЕКАЕТСЯ в ОЗУ-копию (pop_torch_draw: heal'а у него нет, следующий кадр непрозрачно накрывает предыдущий). Отражённое вместе с фоном, оно оказывалось в зеркальной позиции, где накрывать его некому — и оставалось навсегда (уходило только после входа в комнату, который строит фон с нуля). Теперь переворот ПЕРЕРИСОВЫВАЕТ комнату тем же приёмом, что вход (ENTER-ROOM-FAST). Это совпадает с оригиналом: SDLPoP на need_redraw_because_flipped зовёт redraw_screen(0), а не отражает картинку (seg000.c:928). 2. МОМЕНТ ПЕРЕКЛЮЧЕНИЯ. Зелье выпивается из play_seq, в середине кадра, и pop_upside переключался прямо там — остаток кадра рисовался зеркально поверх ещё неперевёрнутого фона. Разделены pop_upside_want (пишут зелье, смерть, чит U) и pop_upside (читают слои); переключение — одно место, начало кадра, вместе с перерисовкой. Оригиналу этого не нужно: он всегда рисует в offscreen неперевёрнутым и зеркалит только на выводе — расхождение записано в docs/impl_diff.md. 3. CLIP_CHAR В ПЕРЕВОРОТЕ. Граница clip_char приходит в ЛОГИЧЕСКИХ координатах (y_clip), сравнивать её с уже отражённым top нельзя: то, что логически выше линии, на экране ниже неё. Теперь тот же срез применяется с другого конца — укорачивает кадр снизу (bcut), верх остаётся на месте; строки ленты не сдвигаются, потому что зеркальная лента отдаёт их в обратном порядке. Раньше в перевороте клип был отключён совсем, и висящий Кид рисовался поверх плиты. Проверено в MAME: переворот чистый, фон без остатков. tests-host 6/6.
This commit is contained in:
@@ -487,6 +487,7 @@ void pop_char_draw(uint8_t who) __banked
|
||||
uint8_t npages, page, idx, dp, flip, hurt, lskip;
|
||||
uint16_t w, h, vis_w;
|
||||
int obj_x, obj_y, fp_x, fwd, top, bx, skip, rows, ct, cr;
|
||||
int bcut; /* срез СНИЗУ (clip_char в перевёрнутом виде) */
|
||||
|
||||
/* Страховка пропуска (DRAW-COST): главный цикл мог решить, что слот
|
||||
* «тихий», и heal не звать — а тик после этого персонажа всё-таки
|
||||
@@ -581,18 +582,34 @@ void pop_char_draw(uint8_t who) __banked
|
||||
vis_w = w;
|
||||
lskip = 0;
|
||||
skip = 0;
|
||||
bcut = 0;
|
||||
/* clip_char (seg006:1231/1749): тайл над головой — стена/пол → всё
|
||||
* выше линии полосы своего ряда НЕ рисуется, иначе персонаж
|
||||
* просвечивает сквозь щели кладки при спуске/висе. */
|
||||
/* clip_char в перевёрнутом виде должен резать СНИЗУ, а не сверху
|
||||
* (тайл над головой стал тайлом под ногами) — отдельная задача
|
||||
* L9-CLIPCHAR; пока в перевороте не режем вовсе: артефакт мельче,
|
||||
* чем срезанный не с той стороны персонаж. */
|
||||
ct = pop_upside ? -1000 : pop_clip_char_top(fp_x, obj_y, w, h);
|
||||
if (ct > top) {
|
||||
skip = ct - top;
|
||||
if (skip > (int)h) skip = (int)h; /* обрезан целиком */
|
||||
top = ct;
|
||||
/* clip_char (seg006:1231/1749): тайл над головой — стена/пол → всё
|
||||
* выше линии полосы своего ряда НЕ рисуется. Граница приходит в
|
||||
* ЛОГИЧЕСКИХ координатах поля (y_clip), и при перевороте её нельзя
|
||||
* сравнивать с уже отражённым top: то, что логически «выше линии»,
|
||||
* на экране оказывается НИЖЕ неё. Поэтому в перевороте тот же
|
||||
* срез применяется с другого конца — укорачивает кадр снизу
|
||||
* (bcut), а верх (top) остаётся на месте. Строки ленты при этом
|
||||
* не сдвигаются: зеркальная лента отдаёт их в обратном порядке,
|
||||
* так что «убрать последние bcut строк вывода» = «не рисовать
|
||||
* первые bcut строк оригинала», а это ровно то, что просит
|
||||
* clip_char. */
|
||||
ct = pop_clip_char_top(fp_x, obj_y, w, h);
|
||||
if (!pop_upside) {
|
||||
if (ct > top) {
|
||||
skip = ct - top;
|
||||
if (skip > (int)h) skip = (int)h; /* обрезан целиком */
|
||||
top = ct;
|
||||
}
|
||||
} else {
|
||||
int top_log = obj_y - (int)h + 1; /* верх кадра ДО отражения */
|
||||
if (ct > top_log) {
|
||||
bcut = ct - top_log;
|
||||
if (bcut > (int)h) bcut = (int)h;
|
||||
}
|
||||
}
|
||||
/* Вторая половина clip_char: правый косяк двери уровня. Дверь
|
||||
* рисуется ПОД персонажем (вся в backtable), поэтому спрятать
|
||||
@@ -619,7 +636,7 @@ void pop_char_draw(uint8_t who) __banked
|
||||
* obj_clip_top = 0, obj_clip_bottom = 192). Персонаж, вышедший за
|
||||
* него (скелет, падающий в пропасть), обязан обрезаться: ниже поля
|
||||
* идёт полоса HP, и без клипа спрайт лез прямо на неё. */
|
||||
rows = (int)h - skip;
|
||||
rows = (int)h - skip - bcut;
|
||||
if (top < 0) { skip += -top; rows += top; top = 0; }
|
||||
if (top + rows > 192) rows = 192 - top;
|
||||
gfx_set_bank(GFX_BANK_SPRITE); /* видео-ОЗУ, без теневой копии */
|
||||
|
||||
Reference in New Issue
Block a user