Drawing a rectangle with SDL2

Utundu picture Utundu · Feb 19, 2014 · Viewed 45.7k times · Source

I just started using SDL2 and I already have a problem. I want to create a window and paint it in red. But it remains white, and I don't understand why.

Here is the code :

int main (int argc, char** argv) {
    SDL_Window* pWindow = NULL;
    pWindow = SDL_CreateWindow("Jeu de la vie", SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED,
        640,
        480,
        SDL_WINDOW_SHOWN);

    SDL_Surface* pSurface = NULL;
    pSurface = SDL_GetWindowSurface(pWindow);
    SDL_FillRect(pSurface, NULL, SDL_MapRGB(pSurface->format, 255, 0, 0));

    while(1);

    SDL_FreeSurface(pSurface);
    SDL_DestroyWindow(pWindow);
    SDL_Quit();
    return EXIT_SUCCESS;
}

Answer

olevegard picture olevegard · Feb 20, 2014

There are several issues with your code, I'll try to address most of them.

Initialize SDL

SDL and SDL2 needs to be initialized before you can use it. The way to initialize SDL is the following function.

int SDL_Init(Uint32 flags)

Where flags can be a different value for different subsystems. Use SDL_INIT_EVERYTHING, to initialize everything.

int SDL_Init(SDL_INIT_EVERYTHING)

Read more about it here..


Initialize SDL_Window and SDL_Renderer

SDL_Renderer and SDL_Window needs to be set up before you can use them. You already create your window properly, so I won't cover that. Here's how to set up an SDL_Renderer

SDL_Renderer* SDL_CreateRenderer(SDL_Window* window,
                                 int         index,
                                 Uint32      flags)

index defines what driver to use. Set it to -1 to use the first driver that supports the other arguments.
flags are used to make the rendering optimized, software rendiring, prevent vsync, etc.. Set it to SDL_RENDERER_ACCELERATED.

Read more about SDL_CreateRenderer here.

Mixing SDL and SDL2

SDL_Surface is primarily something used in SDL, not SDL2. SDL2_image, SDL2_ttf etc still used SDL_Surface, but they are converted into an SDL_Texture before they can be used.

SDL_FillRect(...); is also mostly a SDL thing. But as stated above, the SDL_Surface can be used, but you need to convert it to an SDL_Texture first :

SDL_Texture* SDL_CreateTextureFromSurface(SDL_Renderer* renderer,
                                          SDL_Surface*  surface)

Read more here.

And use

int SDL_RenderCopy(SDL_Renderer*   renderer,
                   SDL_Texture*    texture,
                   const SDL_Rect* srcrect,
                   const SDL_Rect* dstrect)

To render it, read more here.

Infinite loop ( while(1); )

You REALLY shouldn't do this, it'll just loop forever. Use SDL_Delay( 5000 ); to pause for 5000msec or 5 seconds.

A simpler way

You can use

int SDL_RenderDrawRect(SDL_Renderer*   renderer,
                       const SDL_Rect* rect)

To draw a rect.

You should use

int SDL_SetRenderDrawColor(SDL_Renderer* renderer,
                           Uint8         r,
                           Uint8         g,
                           Uint8         b,
                           Uint8         a)

To set the color of what you are drawing, use

int SDL_RenderClear(SDL_Renderer* renderer)

After which you call your SDL_RenderDrawRect()

Up until this point, everything has been drawn "behind the scenes." To render it to the screen, use

void SDL_RenderPresent(SDL_Renderer* renderer)

Example

#include <SDL2/SDL.h>

int main (int argc, char** argv)
{
    SDL_Window* window = NULL;
    window = SDL_CreateWindow
    (
        "Jeu de la vie", SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED,
        640,
        480,
        SDL_WINDOW_SHOWN
    );

    // Setup renderer
    SDL_Renderer* renderer = NULL;
    renderer =  SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED);

    // Set render color to red ( background will be rendered in this color )
    SDL_SetRenderDrawColor( renderer, 255, 0, 0, 255 );

    // Clear winow
    SDL_RenderClear( renderer );

    // Creat a rect at pos ( 50, 50 ) that's 50 pixels wide and 50 pixels high.
    SDL_Rect r;
    r.x = 50;
    r.y = 50;
    r.w = 50;
    r.h = 50;

    // Set render color to blue ( rect will be rendered in this color )
    SDL_SetRenderDrawColor( renderer, 0, 0, 255, 255 );

    // Render rect
    SDL_RenderFillRect( renderer, &r );

    // Render the rect to the screen
    SDL_RenderPresent(renderer);

    // Wait for 5 sec
    SDL_Delay( 5000 );

    SDL_DestroyWindow(window);
    SDL_Quit();

    return EXIT_SUCCESS;
}

Result

Rendered result


You can read more about SDL2 on my blog.