30

This is my code:

#include <iostream>
#include <SDL2/SDL.h>

int main(int argc, const char * argv[]) {

SDL_Init(SDL_INIT_VIDEO);

SDL_Window *_window;
_window = SDL_CreateWindow("Game Engine", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 700, 500, SDL_WINDOW_RESIZABLE);

SDL_Delay(20000);

SDL_DestroyWindow(_window);
SDL_Quit();

return 0;

}

Im working in Xcode. I've downloaded SDL2 and imported the library to the projects build phases. I've tested that the SDL2 works correctly.

The problem is that window never shows up. I just get a "spinning-mac-wheel" and then the program quits after the delay. I've made sure that the window is not hidden behind somewhere.

Ideas?

Michael
  • 791
  • 3
  • 10
  • 23

5 Answers5

105

You have to give the system a chance to have it's event loop run.

easiest is to poll for events yourself:

SDL_Event e;
bool quit = false;
while (!quit){
    while (SDL_PollEvent(&e)){
        if (e.type == SDL_QUIT){
            quit = true;
        }
        if (e.type == SDL_KEYDOWN){
            quit = true;
        }
        if (e.type == SDL_MOUSEBUTTONDOWN){
            quit = true;
        }
    }
}

instead of the wait loop

--- Addendum

Since this answer is still helping people maybe it's nice if I also add a bit more info on why this works instead of just posting the solution.

When on the Mac (same for Windows actually) a program starts, it starts with just the 'main thread'. This is the thread which is used to set up UI stuff. The 'main thead' differs from other threads in that it comes with an event handling system. This system catches events like mouse moves, key presses, button clicks and then queues these and lets your code respond to it. All the UI things on Mac (and Windows) rely on this event pump being there and running. This is the reason why if you do anything UI related in your code you need to make sure you are not on a different thread.

Now, in your code you initialise the window and the UI, but then you do a SDL_Delay. This just blocks the thread and halts it for 20 seconds so nothing is done. And since you do that on the main thread, even the handling of the queue with the events is blocked. So on the Mac that shows as the spinning macwheel.

So the solution I posted actually keeps on polling for events and handles them. This way you are effectively also 'idling', but the moment events are posted (like mouse clicks and keys) the thread will wake up again and stuff will be processed.

Toad
  • 15,593
  • 16
  • 82
  • 128
  • 10
    Adding/clarifying above: If you find that SDL_GetError() isn't reporting anything and SDL_UpdateWindowSurface() / etc are reporting 0 (no errors) then its more than likely that the above code will be the fix, particularly on OSX. You would place the event polling loop after your video setup/init/and initial draw call. The original SDL SDK samples used to include the polling but online tutorials typically include this much later in the process (handling input) which can cause confusion. – Jonathan M. May 14 '18 at 18:59
  • 6
    Thank you for this! Helped me out immensely. – Zip Zap J Aug 03 '18 at 19:07
  • 4
    This should be marked as the answer :) removing delay, adding an event way of exiting fixed it instantly. – chrisallick Aug 03 '20 at 21:46
  • This got me up and running with SDL2 on macOS, many thanks! – Simon Bosley Sep 13 '20 at 18:26
  • i come to this page the 3rd time, but i forgot to scroll down far enough to get this answer. – May Jan 22 '22 at 02:45
2

You have to load a bitmap image, or display something on the window, for Xcode to start displaying the window.

#include <SDL2/SDL.h>
#include <iostream>

using namespace std;

int main() {
    SDL_Window * window = nullptr;

    SDL_Surface * window_surface = nullptr;
    SDL_Surface * image_surface = nullptr;

    SDL_Init(SDL_INIT_VIDEO);

    window = SDL_CreateWindow("Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_SHOWN);

    window_surface = SDL_GetWindowSurface(window);
    image_surface = SDL_LoadBMP("image.bmp");

    SDL_BlitSurface(image_surface, NULL, window_surface, NULL);

    SDL_UpdateWindowSurface(window);

    SDL_Delay(5000);

    SDL_DestroyWindow(window);
    SDL_FreeSurface(image_surface);
    SDL_Quit();
}
aden
  • 21
  • 3
1

You need to initialize SDL with SDL_Init(SDL_INIT_VIDEO) before creating the window.

Pierre
  • 1,162
  • 12
  • 29
  • I forgot too add that line to the question. I've edited it now. So that's not the problem.. – Michael Dec 23 '15 at 16:02
  • Ok, I tried on my computer (xubuntu, x86_64), it works. Maybe the window is not showed because it is not used ? Did you try to display something (image or a simple shape or whatever) ? – Pierre Dec 24 '15 at 14:09
0

So I was trying to run a simple code sample from a tutorial but the window was not showing, just as you mentioned in the question.

Apparently, in order for the window to show you could call SDL_Pump_Events before calling the delay. For some reason, I also have to put it inside a short loop in order for this to work.

The working code looks something like this:

#include <SDL2/SDL.h>
#include <iostream>

using namespace std;

int main()
{
    ...

    SDL_Init(SDL_INIT_VIDEO);

    ...

    for (size_t i = 0; i < 100; i++)
    {
        SDL_PumpEvents();
    }

    SDL_Delay(5000);

    ...

    SDL_Quit();
}

For a more in-depth explanation you can check this link where I found this solution.

Yan Tavares
  • 191
  • 1
  • 8
-1

Please remove the sdl_delay() and replace it with the below mentioned code. I don't have any reason for it but I tried on my own and it works

bool isquit = false;
SDL_Event event;
while (!isquit) {
    if (SDL_PollEvent( & event)) {
        if (event.type == SDL_QUIT) {
            isquit = true;
        }
    }
}
Milo
  • 3,365
  • 9
  • 30
  • 44