DRAW-COST шаг 1: пропуск неизменившегося персонажа — 210% -> 116% кадра
Персонаж, у которого с прошлой отрисовки ЭТОЙ страницы дабл-буфера не изменился ни один вход отрисовки, а фон в его прямоугольнике не трогали, уже нарисован правильно: heal, блит и fore-проход пропускаются целиком. Не спецкейс «мёртвый страж», а общее правило — покрывает и труп, и стоящего Кида, и ждущего стража. Механизм: снимок входов по страницам (pop_cdraw.c, cd_sig/cd_quiet) + позиционная метка «фон трогали вот здесь» (pop_cd_touch в резидентном pop_tile.c, зовёт сам pop_blit_b). Решение перепроверяется перед отрисовкой, а pop_char_draw страхуется собственным heal — если тик всё-таки сдвинул персонажа, прошлый кадр стирается там. Слоты рядом (32 px) — перерисовываем оба, иначе heal соседа выест кусок из «тихого». Метка обязана быть ПОЗИЦИОННОЙ: с флагом «фон трогали хоть где-то» выигрыш был ровно нулевым — факелы анимируются каждый кадр и гасили пропуск для всех сразу (597 684 такта, как без оптимизации). Замеры (MAME, брейкпоинты по totalcycles, бюджет кадра 430 000): комн. 1.3, труп стража, Кид стоит: 210 % -> 116 % (500 772 такта), ноль вызовов pop_heal_fast за кадр, весь фон — 2 блита (44 136); комн. 1.1, Кид стоит вдали от факелов: 404 112 (94 %), цикл 4 -> 3 кадра. Узкое место сместилось на ЛОГИКУ: 60 % кадра уходит на тик персонажей, которые СТОЯТ, ещё 28 % — на loose_tick + process_trobs в комнате без единой ловушки. Разбивка и план — TASKS_OPEN.md#draw-cost.
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
#include <gfx.h>
|
||||
#include <sprite.h>
|
||||
#include "pop_bg.h" /* POP_YOFF */
|
||||
#include "pop_cdraw.h" /* POP_CD_TOUCH — фон тронут, персонажей перерисовать */
|
||||
#include "pop_tile.h"
|
||||
#include "pop_level.h" /* pop_doorlink2 — подстановка нажатой кнопки */
|
||||
#include "_pop_draw.h" /* pop_heal_fast */
|
||||
@@ -88,6 +89,27 @@ uint8_t pop_loose_frame(uint8_t m)
|
||||
return m;
|
||||
}
|
||||
|
||||
/* ---- «Фон трогали ВОТ ЗДЕСЬ» (DRAW-COST; контракт — pop_cdraw.h) ----- */
|
||||
uint8_t pop_cd_dirty;
|
||||
int pop_cd_dx0[2], pop_cd_dy0[2], pop_cd_dx1[2], pop_cd_dy1[2];
|
||||
|
||||
void pop_cd_touch(int x, int y, int w, int h)
|
||||
{
|
||||
uint8_t p;
|
||||
for (p = 0; p < 2; p++) {
|
||||
if (!(pop_cd_dirty & (1 << p))) {
|
||||
pop_cd_dx0[p] = x; pop_cd_dy0[p] = y;
|
||||
pop_cd_dx1[p] = x + w; pop_cd_dy1[p] = y + h;
|
||||
} else {
|
||||
if (x < pop_cd_dx0[p]) pop_cd_dx0[p] = x;
|
||||
if (y < pop_cd_dy0[p]) pop_cd_dy0[p] = y;
|
||||
if (x + w > pop_cd_dx1[p]) pop_cd_dx1[p] = x + w;
|
||||
if (y + h > pop_cd_dy1[p]) pop_cd_dy1[p] = y + h;
|
||||
}
|
||||
}
|
||||
pop_cd_dirty = 3;
|
||||
}
|
||||
|
||||
/* ---- Блит куска атласа ---------------------------------------------- */
|
||||
void pop_blit_b(atlas_t *a, uint8_t idx, int x, int ybottom)
|
||||
{
|
||||
@@ -137,6 +159,11 @@ void pop_blit_b(atlas_t *a, uint8_t idx, int x, int ybottom)
|
||||
} else {
|
||||
gfx_blit_part(dx, dy, img, sx, sy, dw, dh); /* край экрана — с клипом */
|
||||
}
|
||||
/* Кусок ФОНА лёг туда, где может лежать уже нарисованный персонаж —
|
||||
* пометить область, чтобы его перерисовали (DRAW-COST, pop_cdraw.h).
|
||||
* Признак «это не fore-проход поверх персонажа» — окно клипа: его
|
||||
* ставит только он. */
|
||||
if (!pop_t_fclip_on) pop_cd_touch(dx, dy, dw, dh);
|
||||
}
|
||||
gfx_w0_unmap();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user