Переворот: перерисовка вместо отражения, переключение на границе кадра, 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:
@@ -209,3 +209,39 @@ for (short column = 9; column >= 0; --column) {
|
||||
|
||||
**Что проверять при регрессе.** Уровень 2, комната 13, зелье `(1,3)`: выпить —
|
||||
HP убавляется на единицу, экран краснеет РОВНО один раз (без двойного строба).
|
||||
|
||||
---
|
||||
|
||||
## Переворот (зелье инверсии) применяется НА ГРАНИЦЕ КАДРА, а не мгновенно
|
||||
|
||||
**Оригинал** (`toggle_upside`, seg000:15E9): `upside_down = ~upside_down` и
|
||||
`need_redraw_because_flipped = 1` — флаг переключается прямо в момент глотка,
|
||||
то есть в середине кадра. Оригиналу это ничего не стоит: он ВСЕГДА рисует в
|
||||
offscreen неперевёрнутым, а зеркалит только при выводе на экран
|
||||
(`flip_screen` вокруг `copy_screen_rect`, seg000:939/946). Внутренние
|
||||
координаты у него от переворота не зависят вообще.
|
||||
|
||||
**Мы** offscreen-буфера не имеем (две видеостраницы + теневая ОЗУ-копия на
|
||||
каждую), поэтому рисуем зеркально сразу — переворот «зашит» в координаты
|
||||
каждого слоя. Из-за этого момент переключения важен: зелье выпивается из
|
||||
`play_seq`, то есть в СЕРЕДИНЕ кадра, и остаток кадра рисовался бы уже
|
||||
зеркально поверх ещё неперевёрнутого фона. Хуже всего пламя факела — оно
|
||||
ЗАПЕКАЕТСЯ в ОЗУ-копию (`pop_torch_draw`, у него нет heal: каждый следующий
|
||||
кадр непрозрачно накрывает предыдущий). Кадр пламени, положенный в
|
||||
зеркальную позицию на старом фоне, оставался там навсегда — по комнате
|
||||
рассыпались лишние языки огня.
|
||||
|
||||
Поэтому у нас два флага: `pop_upside_want` (пишут зелье, смерть Кида, чит U)
|
||||
и `pop_upside` (читают все слои отрисовки). Переключение — ровно одно место,
|
||||
начало кадра, вместе с перерисовкой: главный цикл делает
|
||||
`pop_upside = pop_upside_want` и зовёт `pop_flip_screen`.
|
||||
|
||||
Сама перерисовка при этом СОВПАДАЕТ с оригиналом: там на
|
||||
`need_redraw_because_flipped` вызывается `redraw_screen(0)` — полная
|
||||
отрисовка, а не отражение уже нарисованного. У нас то же самое —
|
||||
`pop_flip_screen` рисует комнату заново (и получает чистый фон по
|
||||
построению), а вторую страницу дабл-буфера отдаёт копией акселератора.
|
||||
|
||||
**Что проверять при регрессе.** Уровень 9: выпить зелёное зелье — картинка
|
||||
переворачивается ровно один раз, лишних языков пламени по комнате нет. Чит
|
||||
U даёт тот же результат (он идёт тем же путём).
|
||||
|
||||
Reference in New Issue
Block a user