You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Allegro 5中避免重绘康威生命游戏的静态背景?

解决Allegro中重复绘制静态表格边框的问题

我之前做康威生命游戏的Allegro复刻时也碰到过一模一样的问题——每次循环都重绘所有边框不仅浪费性能,还可能导致画面轻微闪烁。核心解决方案就是把静态的背景元素提前绘制到离屏缓冲区,之后每次只更新动态变化的内容,具体步骤如下:

1. 创建离屏背景位图

在程序初始化阶段(绘制初始表格之前),创建一个和游戏窗口尺寸一致的离屏位图,专门用来存放静态的表格边框和底色。这样我们只需要画一次边框,之后就能重复使用这个背景。

修改你的代码,先添加全局变量:

ALLEGRO_BITMAP *background; // 用于存储静态背景
int** board;

然后在初始化Allegro并创建显示窗口后,绘制静态背景:

// 创建和窗口同尺寸的离屏位图
background = al_create_bitmap(SCREEN_W * CELL_SIZE, SCREEN_H * CELL_SIZE);

// 切换绘制目标到离屏位图(此时所有绘制操作都不会显示在屏幕上)
al_set_target_bitmap(background);

// 先填充白色底色
al_clear_to_color(WHITE);

// 一次性绘制所有表格边框
for (int i = 0; i < SCREEN_H ; i++) {
    for (int j = 0; j < SCREEN_W; j++) {
        al_draw_rectangle(
            j * CELL_SIZE, i * CELL_SIZE,
            (j + 1) * CELL_SIZE, (i + 1) * CELL_SIZE,
            BLACK, 1.0
        );
    }
}

// 切换回屏幕缓冲区,准备显示初始画面
al_set_target_bitmap(al_get_backbuffer(display));

// 第一次把静态背景画到屏幕上
al_draw_bitmap(background, 0, 0, 0);
al_flip_display();

2. 循环中只更新动态单元格

在while循环里,我们不再需要重复绘制边框了——只需要先把预先生成的背景画到屏幕上,然后只绘制状态变化的单元格填充色即可:

while (game_running) {
    // 处理输入事件(这里省略你的事件处理代码)
    
    // 根据生命游戏规则更新board状态
    generate();

    // 第一步:绘制静态背景(恢复边框和底色)
    al_draw_bitmap(background, 0, 0, 0);

    // 第二步:只绘制需要更新的单元格填充色
    for (int i = 0; i < rows; ++i) {
        for (int j = 0; j < columns; ++j) {
            if (board[i][j] == 1) {
                // 只有细胞存活时才绘制黑色填充,白色底色已经在背景里了
                al_draw_filled_rectangle(
                    j * CELL_SIZE, i * CELL_SIZE,
                    (j + 1) * CELL_SIZE, (i + 1) * CELL_SIZE,
                    BLACK
                );
            }
            // 细胞死亡时无需绘制,背景的白色已经覆盖了上一帧的黑色
        }
    }

    al_flip_display();
    al_rest(0.1); // 控制帧率,可根据需求调整
}

3. 进阶优化:只重绘变化的单元格

如果你的生命游戏中每次迭代只有少数细胞状态变化,可以再进一步优化:维护一个上一帧的prev_board数组,每次generate()后对比prev_board和当前board,只重绘状态不同的单元格。这样能大幅减少绘制操作的数量,提升性能:

// 初始化时复制一份初始board到prev_board
int** prev_board = malloc(rows * sizeof(int*));
for (int i = 0; i < rows; i++) {
    prev_board[i] = malloc(columns * sizeof(int));
    memcpy(prev_board[i], board[i], columns * sizeof(int));
}

// 循环内修改:
generate();
al_draw_bitmap(background, 0, 0, 0);

for (int i = 0; i < rows; ++i) {
    for (int j = 0; j < columns; ++j) {
        if (prev_board[i][j] != board[i][j]) {
            // 只有状态变化时才重绘
            ALLEGRO_COLOR color = (board[i][j] == 1) ? BLACK : WHITE;
            al_draw_filled_rectangle(
                j * CELL_SIZE, i * CELL_SIZE,
                (j + 1) * CELL_SIZE, (i + 1) * CELL_SIZE,
                color
            );
            // 更新prev_board记录当前状态
            prev_board[i][j] = board[i][j];
        }
    }
}

最后注意事项

  • 程序退出时别忘了销毁离屏位图,避免内存泄漏:al_destroy_bitmap(background);
  • 如果你的窗口尺寸可能变化,需要在窗口 resize 时重新生成背景位图。

内容的提问来源于stack exchange,提问作者gvd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:07:21