Twinklebear / TwinklebearDev-Lessons

Source code and assets for the TwinklebearDev Tutorials
http://www.willusher.io/pages/sdl2/
MIT License
331 stars 97 forks source link

On Lesson 1, the window does not show up #14

Open TonalidadeHidrica opened 4 years ago

TonalidadeHidrica commented 4 years ago

I tried the tutorial Lesson 1. I successfully compiled the file, but when running, it did not show any window; all that happened was that the terminal stopped for exactly three seconds and then the program ended with exit code 0.

I googled and found a similar issue on StackOverflow: SDL Window Not Showing Up at all. According to the answer, it may be the problem that SDL_Delay prevents the window from opening. I tried two source code on the page, one from the question and the other from the answer, then the former does not show the window, while the latter did. So I guess the reason Lesson 1 did not work is the same to that? Maybe it needs to be rewritten.

Also, if you don't mind, please tell me why "SDL_Delay [blocks] the window gets a chance to show"? I'm completely new to SDL, and I want to understand how does it work, what is going on under the hood.

System Information:

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.14.6
BuildVersion:   18G2022
$ g++ --version
Apple clang version 11.0.0 (clang-1100.0.33.17)
Target: x86_64-apple-darwin18.7.0
Thread model: posix
$ brew info sdl2
sdl2: stable 2.0.10 (bottled), HEAD
Low-level access to audio, keyboard, mouse, joystick, and graphics
https://www.libsdl.org/
/usr/local/Cellar/sdl2/2.0.10 (87 files, 4.6MB) *
  Poured from bottle on 2019-09-03 at 09:45:53
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/sdl2.rb
==> Options
--HEAD
        Install HEAD version
==> Analytics
install: 53,946 (30 days), 163,725 (90 days), 730,192 (365 days)
install-on-request: 6,346 (30 days), 19,145 (90 days), 82,627 (365 days)
build-error: 0 (30 days)

The source code I wrote, which did not show a window:

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

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

if (SDL_Init(SDL_INIT_VIDEO) != 0){
    std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl;
    return 1;
}

SDL_Window *win = SDL_CreateWindow("Hello World!", 100, 100, 640, 480, SDL_WINDOW_SHOWN);
if (win == nullptr){
    std::cout << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
    SDL_Quit();
    return 1;
}

SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (ren == nullptr){
    SDL_DestroyWindow(win);
    std::cout << "SDL_CreateRenderer Error: " << SDL_GetError() << std::endl;
    SDL_Quit();
    return 1;
}

std::string imagePath = "/path/to/hello.bmp";
SDL_Surface *bmp = SDL_LoadBMP(imagePath.c_str());
if (bmp == nullptr){
    SDL_DestroyRenderer(ren);
    SDL_DestroyWindow(win);
    std::cout << "SDL_LoadBMP Error: " << SDL_GetError() << std::endl;
    SDL_Quit();
    return 1;
}

SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, bmp);
SDL_FreeSurface(bmp);
if (tex == nullptr){
    SDL_DestroyRenderer(ren);
    SDL_DestroyWindow(win);
    std::cout << "SDL_CreateTextureFromSurface Error: " << SDL_GetError() << std::endl;
    SDL_Quit();
    return 1;
}

//A sleepy rendering loop, wait for 3 seconds and render and present the screen each time
for (int i = 0; i < 10; ++i){
    //First clear the renderer
    SDL_RenderClear(ren);
    //Draw the texture
    SDL_RenderCopy(ren, tex, NULL, NULL);
    //Update the screen
    SDL_RenderPresent(ren);
    //Take a quick break after all that hard work
    SDL_Delay(1000);
}

SDL_DestroyTexture(tex);
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
SDL_Quit();

    return 0;
}
Twinklebear commented 4 years ago

I actually also wouldn't expect SDL_Delay to block the window from showing, I'm not familiar with the SDL internals either but would think that after the window is created it should be opened and visible. Maybe something has changed? It sounds like the latter example from that page (which then starts to poll for events in a loop) does work? I can update the lesson and code to do that, but was avoiding it in that lesson initially to hold off on talking about event handling

TonalidadeHidrica commented 4 years ago

Thanks for the reply. Yeah, avoiding event handling stuff makes easier for the beginner, I agree for that. I'll ask the SDL developers later why does it happen and also ask for a simpler sample without event loop if possible. Maybe rewriting the tutorial can be done afterwards.

AbstractXan commented 4 years ago

Facing this issue. Any updates on this ?

@TonalidadeHidrica thanks for pointing out the StackOverflow article.

Removing SDL_Delay(1000); and Adding this to main.cpp fixes the problem.

// A basic main loop to prevent blocking
bool is_running = true;
SDL_Event event;
while (is_running) {
    while (SDL_PollEvent(&event)) {
        if (event.type == SDL_QUIT) {
            is_running = false;
        }
    }
    SDL_Delay(16);
}
TonalidadeHidrica commented 4 years ago

@AbstractXan Sorry for the late reply. Yeah, the SO article suggests simply adding an event loop.

I was so lazy that I didn't make any contact to SDL developers up until now. But still, it may be useful for beginners if some additional notes are added to the tutorial, telling that one may advance to the next tutorial even if the window did not show up.

veranovus commented 3 years ago

~Facing this issue. Any updates on this ?~

@TonalidadeHidrica thanks for pointing out the StackOverflow article.

Removing SDL_Delay(1000); and Adding this to main.cpp fixes the problem.

// A basic main loop to prevent blocking
bool is_running = true;
SDL_Event event;
while (is_running) {
    while (SDL_PollEvent(&event)) {
        if (event.type == SDL_QUIT) {
            is_running = false;
        }
    }
    SDL_Delay(16);
}

Thanks, I'm using a new M1 MacBook Air and also had this issue but removing the SDL_Delay(1000); and adding that basic loop solved the issue. Thanks a lot.

adomit commented 3 years ago

~Facing this issue. Any updates on this ?~

@TonalidadeHidrica thanks for pointing out the StackOverflow article.

Removing SDL_Delay(1000); and Adding this to main.cpp fixes the problem.

// A basic main loop to prevent blocking
bool is_running = true;
SDL_Event event;
while (is_running) {
    while (SDL_PollEvent(&event)) {
        if (event.type == SDL_QUIT) {
            is_running = false;
        }
    }
    SDL_Delay(16);
}

ths a lot, it works~

jakeyeatsteaky commented 2 years ago

Also on an M1 machine and had to write this loop in order to get the window to show up. Does anyone know why the SDL_Delay(2000) prevents the window from showing, and why the loop fixes it?

teefoss commented 2 years ago

I don't think it has anything to do with SDL_Delay(). On Mac, the window will not appear unless events are processed. If you don't need an event loop as above, just call SDL_PumpEvents() once after creating the window.