【问题标题】:SDL2 function to draw a filled circleSDL2函数绘制一个实心圆
【发布时间】: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 值来访问,这样你就不用在运行时计算它们了

标签: c++ sdl-2 2d-games


【解决方案1】:

我不太清楚如何使用表面和内存管理以及所有这些来做到这一点,但如果这有帮助,这里有一个使用 SDL_Renderer 的版本,运行速度非常快:

void draw_circle(SDL_Renderer *renderer, int x, int y, int radius, SDL_Color color)
{
    SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);
    for (int w = 0; w < radius * 2; w++)
    {
        for (int h = 0; h < radius * 2; h++)
        {
            int dx = radius - w; // horizontal offset
            int dy = radius - h; // vertical offset
            if ((dx*dx + dy*dy) <= (radius * radius))
            {
                SDL_RenderDrawPoint(renderer, x + dx, y + dy);
            }
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-31
    • 1970-01-01
    • 1970-01-01
    • 2022-10-14
    • 2019-01-21
    • 2021-01-30
    • 2011-05-10
    相关资源
    最近更新 更多