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

SDL按下1键时在鼠标坐标绘制‘1’纹理失败问题排查

问题:按下1键无法在鼠标位置绘制指定纹理

用户代码如下:

switch (e.type)
{
    case SDL_QUIT:
    {
        quit = true;
        break;
    }
    case SDL_KEYDOWN:
    {
        switch (e.key.keysym.sym)
        {
            case SDLK_1:
            {
                SDL_Rect rect = {e.motion.x - 8, e.motion.y - 8, 16, 16};
                SDL_RenderCopy(gRenderer, gT[3], NULL, &rect);
                printf("1\n");
                break;
            }
        }
        break;
    }
}

用户反馈按下1键后功能不生效,gT[3]是对应'1'的纹理,怀疑是按键判断相关问题,但不确定原因。

问题分析与解决步骤

  • 核心问题1:KEYDOWN事件中无法通过e.motion获取鼠标坐标
    SDL的事件结构体是union类型,当事件类型为SDL_KEYDOWN时,只有e.key字段有效,e.motion属于鼠标移动事件的字段,此时访问会得到无效值。要获取当前鼠标坐标,应该用SDL_GetMouseState函数:

    int mouseX, mouseY;
    SDL_GetMouseState(&mouseX, &mouseY);
    SDL_Rect rect = {mouseX - 8, mouseY - 8, 16, 16};
    
  • 核心问题2:缺少渲染刷新步骤
    调用SDL_RenderCopy只是把纹理绘制到后台缓冲区,必须调用SDL_RenderPresent(gRenderer)才能把缓冲区内容显示到屏幕上,否则绘制的内容不会被用户看到。

  • 按键判断验证
    代码里的SDLK_1是正确的按键常量,可通过printf("1\n")的输出情况判断按键事件是否触发:如果控制台能打印"1",说明按键判断没问题,问题出在坐标获取或渲染刷新;如果没打印,再检查事件循环是否正确调用SDL_PollEvent处理事件。

调整后的代码片段示例:

switch (e.type)
{
    case SDL_QUIT:
    {
        quit = true;
        break;
    }
    case SDL_KEYDOWN:
    {
        switch (e.key.keysym.sym)
        {
            case SDLK_1:
            {
                int mouseX, mouseY;
                SDL_GetMouseState(&mouseX, &mouseY);
                SDL_Rect rect = {mouseX - 8, mouseY - 8, 16, 16};
                SDL_RenderCopy(gRenderer, gT[3], NULL, &rect);
                SDL_RenderPresent(gRenderer); // 新增渲染刷新步骤
                printf("1\n");
                break;
            }
        }
        break;
    }
}

补充说明:如果你的渲染逻辑是在事件循环之外统一执行清屏、绘制、刷新操作,那可以不用在按键事件里单独调用SDL_RenderPresent,但要确保本次绘制操作在清屏之后、统一刷新之前执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 02:10:32