我创建了一个基本程序,在Windows控制台中使用SetPixel()
方法渲染精灵,它可以正常工作,但是有很大的开销。
我已经对此进行了一些优化,这有所帮助,但速度仍然太慢。
目前我的程序使用两个COLORREF
缓冲区,将更新的缓冲区绘制到屏幕上,交换它们并重新开始。然而,只有当像素发生变化时,才会重新绘制像素。这大大提高了性能,但仍然很慢。缓冲区交换尚未使用指针完成,但真正的开销在于SetPixel()
,因此,我正在寻找一种比SetPixel()
更快的使用GDI创建像素级图形的替代方法。
(忽略anim_frame和img_data向量的第一维,它们只是为了以后添加动画对象而存在)
void graphics_context::update_screen()
{
update_buffer();
for (int x = 0; x < this->width; x++)
{
for (int y = 0; y < this->height; y++)
{
if (this->buffer.at(x).at(y) != this->buffer_past.at(x).at(y))
{
for (int i = 0; i < this->scale_factor; i++)
{
for (int j = 0; j < this->scale_factor; j++)
{
int posX = i + (this->scale_factor * x) + this->width_offset;
int posY = j + (this->scale_factor * y) + this->height_offset;
SetPixel(this->target_dc, posX, posY, this->buffer.at(x).at(y));
}
}
}
}
}
buffer_past = buffer;
}
以下是update_buffer()
方法:
void graphics_context::update_buffer()
{
for (int x = 0; x < this->width; x++)
{
for (int y = 0; y < this->height; y++)
{
buffer.at(x).at(y) = RGB(0, 0, 0);
}
}
//this->layers.at(1)->sprite; <- pointer to member gfx_obj pointer
for (int i = 0; i < this->layers.size(); i++)
{
gfx_object tmp_gfx = *this->layers.at(i)->sprite;
for (int x = 0; x < tmp_gfx.img_data.at(0).size(); x++)
{
for (int y = 0; y < tmp_gfx.img_data.at(tmp_gfx.anim_frame).at(0).size(); y++)
{
if(tmp_gfx.img_data.at(tmp_gfx.anim_frame).at(x).at(y) != RGB(0,255,0))
buffer.at(x + this->layers.at(i)->locX).at(y + this->layers.at(i)->locY) = tmp_gfx.img_data.at(tmp_gfx.anim_frame).at(x).at(y);
}
}
}
}
SetPixel
因为每次调用都必须发现正在写入的图像的属性,所以速度非常慢。使用LockBits
直接操作位图字节要快得多,就像 这个问题 中所示,但这也更加复杂,因为位图格式可能不同。 - 500 - Internal Server Errortarget_dc
是窗口设备上下文,则会进行许多 GDI 调用,这会非常慢。如果target_dc
是内存设备上下文,则SetPixel
的速度较快。使用SetPixelV
这个函数,它不返回已存在的颜色,并且速度更快。但无论哪种方式都是错误的。最后您需要使用BitBlt
来绘制图像。您也可以使用BitBlt
来绘制精灵。 - Barmak Shemirani.at
也不是很快,但这可能是次要的。 - MSalterstarget_dc
是一个窗口设备上下文。 - Kivi[]
运算符更快吗?还是我应该通过一些指针魔法直接访问内存? - Kivi