Search code examples
c++sdlsdl-2game-development

properly rendering an SDL rectangle to the screen


Here is my code, I am following lazyfoos tutorials on SDL, here is the exact tutorial I am following - http://lazyfoo.net/tutorials/SDL/08_geometry_rendering/index.php

Notice the call to SDL_SetRenderDrawColor. We're using 255 red and 255 green which combine together to make yellow. Remember that call to SDL_SetRenderDrawColor at the top of the loop? If that wasn't there, the screen would be cleared with whatever color was last set with SDL_SetRenderDrawColor, resulting in a yellow background in this case.

Lazyfoo does explain it above but it still doesn't make sense to me.

To draw a filled rectangle to the screen is a pretty trivial task but it's a task that sometimes causes a lot of confusion,for example you need to call SDL_SetRenderDrawColor() not once but twice,once before you clear the renderer,and also once before you call SDL_RenderFillRect().

Why do you need to call SDL_SetRenderDrawColor() twice and why in that order? I noticed if I comment out the first SDL_SetRenderDrawColor() just before the call to SDL_RenderFillRect(),the full window will be the colour you set the rectangle to be,but when you include the two calls to SDL_SetRenderDrawColor() in the order I specified the window shows a coloured rectangle in the centre of the screen with the rest of the screen being white(first SDL_SetRenderDrawColor() call).

Here is my game loop where the calls are made.

while( !quit )
{
    while( SDL_PollEvent( &event ) != 0 )
    {
        if( event.type == SDL_QUIT )
        {
            quit = true;

        }
    }

    SDL_SetRenderDrawColor( renderer, 255, 255, 255, 0 ); // line of code in question
    SDL_RenderClear( renderer );

    SDL_Rect fillRect = { 500 / 4, 500 / 4, 500 / 2, 500 / 2 };
    SDL_SetRenderDrawColor( renderer, 0x00, 0xFF, 0x00, 0xFF ); // 2nd line of code in question
    SDL_RenderFillRect( renderer, &fillRect );

    SDL_RenderPresent( renderer );
}

Solution

  • Why do you need to call SDL_SetRenderDrawColor() twice and why in that order?

    The name of SDL_RenderClear is a bit misleading. It doesn't clear the screen to "empty" or anything - it just fills it with whatever color was set by SDL_SetRenderDrawColor. So if you don't change the color between "clearing" and drawing the rectangle, then you won't see the rectangle because you're drawing it with the same color that you just filled the entire screen with.

    So here

    SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
    SDL_RenderClear( gRenderer );
    

    You make the whole screen white. We do this by setting white, and then painting over the entire screen with white.

    Then here

    SDL_SetRenderDrawColor( gRenderer, 0xFF, 0x00, 0x00, 0xFF );  
    

    We set red so the rectangle here

    SDL_RenderFillRect( gRenderer, &fillRect );
    

    Will be red (not white).

    And if I remember the tutorial correctly, it also draws a line and some other things, every time calling SDL_SetRenderDrawColor right before to set the correct color.

    I noticed if I comment out the first SDL_SetRenderDrawColor() just before the call to SDL_RenderFillRect(),the full window will be the colour you set the rectangle to be

    Very good observation! You see, since you're looping (while(!quit){) you do SDL_RenderClear and then SDL_RenderFillRect... but then SDL_RenderClear comes again, and so on. So when SDL_RenderClear happens, the color was actually set from right before SDL_RenderFillRect in the last run through the loop. Hence why it has that color, too.

    So actually, I don't know what the color is at the very first time because it's not set yet (might be a default value of white, or something), but we probably can't see it because that's just on the first run through the loop anyway. So what happens roughly is:

    ...
    SDL_RenderClear(renderer);
    SDL_SetRenderDrawColor( renderer, 0x00, 0xFF, 0x00, 0xFF );
    SDL_RenderFillRect( renderer, &fillRect );
    SDL_RenderClear(renderer);
    SDL_SetRenderDrawColor( renderer, 0x00, 0xFF, 0x00, 0xFF );
    SDL_RenderFillRect( renderer, &fillRect ); 
    SDL_RenderClear(renderer);
    SDL_SetRenderDrawColor( renderer, 0x00, 0xFF, 0x00, 0xFF );
    SDL_RenderFillRect( renderer, &fillRect ); 
    ...
    

    So you see, with only that second SDL_SetRenderDrawColor call, both SDL_RenderClear and SDL_RenderFillRect will always draw in green, except the very first SDL_RenderClear call in the first frame.