/* * gfx_dbuf — double-buffering demo (BGI, bgi256.lib). * * Рендерит движущийся прямоугольник, чередуя страницу 0 и 1: * - Каждый кадр: рисуем на СКРЫТОЙ странице, затем делаем её видимой. * - Видимая страница никогда не пишется → пользователь видит только * целые кадры (без артефактов, без мерцания от per-frame clear). * * Переключение страниц и vsync — через mode-agnostic gfx_* (gfx.h, * остались в BGI_GFX): gfx_set_draw_page / gfx_set_visible_page / * gfx_get_visible_page / gfx_wait_vsync. Рисование — через BGI * (graphics.h): cleardevice / bar / rectangle / outtextxy. Режим * 0x81 выбирается линковкой: EXTRA_FLAGS=--gfx 256. * * Индикатор страницы (маленький swatch сверху-справа) меняет оттенок * каждый кадр — если бокс движется плавно, а swatch мигает между двумя * оттенками, своп работает. Press any key to exit. */ #include #include #include #include /* double-buffering + vsync (mode-agnostic) */ #include static uint8_t palette[256 * 4]; #define COL_BLACK 0x00 #define COL_BG 0x20 #define COL_STRIPE 0x60 #define COL_TEXT 0xC0 #define COL_BOX 0xFF #define COL_PAGE0 0x40 #define COL_PAGE1 0xE0 static void make_palette(void) { for (int i = 0; i < 256; i++) { palette[i*4+0] = (uint8_t)i; palette[i*4+1] = (uint8_t)i; palette[i*4+2] = (uint8_t)i; palette[i*4+3] = 0; } } static void draw_frame(int box_x, int box_y, uint8_t page_indicator) { setbkcolor(COL_BG); cleardevice(); /* Static decoration — identical on both pages so the swap doesn't * flicker the chrome. */ setfillstyle(SOLID_FILL, COL_STRIPE); bar(0, 0, GFX_WIDTH - 1, 7); bar(0, GFX_HEIGHT - 8, GFX_WIDTH - 1, GFX_HEIGHT - 1); setcolor(COL_TEXT); outtextxy(8, 16, "double-buffering demo"); outtextxy(8, GFX_HEIGHT - 24, "press a key to exit"); /* Page indicator — different shade per page: flicker here proves * the swap is happening. */ setfillstyle(SOLID_FILL, page_indicator ? COL_PAGE1 : COL_PAGE0); bar(GFX_WIDTH - 24, 16, GFX_WIDTH - 24 + 11, 16 + 11); /* The animated box. */ setfillstyle(SOLID_FILL, COL_BOX); bar(box_x, box_y, box_x + 39, box_y + 29); setcolor(COL_BLACK); rectangle(box_x, box_y, box_x + 39, box_y + 29); } int main(void) { make_palette(); initgraph(); /* Каждая графическая страница имеет свою палитру (0→pal 0, 1→pal 1). * Грузим одну и ту же в обе — визуальный своп бесшовный. */ gfx_pal_load(0, 0, 0, palette); gfx_pal_load(1, 0, 0, palette); /* Очистить обе страницы, чтобы первый флип не вскрыл мусор. */ setbkcolor(COL_BG); gfx_set_draw_page(0); cleardevice(); gfx_set_draw_page(1); cleardevice(); /* Bouncing rect state. */ int box_x = 10; int box_y = 100; int dx = 3; int dy = 2; const int box_w = 40, box_h = 30; while (!kbhit()) { uint8_t hidden = 1 - gfx_get_visible_page(); gfx_set_draw_page(hidden); draw_frame(box_x, box_y, hidden); /* Ждать следующий кадр перед флипом — своп падает в vblank, * пользователь не видит полунарисованный кадр. */ gfx_wait_vsync(); gfx_set_visible_page(hidden); /* Step the box; bounce off all four walls. */ box_x += dx; if (box_x < 0) { box_x = 0; dx = -dx; } if (box_x + box_w > GFX_WIDTH) { box_x = GFX_WIDTH - box_w; dx = -dx; } box_y += dy; if (box_y < 8) { box_y = 8; dy = -dy; } if (box_y + box_h > GFX_HEIGHT-8) { box_y = GFX_HEIGHT-8 - box_h; dy = -dy; } } (void)getch(); closegraph(); puts("done"); return 0; }