【问题标题】:SDL (C)- Window Won't Appear without Event LoopSDL (C) - 没有事件循环,窗口不会出现
【发布时间】:2019-11-23 23:03:19
【问题描述】:

我正在尝试制作一个程序,在一个窗口中呈现几个彩色矩形,然后在几秒钟后消失。基本上,应该会出现以下内容(尽管我遇到了问题,但我很快就会解释我是如何做到的):

The result (I'm new here by the way, is it possible to directly show images in a post instead of having to just include a link to it?)

我尝试运行的代码如下,显然包含 以及“WINDOW_WIDTH”和“WINDOW_HEIGHT”的定义,它们都出现在下面的代码(分别设置为 800 和 640)。

SDL_Window *window;
SDL_Renderer *renderer;

SDL_Init(SDL_INIT_VIDEO);

window = SDL_CreateWindow("Game Window", 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0);

if (window == NULL) {
        // In the case that the window could not be made...
        printf("Could not create window: %s\n", SDL_GetError());
        return 1;
    }

renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);

SDL_RenderClear(renderer);


SDL_SetRenderDrawColor(renderer, 140, 0, 100, 100);

SDL_Rect rect = { 0, 0, 800, 640 };

SDL_RenderFillRect(renderer, &rect);

SDL_SetRenderDrawColor(renderer, 60, 0, 255, 100);

SDL_Rect rect2 = { 40, 40, 720, 560 };

SDL_RenderFillRect(renderer, &rect2);

SDL_SetRenderDrawColor(renderer, 50, 140, 0, 100);

SDL_Rect rect3 = { 80, 80, 640, 480 };

SDL_RenderFillRect(renderer, &rect3);

SDL_SetRenderDrawColor(renderer, 200, 50, 25, 0);

SDL_Rect rect4 = { 120, 120, 560, 400 };

SDL_RenderFillRect(renderer, &rect4);

SDL_RenderPresent(renderer);

SDL_Delay(2000);

SDL_DestroyWindow(window);

SDL_DestroyRenderer(renderer);

SDL_Quit();
return 0;

这段代码看起来应该可以正常工作,实际上对于上述视频中的人(他和我一样,在 MacOS 上使用 Xcode 运行此代码,尽管它的版本要旧得多)也能正常工作。然而,当我运行我的书面代码时,视频中发生的同样的事情似乎并没有发生在我身上。相反,窗口根本不会出现。代码本身确实可以运行,并且非常好,没有任何错误或警告,但是在延迟结束并且 SDL 窗口被破坏之前,带有彩色矩形的窗口根本不会出现。

我意识到这个问题之前已经在这个网站上提出过,并且每个问题都有非常相似的问题,我需要明确一点,是的,我已经尝试使用事件循环,它工作得非常好。例如,如果我运行以下代码,它与第一批代码相同,只是将“SDL_DELAY”替换为事件处理程序,该事件处理程序检测何时按下键盘或鼠标(并且还包括布尔值的 使用的变量)- 窗口看起来很好:

SDL_Window *window;
SDL_Renderer *renderer;

SDL_Init(SDL_INIT_VIDEO);

window = SDL_CreateWindow("Game Window", 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0);

if (window == NULL) {
        // In the case that the window could not be made...
        printf("Could not create window: %s\n", SDL_GetError());
        return 1;
    }

renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);

SDL_RenderClear(renderer);


SDL_SetRenderDrawColor(renderer, 140, 0, 100, 100);

SDL_Rect rect = { 0, 0, 800, 640 };

SDL_RenderFillRect(renderer, &rect);

SDL_SetRenderDrawColor(renderer, 60, 0, 255, 100);

SDL_Rect rect2 = { 40, 40, 720, 560 };

SDL_RenderFillRect(renderer, &rect2);

SDL_SetRenderDrawColor(renderer, 50, 140, 0, 100);

SDL_Rect rect3 = { 80, 80, 640, 480 };

SDL_RenderFillRect(renderer, &rect3);

SDL_SetRenderDrawColor(renderer, 200, 50, 25, 0);

SDL_Rect rect4 = { 120, 120, 560, 400 };

SDL_RenderFillRect(renderer, &rect4);

SDL_RenderPresent(renderer);

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;
        }
    }
}

SDL_DestroyWindow(window);

SDL_DestroyRenderer(renderer);

SDL_Quit();
return 0;

然而,这与第一次尝试实现的目标不同,正如我所说的那样,它是一个窗口,它被渲染然后在短时间内被销毁。如果我不能使用上面显示的第一组代码,我应该如何做到这一点?此外,为什么使用 SDL_DELAY 的这种设置显然对视频中的人有效(为方便起见,可以再次找到 here)但当我尝试输入时却不行?

【问题讨论】:

    标签: c sdl


    【解决方案1】:

    你是对的,它之前被问过很多次。简短的回答是“窗口管理器的行为不同,更糟糕的是,它们可能启用了合成”。基本上你创建窗口,开始绘图,告诉窗口管理器你已经完成了,一段时间后得到信号,你认为你正在绘制的窗口是刚刚创建的,所以你会重画你想要显示的任何东西。当您的窗口调整大小、从最小化状态恢复、被其他窗口遮盖等时,也会发生同样的事情——这总是一件事,简单的 3 行示例只是忽略了它;窗口管理器不负责保存您的图像,每当发生某些事情时,它只会向您发送重绘信号(并不意味着它不允许为自己的目的保留图像,主要用于合成、预览等)。在合成年龄之前,它“大部分时间都有效”。

    窗口管理器也可能依赖目标应用程序的事件处理来显示“应用程序没有响应”对话框。

    所以实际上您的第二个版本仍然不正确,因为您只绘制一次并且不关注重绘事件。游戏通常不会打扰这些事件,因为它们的图像无论如何都非常动态并且无条件地重绘。你不仅需要事件循环,还需要重绘。

    至于如何在经过一段时间后中断循环 - 您需要查看时间以及给定时间间隔何时过去触发您的 quit 或以其他方式中断循环。除了操作系统提供的时间函数,还有SDL_GetTicksSDL_AddTimer等。

    这是一个例子:

    #include <SDL2/SDL.h>
    #include <stdio.h>
    #include <stdbool.h>
    
    #define WINDOW_WIDTH 800
    #define WINDOW_HEIGHT 600
    
    int main(int argc, char **argv) {
        SDL_Window *window;
        SDL_Renderer *renderer;
    
        SDL_Init(SDL_INIT_VIDEO);
    
        window = SDL_CreateWindow("Game Window", 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0);
        if (window == NULL) { return 1; }
    
        renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
        if (renderer == NULL) { return 1; }
    
        const Uint32 time_started = SDL_GetTicks();
        SDL_Event e;
        bool quit = false;
        while (!quit){
            // check for timeout
            if(SDL_GetTicks() - time_started > 2000) { quit = true; }
    
            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;
                }
            }
    
            // break early - doesn't really matter
            if(quit) { break; }
    
            SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
            SDL_RenderClear(renderer);
            SDL_SetRenderDrawColor(renderer, 140, 0, 100, 100);
            SDL_Rect rect = { 0, 0, 800, 640 };
            SDL_RenderFillRect(renderer, &rect);
            SDL_SetRenderDrawColor(renderer, 60, 0, 255, 100);
            SDL_Rect rect2 = { 40, 40, 720, 560 };
            SDL_RenderFillRect(renderer, &rect2);
            SDL_SetRenderDrawColor(renderer, 50, 140, 0, 100);
            SDL_Rect rect3 = { 80, 80, 640, 480 };
            SDL_RenderFillRect(renderer, &rect3);
            SDL_SetRenderDrawColor(renderer, 200, 50, 25, 0);
            SDL_Rect rect4 = { 120, 120, 560, 400 };
            SDL_RenderFillRect(renderer, &rect4);
            SDL_RenderPresent(renderer);
        }
    
        SDL_DestroyRenderer(renderer);
        SDL_DestroyWindow(window);
        SDL_Quit();
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多