Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SDL2 function to draw a filled circle

I am looking for a function that draws a filled circle using SDL2 without using a renderer at all. I currently have this:

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);
}

which has been adapted from another function I found here, it draws the pixels directly to the windowSurface after calling eraseOldCircle (which puts the game's background image back to the previous position of the circle, effectively erasing it from there.) but it is still too slow for what I need (probably the maths?). What would be the fastest way to draw a circle using direct pixel access? I need it to be high speed so I can use it in a 2D game. I haven't been able to find anything until now, everything I see uses SDL_Renderer, but I should strictly never use it.

Here is eraseOldCircle() in case it helps:

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);
}
like image 441
Κοσμάς Ράπτης Avatar asked Nov 24 '25 21:11

Κοσμάς Ράπτης


1 Answers

I'm not too sure how to do it with surfaces and memory management and all that, but if this helps, here is a version using an SDL_Renderer that runs pretty quickly:

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);
            }
        }
    }
}
like image 173
Ggsgn Hdjwngnf Avatar answered Nov 26 '25 10:11

Ggsgn Hdjwngnf