我正在尝试制作一个程序,该程序在窗口中呈现几个彩色矩形,然后在几秒钟后消失。基本上,应该出现以下内容(尽管我遇到了问题,我将在短期内首先解释如何实现它):
我要运行的代码如下,显然可以包含
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),但是当我尝试输入时却无效?
答案 0 :(得分:1)
您是对的,之前曾多次被问到。简短的答案是“窗口管理器的行为有所不同,更糟糕的是,他们可能启用了合成”。基本上,您创建窗口,开始绘制,告诉窗口管理器您已经完成,并且一段时间后,您会收到信号,表明您认为正在绘制的窗口是刚刚创建的,因此请您重新绘制要显示的内容。当调整窗口大小,从最小化状态还原,被其他窗口遮盖等等时,会发生相同的事情-这始终是一件事情,简单的3行示例只是忽略了它;窗口管理器不负责保存您的图像,只要发生任何事情,它只会向您发送重新绘制的信号(这并不意味着它不允许出于自己的目的保留图像,主要用于合成,预览等)。在合成年龄之前,它“大部分时间都有效”。
窗口管理器还可能依赖于目标应用程序的事件处理来显示“应用程序无响应”对话框。
因此,实际上您的第二个版本仍然不正确,因为您只绘制了一次,而不关注重新绘制事件。游戏通常不会打扰这些事件,因为它们的图像反而是非常动态的,可以无条件重绘。您不仅需要事件循环,还需要重绘。
关于如何在经过一段时间后中断循环-您需要查看时间以及经过给定间隔后触发quit
或以其他方式中断循环。除了操作系统提供的时间功能外,还有SDL_GetTicks
,SDL_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;
}