You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SDL2中无法在窗口绘制简单位图问题求助

SDL2窗口显示空白的问题排查与修复

核心问题分析与修复

1. 窗口表面获取顺序错误

在gameinit函数中,你先调用了SDL_GetWindowSurface(window),但此时window还未被创建(SDL_CreateWindow在这行之后),导致screensurface指向无效内存地址。后续的SDL_BlitSurface操作根本没有写入到实际窗口的表面上。

修复:
将获取窗口表面的代码移到SDL_CreateWindow成功之后:

window = SDL_CreateWindow("Transcend", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
if( window == NULL ){
    // 错误处理代码
    return false;
}
// 现在窗口已创建,获取其表面
screensurface = SDL_GetWindowSurface(window);

2. 按键事件处理逻辑错误

你的事件处理中存在两处关键错误:

  • 直接用event.type匹配SDLK_w这类按键码是错误的,event.type表示事件类型(比如按键按下是SDL_KEYDOWN),具体按键码需要从event.key.keysym.sym中获取
  • 每个case后缺少break,会导致触发一个按键时所有后续的按键标志都被设为true

修复:
修改事件循环中的按键处理代码:

while (SDL_PollEvent(&event) != 0) {
    if (event.type == SDL_QUIT) {
        quit = true;
    }
    // 处理按键按下事件
    if(event.type == SDL_KEYDOWN){
        switch(event.key.keysym.sym) {
            case SDLK_w:
                kpresses.wdown = true;
                break; // 必须添加break避免贯穿
            case SDLK_a:
                kpresses.adown = true;
                break;
            case SDLK_s:
                kpresses.sdown = true;
                break;
            case SDLK_d:
                kpresses.ddown = true;
                break;
            case SDLK_e:
                kpresses.edown = true;
                break;
            case SDLK_ESCAPE:
                kpresses.escdown = true;
                quit = true; // 可选:按ESC直接退出
                break;
        }
    }
}

3. 图片路径与错误日志问题

  • 你使用相对路径"Sprite.bmp",需要确保该图片位于生成的Transcend.exe所在目录(即上级目录,因为编译命令指定输出为../Transcend.exe),否则SDL_LoadBMP会返回NULL
  • 错误日志的关闭方式有误,errfile.std::ofstream::close();应改为errfile.close();,避免语法冗余和潜在问题

修复:

  • 将Sprite.bmp复制到Transcend.exe所在的上级目录测试
  • 替换所有错误日志中的关闭语句为errfile.close();

4. 资源泄漏问题

gamehalt函数中未释放加载的图片表面,会造成资源泄漏。

修复:

void gamehalt()
{
    SDL_FreeSurface(image);
    image = NULL;
    SDL_DestroyWindow(window);
    window = NULL;
    SDL_Quit();
}

修正后的gameinit函数示例

bool gameinit() {
    std::ofstream errfile;
    errfile.open("errlog.txt");
    clearkpresses();
    setrect();
    if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) < 0 ) {
        errmsg = "SDL could not initialize! SDL_Error:";
        std::cout << errmsg << SDL_GetError() << std::endl;
        errfile << errmsg << SDL_GetError() << std::endl;
        errfile.close();
        
        return false;
    }
    window = SDL_CreateWindow("Transcend", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
    if( window == NULL ){
        errmsg = "Window could not be created! SDL_Error:";
        std::cout << errmsg << SDL_GetError() << std::endl;
        errfile << errmsg << SDL_GetError() << std::endl;
        errfile.close();

        return false;
    }
    // 修正:创建窗口后再获取表面
    screensurface = SDL_GetWindowSurface(window);
    image = SDL_LoadBMP(imgpath);
    if (image == NULL) {
        errmsg = "Media unable to load! IMG Error: ";
        std::cout << errmsg << SDL_GetError() << std::endl;
        errfile << errmsg << SDL_GetError() << std::endl;
        errfile.close();

        return false;
    }
    return true;
}

内容的提问来源于stack exchange,提问作者Owen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 04:20:35