ALLEGRO5 根据背景更改文本的像素颜色

ALLEGRO5 change pixel color of text based on background

第一次尝试:

void Tower::_DrawHealthBarText(std::string text, int x, int y, ALLEGRO_FONT* font)
{
    al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP);
    ALLEGRO_BITMAP* bmp = al_create_bitmap(196, 17);
    int bmpIndex[196][17] = { };

    al_set_target_bitmap(bmp);
    al_draw_rectangle(5, 20, 200, 20 + 15, al_map_rgb(255, 255, 255), 1.0f);
    al_draw_filled_rectangle(5, 20, 5 - 195.0f + ((195.0f / _player->playerMaxHealth) * _player->playerHealth) + 195.0f, 20 + 15, al_map_rgb(255, 255, 255));
    al_draw_filled_rectangle(4, 19, 201, 20 + 15 + 1, al_map_rgb(0, 0, 0));

    for (int x = 0; x < 196; x++)
    {
        for (int y = 0; y < 17; y++)
        {
            unsigned char r, g, b;
            al_unmap_rgb(al_get_pixel(bmp, x, y), &r, &g, &b);
            if ((r + g + b) / 3 == 255)
            {
                bmpIndex[x][y] = 0;
            }
            else if ((r + g + b) / 3 == 0)
            {
                bmpIndex[x][y] = 1;
            }
        }
    }
    // Clear to transparent background
    al_clear_to_color(rgba(0, 0, 0, 0));

    al_draw_text(getFont(12), al_map_rgb(255, 255, 255), 0, 0, 0, text.c_str());

    al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP);
    al_set_target_backbuffer(g_Window);
    al_draw_bitmap(bmp, x, y, 0);

    al_destroy_bitmap(bmp);
}

第二次尝试:

int bmpIndex[196][17] = { };
void Tower::_DrawHealthBarText(std::string text, int _x, int _y, ALLEGRO_FONT* font)
{
    al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP);
    al_hold_bitmap_drawing(true);
    for (int x = 0; x < 196; x++)
    {
        for (int y = 0; y < 17; y++)
        {
            unsigned char r, g, b;
            al_unmap_rgb(al_get_pixel(al_get_backbuffer(g_Window), _x + x, _y + y), &r, &g, &b);
            if ((r + g + b) / 3 == 255)
            {
                bmpIndex[x][y] = 0;
            }
            else if ((r + g + b) / 3 == 0)
            {
                bmpIndex[x][y] = 1;
            }
        }
    }
    al_hold_bitmap_drawing(false);
    al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP);
}

我用谷歌搜索并尝试了我自己的代码,正如您在上面看到的那样...但是使用这个多级循环非常慢。我的想法是使用着色器,但我还不知道如何使用它们。

我希望文本根据文本所在位置的背景更改颜色...

基本上它是一个健康栏,我想在健康栏顶部显示文本并根据背景更改颜色...如果背景是黑色,则相应的像素将更改为白色。随后,如果背景像素为白色,则文本像素变为黑色。

像这样: photoshop render concept

我的修复:

        // Hacky bullshit
        _DrawText(std::to_string((int)_player->playerHealth), 5 + ((195.0f - al_get_text_width(getFont(12), std::to_string((int)_player->playerHealth).c_str())) / 2), py + 18, getFont(12), al_map_rgb(255, 0, 0), 0);
        al_draw_rectangle(px + 5, py + 20, px + 200, py + 20 + 15, al_map_rgb(255, 255, 255), 1.0f);
        ALLEGRO_BITMAP* bmp = al_create_bitmap(200, 20);
        {
            al_set_target_bitmap(bmp);
            al_draw_filled_rectangle(5, 0, 5 + ((195.0f / _player->playerMaxHealth) * _player->playerHealth), 15, al_map_rgb(255, 255, 255));
            _DrawText(std::to_string((int)_player->playerHealth), 5 + ((195.0f - al_get_text_width(getFont(12), std::to_string((int)_player->playerHealth).c_str())) / 2), -2, getFont(12), al_map_rgb(155, 0, 0), 0);
            al_set_target_backbuffer(g_Window);
            al_draw_bitmap_region(bmp, 0, 0, 5 + ((195.0f / _player->playerMaxHealth) * _player->playerHealth), 20, px, py + 20, 0);
        }
        al_destroy_bitmap(bmp);

最简单的方法是使用剪切矩形,这是大多数图形 API 的一个共同特征。当你设置了裁剪矩形后,裁剪矩形外面什么都画不出来。

  • 首先,设置裁剪矩形覆盖进度条的白色部分。用黑色画你的文字。
  • 然后,设置裁剪矩形覆盖进度条的黑色部分。用白色绘制文本,位置与用黑色绘制的文本相同。
int x = 0, y = 0;
int bar_width = 196, bar_height = 17;
int bar_position = static_cast<int>(
    bar_width * _player->playerHealth / _player->playerMaxHealth);

// Set the clipping rectangle so text only appears on the left
// side of the bar (which is white),
al_set_clipping_rectangle(x, y, bar_position, bar_height);

// Draw black text.
al_draw_text(getFont(12), al_map_rgb(0, 0, 0), x, y, 0, text.c_str());

// Set the clipping rectangle so text only appears on the right
// side of the bar (which is black).
al_set_clipping_rectangle(x + bar_position, y, bar_width - bar_position, bar_height);

// Draw white text in the same position as the black text.
al_draw_text(getFont(12), al_map_rgb(255, 255, 255), x, y, 0, text.c_str());

// Reset clipping rectangle so you can draw graphics as usual again.
al_reset_clipping_rectangle();