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();
第一次尝试:
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();