【发布时间】:2021-04-19 18:12:06
【问题描述】:
我正在寻找一个使用 SDL2 绘制实心圆而不使用渲染器的函数。我目前有这个:
void Circle(int center_x, int center_y, int radius, SDL_Color color) {
eraseOldCircle();
uint32_t *pixels = (uint32_t *) windowSurface->pixels;
SDL_PixelFormat *windowFormat = windowSurface->format;
SDL_LockSurface(windowSurface); // Lock surface for direct pixel access capability
int radiussqrd = radius * radius;
for(int x=center_x-radius; x<=center_x+radius; x++) {
int dx = center_x - x;
for(int y=center_y-radius; y<=center_y+radius; y++) {
int dy = center_y - y;
if((dy * dy + dx * dx) <= radiussqrd) {
pixels[(y * WIDTH + x)] = SDL_MapRGB(windowFormat, color.r, color.g, color.b);
}
}
}
SDL_UnlockSurface(windowSurface);
SDL_UpdateWindowSurface(window);
}
改编自我在这里找到的另一个函数,它在调用eraseOldCircle后将像素直接绘制到windowSurface(这会将游戏的背景图像放回圆圈的先前位置,有效地从那里擦除它.) 但对于我需要的东西来说它仍然太慢了(可能是数学?)。使用直接像素访问绘制圆的最快方法是什么?我需要它是高速的,所以我可以在 2D 游戏中使用它。直到现在我都找不到任何东西,我看到的所有东西都使用SDL_Renderer,但我绝对不应该使用它。
这里是eraseOldCircle(),以防万一:
void eraseOldCircle() {
//Calculate previous position of ball
SDL_Rect pos = {circlePosition.x-(radius+steps), circlePosition.y-(radius+steps), radius*radius, radius*2+steps};
SDL_BlitSurface(backgroundImage, &pos, windowSurface, &pos);
}
【问题讨论】:
-
如果您将圆圈视为一堆像素行,那么您所需要的只是这些行的端点,然后您可以使用例如一个循环,
memcpy()或std::copy()以快速填充行。对于端点,您所需要的只是给定半径的一个象限的增量值。如果事先知道半径,您甚至可以预先计算增量。我不会将此作为答案发布,因为答案可能需要更多细节,但这可能会帮助您指明正确的方向。 -
@scg 非常感谢,我会试试看能不能做点什么
-
你确定最快的方法不是 SDL_Renderer?
-
@user253751 游戏需要能在原Xbox上运行(使用nxdk工具链移植),SDL_Renderer在里面很慢。
-
我想到了一些可能会有所帮助的方法,而不是绘制单个像素,也许只是为圆的每个 Y 值绘制一条线,从圆周的左侧开始到另一个,以及长度每次都改变。你可以在一个数组中预加载 sin 和 cos 值来访问,这样你就不用在运行时计算它们了