SDL2窗口失焦时矩形动画停止,如何实现持续运行?
解决SDL矩形仅在输入时移动的问题
嘿,我一眼就看出问题所在了——你把矩形的更新和渲染逻辑全都塞进了SDL_PollEvent的循环内部!
问题根源
SDL_PollEvent()的循环只会在有事件发生(比如鼠标移动、按键按下、窗口关闭)的时候执行迭代。没有事件的时候,这个循环根本不会跑,你的矩形自然就停住了。要让动画持续运行,必须把状态更新和渲染逻辑移到事件循环的外面,放在主游戏循环里,这样不管有没有输入事件,每一次主循环都会执行更新和渲染操作。
修改后的完整代码
#include <stdio.h> #include <SDL_image.h> #include <SDL.h> const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; SDL_Window *gWindow = nullptr; SDL_Renderer *gRenderer = nullptr; bool init() { bool in = true; if (SDL_Init(SDL_INIT_VIDEO)<0) { printf("SDL_ did not init, %s", SDL_GetError()); in = false; } else { if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1")) { printf("linear texture filtering boned.\n"); in = false; } else { gWindow = SDL_CreateWindow("CELLULA_CHARLIE", 1000, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_ALWAYS_ON_TOP); if (gWindow == nullptr) { printf("gwindow did not load, %s", SDL_GetError()); in = false; } else { gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); if (gRenderer == nullptr) { printf("main renderer failed loading, %s", SDL_GetError()); in = false; } else { SDL_SetRenderDrawColor(gRenderer, 255, 255, 255, 255); int imgFlags = IMG_INIT_PNG; if (!(IMG_Init(imgFlags)&imgFlags)) { printf("Img did not init, %s", IMG_GetError()); in = false; } } } } } return in; } void close() { SDL_DestroyRenderer(gRenderer); SDL_DestroyWindow(gWindow); gWindow = nullptr; gRenderer = nullptr; IMG_Quit(); SDL_Quit(); } int main(int argc, char*args[]) { int i = 0; SDL_Rect rectangle; rectangle.h = rectangle.w = 32; rectangle.x = rectangle.y = 0; if (!init()) { printf("init failed\n"); } else { bool quit = false; SDL_Event e; while (!quit) { // 单独处理事件,只负责响应输入/系统事件 while (SDL_PollEvent(&e) != 0) { if (e.type == SDL_QUIT) { quit = true; } } // 状态更新:移动矩形 rectangle.x = i * 32; rectangle.y = rectangle.x; i++; if (rectangle.x > 500) { i = 0; } // 渲染流程:清屏→绘制矩形→显示画面 SDL_SetRenderDrawColor(gRenderer, 255, 255, 255, 255); SDL_RenderClear(gRenderer); SDL_SetRenderDrawColor(gRenderer, 0, 0, 0, 255); SDL_RenderFillRect(gRenderer, &rectangle); SDL_RenderPresent(gRenderer); // 可选:添加延迟控制移动速度,否则会非常快 SDL_Delay(30); } } close(); return 0; }
关键修改点
- 拆分循环结构:把事件处理、状态更新、渲染分成三个独立的部分,都放在主
while(!quit)循环内,但事件处理是单独的子循环。 - 控制帧率:添加了
SDL_Delay(30)让矩形移动速度更合理(大约30帧/秒),你可以根据需求调整这个数值。 - 逻辑分离:事件处理只负责处理退出等事件,更新和渲染逻辑每次主循环都会执行,保证动画持续运行。
额外优化建议
如果想要更精确的帧率控制,推荐使用SDL_GetTicks()来计算时间差,替代固定的SDL_Delay,这样可以让动画在不同性能的设备上保持一致的速度。比如:
Uint32 lastTime = SDL_GetTicks(); const int FPS = 30; const int frameDelay = 1000 / FPS; while (!quit) { Uint32 currentTime = SDL_GetTicks(); Uint32 frameTime = currentTime - lastTime; // ...事件处理、更新、渲染逻辑... if (frameTime < frameDelay) { SDL_Delay(frameDelay - frameTime); } lastTime = currentTime; }
内容的提问来源于stack exchange,提问作者Wkulczi
相关产品推荐
相关产品推荐

