roomtest: двойная буферизация (два экрана + флип), тумблер SPACE
Убирает мерцание/тиринг при перерисовке слоёв (Kid/fore/пол-оверлей): рендер всего кадра в скрытую страницу, tear-free флип на vblank. Инфра libbgi (gfx_set_draw_page/visible_page/wait_vsync) уже была. - фон комнаты рисуется в ОБЕ графические страницы (у каждой своя ОЗУ-копия — источник heal); палитра 0->1 уже синкалась gfx_pal_sync; - kid_heal/kid_draw: прямоугольник Kid запоминается ПО СТРАНИЦЕ (kid_l*[2]) — при чередовании страниц heal стирает пиксели своей страницы (прошлый Kid там был 2 логических кадра назад); - цикл: draw в back, 3x wait_vsync (пейсинг), gfx_set_visible_page(back); - SPACE (edge) — тумблер: off = однобуфер (draw==visible==0) для отладки. Мерцание при подъёме подтверждено устранённым в MAME (пользователь). План: applications/PoP/docs/double_buffer_plan.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -20,6 +20,11 @@
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* Дабл-буфер: front — видимая страница, back — куда рисуем. dbuf=1
|
||||
* по умолчанию (без мерцания); SPACE переключает в однобуфер для
|
||||
* отладки багов рисования (edge по sp_prev, чтоб не дёргать). */
|
||||
uint8_t pg, front = 0, back, dbuf = 1, sp_prev = 0;
|
||||
|
||||
if (pop_bg_load() != 0) { /* атласы — ДО initgraph */
|
||||
puts("pop_bg_load failed");
|
||||
return 1;
|
||||
@@ -30,19 +35,22 @@ int main(void)
|
||||
}
|
||||
|
||||
initgraph();
|
||||
gfx_set_draw_page(0);
|
||||
gfx_set_visible_page(0);
|
||||
if (gfx_pal_fload(0, "kid.pal") < 0) /* единая игровая палитра */
|
||||
gfx_pal_fload(0, "a:\\kid.pal");
|
||||
gfx_pal_sync();
|
||||
gfx_pal_sync(); /* палитра 0 -> плоскость 1 */
|
||||
|
||||
/* Фон комнаты рисуется ОДИН РАЗ — в видео-ОЗУ И теневую копию
|
||||
* (GFX_BANK_TRANSPARENT внутри pop_room_draw). Дальше каждый тик
|
||||
* восстанавливаем ТОЛЬКО прямоугольник Кида из теневой копии (heal),
|
||||
* а не весь экран. */
|
||||
setfillstyle(SOLID_FILL, BLACK);
|
||||
bar(0, 0, 319, 255);
|
||||
pop_room_draw(1, room1_fg, room1_bg, leftcol_fg, leftcol_bg);
|
||||
/* Фон комнаты рисуется в ОБЕ графические страницы: у каждой своя
|
||||
* ОЗУ-копия/видео-ОЗУ, а heal берёт чистый фон из ОЗУ-копии ТОЙ
|
||||
* страницы, в которую рисуем. Дальше каждый тик восстанавливаем
|
||||
* ТОЛЬКО прямоугольник Кида (kid_heal), а не весь экран. */
|
||||
for (pg = 0; pg < 2; pg++) {
|
||||
gfx_set_draw_page(pg);
|
||||
setfillstyle(SOLID_FILL, BLACK);
|
||||
bar(0, 0, 319, 255);
|
||||
pop_room_draw(1, room1_fg, room1_bg, leftcol_fg, leftcol_bg);
|
||||
}
|
||||
gfx_set_draw_page(0);
|
||||
|
||||
/* K2b: Kid стоит на уступе (row1), управляется с клавиатуры.
|
||||
* ←/→ бег, ↓ присед, ↑+→ прыжок с места, Shift шаг (K3). ESC — выход. */
|
||||
@@ -59,11 +67,24 @@ int main(void)
|
||||
}
|
||||
|
||||
while (!kbd_raw_down(KBD_ESC)) {
|
||||
gfx_wait_vsync();
|
||||
gfx_wait_vsync();
|
||||
gfx_wait_vsync();
|
||||
/* SPACE — тумблер дабл-буфера (edge, чтоб одно нажатие = один
|
||||
* переключ). Выключение возвращает показ на страницу 0. */
|
||||
uint8_t sp = kbd_raw_down(KBD_SPACE);
|
||||
if (sp && !sp_prev) {
|
||||
dbuf ^= 1;
|
||||
if (!dbuf) {
|
||||
gfx_set_visible_page(0);
|
||||
front = 0;
|
||||
}
|
||||
}
|
||||
sp_prev = sp;
|
||||
|
||||
/* Рисуем в СКРЫТУЮ страницу (при dbuf); в однобуфере — в 0. */
|
||||
back = dbuf ? (uint8_t)(front ^ 1) : 0;
|
||||
gfx_set_draw_page(back);
|
||||
|
||||
pop_ctrl_tick(); /* ввод -> control(): смена seq */
|
||||
kid_heal(); /* стереть прошлый кадр (фон из тени) */
|
||||
kid_heal(); /* стереть прошлый кадр ЭТОЙ страницы */
|
||||
kid_tick(); /* play_seq: следующий кадр */
|
||||
pop_phys_tick(); /* K3: падение/приземление/стена */
|
||||
if (pop_fell_out) { /* упал за низ комнаты — сброс на старт */
|
||||
@@ -73,6 +94,17 @@ int main(void)
|
||||
kid_draw(); /* нарисовать новый кадр */
|
||||
pop_fore_over_kid(kid_fp_obj_x(), kid_fp_obj_y(),
|
||||
kid_fp_width(), kid_fp_height(), Kid.direction, Kid.frame);
|
||||
|
||||
/* Пейсинг 3 кадра, затем tear-free флип на vblank: draw уже
|
||||
* сделан (скрытая страница), wait_vsync ловит начало кадра,
|
||||
* set_visible_page переключает во время бланка (gfx.h паттерн). */
|
||||
gfx_wait_vsync();
|
||||
gfx_wait_vsync();
|
||||
gfx_wait_vsync();
|
||||
if (dbuf) {
|
||||
gfx_set_visible_page(back);
|
||||
front = back;
|
||||
}
|
||||
}
|
||||
|
||||
pop_ctrl_close();
|
||||
|
||||
Reference in New Issue
Block a user