I'm starting a new project in SDL2 and as I'm still trying out different architectural approaches I usually start out by bringing up a white window to confirm that the new approach I'm trying out satisfies at least the bare minimum to get started with SDL2.
This time, I wanted to try wrapping my application into a separate Application
class so as to unclutter main
, like so:
#include <SDL2/SDL.h>
#include <stdio.h>
#include <string>
#include "HApplication/HApplication.h"
//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
int main(int argc, char *argv[])
{
HApplication application = HApplication( SCREEN_WIDTH, SCREEN_HEIGHT );
bool hasStarted = application.checkRunning();
if ( hasStarted ){
application.run();
}
else{
std::string msg = "Application failed to initialize.";
SDL_LogError( SDL_LOG_CATEGORY_ERROR, msg.c_str() );
}
// add error codes
return 0;
}
Now, the run
method in HApplication
is meant to reflect the main loop until the user exits. For test purposes, I'd just like to get two lines crossing in the middle on a white background. After initializing SDL, the window, and the renderer, which all work out fine, I'm presented with a window filled completely back, although I've used very similar code successfully before:
void HApplication::run()
{
// while user doesn't quit, keep going
bool userQuit = false;
SDL_Event e
while( !userQuit )
{
// handle queued events
while ( SDL_PollEvent( &e ) != 0 )
{
if ( e.type == SDL_QUIT )
{
userQuit = true;
}
}
// clear screen
SDL_SetRenderDrawColor( appRenderer, 255, 255, 255, 255);
SDL_RenderClear( appRenderer );
// draw cross
SDL_SetRenderDrawColor( appRenderer, 0, 0, 0, 255 );
SDL_RenderDrawLine( appRenderer, 0, screenHeight/2, screenWidth, screenHeight/2);
SDL_SetRenderDrawColor( appRenderer, 0, 0, 0, 255 );
SDL_RenderDrawLine( appRenderer, screenWidth/2 , 0, screenWidth/2, screenHeight);
// update screen with new scene
SDL_RenderPresent( appRenderer );
SDL_UpdateWindowSurface( appWindow );
}
close();
}
I'm not quite sure why this happens, especially since I can see what I want stepping through the loop step-by-step using the debugger. I am quite honestly pretty much at a loss at where to even start.
I tried looking on Google and Stackoverflow for similar questions. However, these were mostly addressing problems with loading textures, which I haven't even gotten to yet. If possible, I would like to keep a separate class handling game logic and resources.
EDIT: It seems like I needed to get rid of SDL_UpdateWindow
. However, I'm not quite sure why. If anyone has an explanation, I'd be happy to hear!
SDL has both a CPU rendering API and a GPU one.
Everything that works with a SDL_Renderer
belongs to the GPU API. For example, you can make a SDL_Texture
and use SDL_RenderCopy
to render it. The final step is to call SDL_RenderPresent
so that everything that was rendered gets displayed.
SDL_UpdateWindowSurface
is part of the CPU API. To use this API, you can for example draw to a SDL_Surface
and then use SDL_BlitSurface
with SDL_GetWindowSurface
to render to the window's surface. The final step is to call SDL_UpdateWindowSurface
to display the changes, which is the equivalent to SDL_Flip
in SDL 1.2.
In short: after the SDL_RenderPresent
call, you get what you wanted, but after the SDL_UpdateWindowSurface
call, you overwrite that with the CPU window surface which is probably initialized to black. Just remove that SDL_UpdateWindowSurface
call and use the GPU API only.