Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 09f32ce834 | |||
| 4db60c750f |
@@ -3337,3 +3337,46 @@ draw_tile_anim(); draw_tile_bottom(0); draw_loose(0);
|
|||||||
`draw_tile_anim_right` — то есть анимированной правой грани СОСЕДА (пики,
|
`draw_tile_anim_right` — то есть анимированной правой грани СОСЕДА (пики,
|
||||||
ворота, loose). Симптома на это пока не видели; если всплывёт «правая грань
|
ворота, loose). Симптома на это пока не видели; если всплывёт «правая грань
|
||||||
соседа под персонажем/куском» — смотреть сюда.
|
соседа под персонажем/куском» — смотреть сюда.
|
||||||
|
|
||||||
|
### Вариант B: порт корзины 30 (2026-08-18)
|
||||||
|
|
||||||
|
Реализовано то, что разобрано в коммите `272cf8f`. Кусок, у которого ряд
|
||||||
|
объекта вне 0..2 (`y_to_row_mod4` даёт −1 и «выше потолка», и «ниже пола»),
|
||||||
|
считается объектом ТАЙЛА 30 — а такие оригинал рисует ПЕРВЫМИ, до всего
|
||||||
|
обхода тайлов. Два следствия:
|
||||||
|
|
||||||
|
- `defer = 0` — кусок идёт под всем, включая Кида (раньше сравнение рядов
|
||||||
|
давало обратное: «−1 обходится последним» читалось как «поверх»);
|
||||||
|
- оверлею отдаётся ориентир **3** («раньше любого ряда обхода 2,1,0»)
|
||||||
|
вместо сырого −1, и в набор перекрываемых тайлов добавляется **своя
|
||||||
|
клетка** — у куска в обычном ряду её перерисовывать нельзя, там объект
|
||||||
|
вливается в midtable уже после частей своего тайла.
|
||||||
|
|
||||||
|
**Замер 13/23 (3032 кадра, зонды фаз + детализация зелёной):**
|
||||||
|
|
||||||
|
| секция | тег `mob-order-B-start` | после B | дельта |
|
||||||
|
|---|---:|---:|---:|
|
||||||
|
| работа | 888 984 | **913 848** | +24 864 |
|
||||||
|
| синяя | 159 804 | 159 810 | +6 |
|
||||||
|
| зелёная | 427 242 | **440 418** | +13 176 |
|
||||||
|
| циан | 378 864 | 393 000 | +14 136 |
|
||||||
|
|
||||||
|
Период кадра не изменился: 4 растра в 23 кадрах, 5 в двух — как и до правки.
|
||||||
|
|
||||||
|
**Зелёная вышла за растровый кадр** (440 418 против 430 000) при цели
|
||||||
|
400 000. Детализация показывает, где именно:
|
||||||
|
|
||||||
|
| участок зелёной | максимум |
|
||||||
|
|---|---:|
|
||||||
|
| `pop_loose_tick` целиком | 185 826 |
|
||||||
|
| — из них `pop_loose_mob_tick` | **168 180** |
|
||||||
|
| — циклы по тайлам | 23 736 |
|
||||||
|
| — `check_loose_fall_on_kid` | 5 868 |
|
||||||
|
| тробы + `pop_redraw_needed` | 337 800 |
|
||||||
|
| шов и прочее | 11 964 |
|
||||||
|
|
||||||
|
(максимумы взяты по разным кадрам, поэтому не складываются в общий).
|
||||||
|
|
||||||
|
Основной кандидат на возврат этих тактов — задача
|
||||||
|
[HEAL-WIDTH](TASKS_OPEN.md#heal-width): heal'ы кусков и плит берут ширину по
|
||||||
|
клеткам, а фактический след — 58/57.
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ ESC выход.
|
|||||||
|
|
||||||
## Статус (2026-08-18)
|
## Статус (2026-08-18)
|
||||||
|
|
||||||
**Уровни 1-3 приняты, 4-9 прошли предварительный тест.** Работает: комнаты и
|
**Уровни 1-3 приняты, 4-12 прошли предварительный тест.** Работает: комнаты и
|
||||||
переходы, Kid (анимация, управление, коллизия/падение, зацеп/подтягивание/
|
переходы, Kid (анимация, управление, коллизия/падение, зацеп/подтягивание/
|
||||||
спуск, окклюзия), кнопки и ворота, пики, чомперы, проваливающиеся полы, дверь
|
спуск, окклюзия), кнопки и ворота, пики, чомперы, проваливающиеся полы, дверь
|
||||||
уровня и переход на следующий, меч и бой, стражи с ИИ (включая скелета и
|
уровня и переход на следующий, меч и бой, стражи с ИИ (включая скелета и
|
||||||
|
|||||||
@@ -44,7 +44,10 @@
|
|||||||
| 7 | **предварительно пройден** (2026-08-18) | [SPIKE-BAKED](BUGS_CLOSED.md#spike-baked) — выдвинутые пики консервировались в фон запечкой соседней кнопки и оставались навсегда (`980d48c`); [DIED-ON-BUTTON](BUGS_CLOSED.md#died-on-button) — смерть на кнопке не ломала её насовсем: до `check_press` труп не доходил, самой `died_on_button` не было, а таймер связи переживал респавн (`6feab5d`) |
|
| 7 | **предварительно пройден** (2026-08-18) | [SPIKE-BAKED](BUGS_CLOSED.md#spike-baked) — выдвинутые пики консервировались в фон запечкой соседней кнопки и оставались навсегда (`980d48c`); [DIED-ON-BUTTON](BUGS_CLOSED.md#died-on-button) — смерть на кнопке не ломала её насовсем: до `check_press` труп не доходил, самой `died_on_button` не было, а таймер связи переживал респавн (`6feab5d`) |
|
||||||
| 8 | **предварительно пройден** (2026-08-18) | [GUARD-RESPAWN-COL0](BUGS_CLOSED.md#guard-respawn-col0) — при возврате в комнату страж телепортировался в колонку 0 и падал насмерть: колонку несёт `guards_x`, а не тайл (`c40ae3f`); [SEAM-FIGHT-FLICKER](BUGS_CLOSED.md#seam-fight-flicker) — бой у шва перерисовывал комнату туда-обратно: `leave_room` запрещает уход ещё и на кадрах меча (`a498255`, сверено с SDLPoP покадрово) |
|
| 8 | **предварительно пройден** (2026-08-18) | [GUARD-RESPAWN-COL0](BUGS_CLOSED.md#guard-respawn-col0) — при возврате в комнату страж телепортировался в колонку 0 и падал насмерть: колонку несёт `guards_x`, а не тайл (`c40ae3f`); [SEAM-FIGHT-FLICKER](BUGS_CLOSED.md#seam-fight-flicker) — бой у шва перерисовывал комнату туда-обратно: `leave_room` запрещает уход ещё и на кадрах меча (`a498255`, сверено с SDLPoP покадрово) |
|
||||||
| 9 | **предварительно пройден** (2026-08-18) | багов не найдено |
|
| 9 | **предварительно пройден** (2026-08-18) | багов не найдено |
|
||||||
| 10+ | не начат | |
|
| 10 | **предварительно пройден** (2026-08-18) | багов не найдено |
|
||||||
|
| 11 | **предварительно пройден** (2026-08-18) | [MOB-NEIGHBOUR-ROOM](BUGS_CLOSED.md#mob-neighbour-room) — плиты нижнего ряда пропадали без кадров падения (кусок в соседней комнате не рисовался, `ed5615a`); порядок куска относительно соседней плиты и Кида — порт корзины 30 (`4db60c7`) |
|
||||||
|
| 12 | **предварительно пройден** (2026-08-18) | багов не найдено |
|
||||||
|
| 13+ | не начат | |
|
||||||
|
|
||||||
«Предварительно пройден» ≠ «принят»: уровни 4-6 пройдены прогоном по
|
«Предварительно пройден» ≠ «принят»: уровни 4-6 пройдены прогоном по
|
||||||
сценарию, а не обходом ВСЕХ комнат — полные обходы делаются по готовности
|
сценарию, а не обходом ВСЕХ комнат — полные обходы делаются по готовности
|
||||||
@@ -303,6 +306,13 @@ MEM-BANK2, MEM-BANK5, CLIP-1, KBD-1, DBG-CHEATS.
|
|||||||
прогон комнат с плитами, пиками и чомперами: сужение heal'а — самый прямой
|
прогон комнат с плитами, пиками и чомперами: сужение heal'а — самый прямой
|
||||||
способ получить «недочищенный хвост».
|
способ получить «недочищенный хвост».
|
||||||
|
|
||||||
|
**Родня — [G8](../docs/perf_green_phase.md) (пометка соседа узкой полосой).**
|
||||||
|
Это две половины одной темы, и брать их логично вместе: G8 про ширину
|
||||||
|
ЗАПЕЧКИ соседнего тайла (60 вместо 28 нужных, да ещё `draw_tile` соседа
|
||||||
|
дважды на пометку), HEAL-WIDTH — про ширину HEAL'ов (64 вместо 58/57).
|
||||||
|
Числа там уже разобраны: 60 = 32 свой тайл + 28 собственный свес, и для
|
||||||
|
запечки САМОГО тайла 60 минимальны — сужать можно только пометку СОСЕДА.
|
||||||
|
|
||||||
|
|
||||||
### <a id="l12-shadow"></a>L12-SHADOW. Уровень 12: встреча с тенью, бой, слияние
|
### <a id="l12-shadow"></a>L12-SHADOW. Уровень 12: встреча с тенью, бой, слияние
|
||||||
|
|
||||||
|
|||||||
@@ -1203,13 +1203,6 @@ static void mob_spawn(uint8_t room, int row, int col)
|
|||||||
m->defer = 0;
|
m->defer = 0;
|
||||||
m->prev_y[0] = m->prev_y[1] = MOB_Y_NONE;
|
m->prev_y[0] = m->prev_y[1] = MOB_Y_NONE;
|
||||||
m->draw_y = MOB_Y_NONE;
|
m->draw_y = MOB_Y_NONE;
|
||||||
{ /* ВРЕМЕННО: журнал решения оверлея — копим за весь полёт */
|
|
||||||
uint8_t k = (uint8_t)(m - mobs);
|
|
||||||
pop_dbg_pass[k] = 0;
|
|
||||||
pop_dbg_ovl[k * 4 + 2] = 0;
|
|
||||||
pop_dbg_ovl[k * 4 + 3] = 0;
|
|
||||||
pop_dbg_tiles[k] = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Отрыв куска в ТЕКУЩЕЙ комнате (обычный случай — pop_loose_tick). */
|
/* Отрыв куска в ТЕКУЩЕЙ комнате (обычный случай — pop_loose_tick). */
|
||||||
@@ -1497,7 +1490,18 @@ static void mob_tick_one(mob_t *m, uint8_t pg)
|
|||||||
{
|
{
|
||||||
int8_t mrow = pop_y_to_row((int16_t)mt_m->draw_y); /* y_to_row_mod4 */
|
int8_t mrow = pop_y_to_row((int16_t)mt_m->draw_y); /* y_to_row_mod4 */
|
||||||
uint8_t over;
|
uint8_t over;
|
||||||
if (mrow != pop_bg_obj_row) over = (mrow < pop_bg_obj_row); /* ряды идут 2,1,0 */
|
if (mrow < 0 || mrow > 2) {
|
||||||
|
/* КОРЗИНА 30 (get_tilepos_nominus, seg006:110). Ряд объекта вне
|
||||||
|
* комнаты: y_to_row_mod4 берёт остаток по 4, поэтому «выше
|
||||||
|
* потолка» и «ниже пола» дают одно и то же −1, а оригинал сводит
|
||||||
|
* оба в тайл 30. Объекты этого тайла рисуются ПЕРВЫМИ —
|
||||||
|
* draw_objtable_items_at_tile(30) стоит в redraw_needed_tiles до
|
||||||
|
* всего обхода тайлов. Значит кусок под ВСЕМ, включая Кида; до
|
||||||
|
* сих пор сравнение рядов давало обратное («−1 обходится
|
||||||
|
* последним» = поверх). */
|
||||||
|
over = 0;
|
||||||
|
}
|
||||||
|
else if (mrow != pop_bg_obj_row) over = (mrow < pop_bg_obj_row); /* ряды идут 2,1,0 */
|
||||||
else if (mt_m->col != pop_bg_obj_col) over = (mt_m->col > pop_bg_obj_col);
|
else if (mt_m->col != pop_bg_obj_col) over = (mt_m->col > pop_bg_obj_col);
|
||||||
else over = (mt_m->draw_y > pop_cd[POP_CH_KID].fpy);
|
else over = (mt_m->draw_y > pop_cd[POP_CH_KID].fpy);
|
||||||
/* РИСОВАНИЯ ЗДЕСЬ БОЛЬШЕ НЕТ — только решение, в какой проход кусок
|
/* РИСОВАНИЯ ЗДЕСЬ БОЛЬШЕ НЕТ — только решение, в какой проход кусок
|
||||||
@@ -1586,30 +1590,30 @@ static void mob_overlay_neighbour(const mob_t *m)
|
|||||||
{
|
{
|
||||||
int8_t r = pop_y_to_row((int16_t)m->draw_y);
|
int8_t r = pop_y_to_row((int16_t)m->draw_y);
|
||||||
int8_t rt = pop_y_to_row((int16_t)(m->draw_y - 18));
|
int8_t rt = pop_y_to_row((int16_t)(m->draw_y - 18));
|
||||||
int8_t c = (int8_t)(m->col + 1);
|
/* КОРЗИНА 30 оригинала (get_tilepos_nominus, seg006:110): ряд объекта вне
|
||||||
|
* комнаты. y_to_row_mod4 берёт остаток по 4, поэтому «выше потолка» и
|
||||||
|
* «ниже пола» дают одно и то же −1 — оригинал сводит оба случая в тайл 30
|
||||||
|
* и рисует такие объекты ПЕРВЫМИ, до всего обхода тайлов
|
||||||
|
* (draw_objtable_items_at_tile(30) в redraw_needed_tiles).
|
||||||
|
*
|
||||||
|
* Отсюда два отличия от обычного куска:
|
||||||
|
* - ориентир «тайл объекта» = 3, то есть РАНЬШЕ любого ряда обхода
|
||||||
|
* (2,1,0). Сюда уходил сырой −1, и гейт other_overlay_tile
|
||||||
|
* `row > pop_bg_obj_row` читал его наоборот — «объект поверх всего» —
|
||||||
|
* и соседа не возвращал вовсе (тело плиты пропадало, оставался
|
||||||
|
* только её торец из переднего слоя);
|
||||||
|
* - перекрыть кусок должна и СВОЯ клетка, а не только сосед справа:
|
||||||
|
* после объекта у оригинала рисуются ВСЕ тайлы. У куска в обычном
|
||||||
|
* ряду своя клетка не перерисовывается — там объект вливается в
|
||||||
|
* midtable уже ПОСЛЕ частей своего тайла. */
|
||||||
|
uint8_t b30 = (uint8_t)(r < 0 || r > 2);
|
||||||
|
int8_t oref = b30 ? (int8_t)3 : r;
|
||||||
|
int8_t c, cend = (int8_t)(m->col + 1);
|
||||||
int ytop, ybot;
|
int ytop, ybot;
|
||||||
uint8_t *dbg = &pop_dbg_ovl[(m - mobs) * 4]; /* ВРЕМЕННО: журнал решения */
|
if (cend > 9) cend = 9;
|
||||||
{ /* ВРЕМЕННО: перебор ВСЕХ тайлов, чьи габариты пересекаются со спрайтом
|
/* Габарит куска — по ЭКРАННОЙ координате: у куска, видимого из соседней
|
||||||
* куска — чтобы понять, скольким тайлам реально нужно лечь поверх. */
|
* комнаты, draw_y отличается от y на 192. */
|
||||||
int8_t rr, kk;
|
ytop = m->draw_y - (int)mob_spr[2] + 1;
|
||||||
int t0 = m->draw_y - (int)mob_spr[2] + 1, t1 = m->draw_y;
|
|
||||||
for (rr = -1; rr <= 2; rr++)
|
|
||||||
for (kk = 0; kk <= 1; kk++) {
|
|
||||||
int8_t cc = (int8_t)(m->col + kk);
|
|
||||||
if (cc > 9) continue;
|
|
||||||
if (pop_tile_code(rr, cc) &&
|
|
||||||
t1 >= 63 * rr + 2 && t0 <= 63 * rr + 66)
|
|
||||||
pop_dbg_tiles[m - mobs] |= (uint8_t)(1 << ((rr + 1) * 2 + kk));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dbg[0] = (uint8_t)(r + 128); dbg[1] = (uint8_t)(rt + 128);
|
|
||||||
dbg[2] |= 1;
|
|
||||||
if (c > 9) return;
|
|
||||||
dbg[2] |= 2;
|
|
||||||
/* Габарит куска — по ЭКРАННОЙ координате, как и ряд выше: у куска,
|
|
||||||
* видимого из соседней комнаты, draw_y отличается от y на 192, и
|
|
||||||
* сравнение с габаритом тайла по y давало заведомо ложный ответ. */
|
|
||||||
ytop = m->draw_y - (int)mob_spr[2] + 1; /* верх спрайта куска */
|
|
||||||
ybot = m->draw_y;
|
ybot = m->draw_y;
|
||||||
/* ПРЕДУСЛОВИЯ ПРОВЕРЯЕМ ЗДЕСЬ, до вызова в банк 2. pop_mob_overlay_tile
|
/* ПРЕДУСЛОВИЯ ПРОВЕРЯЕМ ЗДЕСЬ, до вызова в банк 2. pop_mob_overlay_tile
|
||||||
* живёт в банке 2, то есть каждый вызов из банка 7 платит межбанковый
|
* живёт в банке 2, то есть каждый вызов из банка 7 платит межбанковый
|
||||||
@@ -1620,21 +1624,15 @@ static void mob_overlay_neighbour(const mob_t *m)
|
|||||||
* ничего не рисовало.
|
* ничего не рисовало.
|
||||||
*
|
*
|
||||||
* Габарит тайла берём ПОЛНЫМ (63*row+2 .. +66) — какая именно часть
|
* Габарит тайла берём ПОЛНЫМ (63*row+2 .. +66) — какая именно часть
|
||||||
* соседа окажется поверх куска, решит уже окно клипа внутри. Сужать по
|
* соседа окажется поверх куска, решит уже окно клипа внутри. */
|
||||||
* реальной высоте кусков нельзя: у колонн и зеркала база высокая. */
|
for (c = b30 ? (int8_t)m->col : cend; c <= cend; c++) {
|
||||||
if (r >= 0 && r <= 2 && pop_tile_code(r, c)) dbg[2] |= 4;
|
if (c < 0) continue;
|
||||||
if (r >= 0 && r <= 2 && ybot >= 63 * r + 2 && ytop <= 63 * r + 66) dbg[2] |= 8;
|
if (r >= 0 && r <= 2 && pop_tile_code(r, c) &&
|
||||||
if (r >= 0 && r <= 2 && pop_tile_code(r, c) &&
|
ybot >= 63 * r + 2 && ytop <= 63 * r + 66)
|
||||||
ybot >= 63 * r + 2 && ytop <= 63 * r + 66) {
|
pop_mob_overlay_tile(r, c, oref, (int8_t)m->col, m->x, m->draw_y, mob_spr[2]);
|
||||||
dbg[2] |= 0x10; dbg[3]++;
|
if (rt != r && rt >= 0 && rt <= 2 && pop_tile_code(rt, c) &&
|
||||||
pop_mob_overlay_tile(r, c, r, (int8_t)m->col, m->x, m->draw_y, mob_spr[2]);
|
ybot >= 63 * rt + 2 && ytop <= 63 * rt + 66)
|
||||||
}
|
pop_mob_overlay_tile(rt, c, oref, (int8_t)m->col, m->x, m->draw_y, mob_spr[2]);
|
||||||
if (rt != r && rt >= 0 && rt <= 2 && pop_tile_code(rt, c)) dbg[2] |= 0x20;
|
|
||||||
if (rt != r && rt >= 0 && rt <= 2 && ybot >= 63 * rt + 2 && ytop <= 63 * rt + 66) dbg[2] |= 0x40;
|
|
||||||
if (rt != r && rt >= 0 && rt <= 2 && pop_tile_code(rt, c) &&
|
|
||||||
ybot >= 63 * rt + 2 && ytop <= 63 * rt + 66) {
|
|
||||||
dbg[2] |= 0x80; dbg[3]++;
|
|
||||||
pop_mob_overlay_tile(rt, c, r, (int8_t)m->col, m->x, m->draw_y, mob_spr[2]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1650,10 +1648,6 @@ static void mob_draw_pass(uint8_t pg, uint8_t want_defer)
|
|||||||
mob_t *m = &mobs[i];
|
mob_t *m = &mobs[i];
|
||||||
/* Отбор по draw_y, а НЕ по комнате: кусок, только что провалившийся
|
/* Отбор по draw_y, а НЕ по комнате: кусок, только что провалившийся
|
||||||
* в комнату снизу, ещё виден из нашей (см. mob_tick_one). */
|
* в комнату снизу, ещё виден из нашей (см. mob_tick_one). */
|
||||||
pop_dbg_pass[i] |= 1;
|
|
||||||
if (m->active) pop_dbg_pass[i] |= 2;
|
|
||||||
if (m->draw_y != MOB_Y_NONE) pop_dbg_pass[i] |= 4;
|
|
||||||
if ((uint8_t)(m->defer != 0) == want_defer) pop_dbg_pass[i] |= 8;
|
|
||||||
if (!m->active || m->draw_y == MOB_Y_NONE) continue;
|
if (!m->active || m->draw_y == MOB_Y_NONE) continue;
|
||||||
if ((uint8_t)(m->defer != 0) != want_defer) continue;
|
if ((uint8_t)(m->defer != 0) != want_defer) continue;
|
||||||
for (j = n; j > 0 && mobs[order[j - 1]].draw_y < m->draw_y; j--)
|
for (j = n; j > 0 && mobs[order[j - 1]].draw_y < m->draw_y; j--)
|
||||||
@@ -1670,10 +1664,8 @@ static void mob_draw_pass(uint8_t pg, uint8_t want_defer)
|
|||||||
* в кадр пересечения границы пометка указывала на прежний тайл, и
|
* в кадр пересечения границы пометка указывала на прежний тайл, и
|
||||||
* передняя часть колонны кусок не перекрывала — ровно ОДИН кадр,
|
* передняя часть колонны кусок не перекрывала — ровно ОДИН кадр,
|
||||||
* как и наблюдалось (прогон 2026-08-13, комната 23, колонка 8). */
|
* как и наблюдалось (прогон 2026-08-13, комната 23, колонка 8). */
|
||||||
pop_dbg_pass[order[i]] |= 0x10;
|
|
||||||
mob_mark_neighbour(&mobs[order[i]]);
|
mob_mark_neighbour(&mobs[order[i]]);
|
||||||
mob_render(&mobs[order[i]], pg);
|
mob_render(&mobs[order[i]], pg);
|
||||||
pop_dbg_pass[order[i]] |= 0x20;
|
|
||||||
mob_overlay_neighbour(&mobs[order[i]]);
|
mob_overlay_neighbour(&mobs[order[i]]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user