C++ 在linux中,当VSYNC打开时,鼠标处理SDL2非常缓慢

C++ 在linux中,当VSYNC打开时,鼠标处理SDL2非常缓慢,c++,sdl-2,linux-mint,sdl-ttf,C++,Sdl 2,Linux Mint,Sdl Ttf,在SDL2的事件处理循环中,调用方法SDL_GetMouseState(&x,&y)或对相对鼠标坐标使用event.motion.x和event.motion.y会使SDL2的响应速度非常缓慢。奇怪的是,SDL\u GetMouseState()比event.motion.x和y快得多,但它们都糟糕得无法忍受。有没有其他方法来获取鼠标位置?你甚至可以试试这个。我在SDL2中设置了一个简单的文本程序来测试一些响应性的东西,比如滚动,在滚动中偏移y值。尝试使用和不使用vsync以及使用和不使用这种方

在SDL2的事件处理循环中,调用方法
SDL_GetMouseState(&x,&y)
或对相对鼠标坐标使用
event.motion.x
event.motion.y
会使SDL2的响应速度非常缓慢。奇怪的是,
SDL\u GetMouseState()
event.motion.x和y
快得多,但它们都糟糕得无法忍受。有没有其他方法来获取鼠标位置?你甚至可以试试这个。我在SDL2中设置了一个简单的文本程序来测试一些响应性的东西,比如滚动,在滚动中偏移y值。尝试使用和不使用vsync以及使用和不使用这种方式获取鼠标位置。我目前正在使用LinuxMint

Code:(如果像我一样使用代码块,则项目所在文件夹中需要arial.ttf)


#包括
#包括
#包括
#包括
使用std::string;
使用std::to_字符串;
int main(int argc,char*argv[])
{
SDL_Init(SDL_Init_视频);
TTF_Init();
SDL_Window*Window=SDL_CreateWindow(“测试程序”,0,30,1280,720,SDL_Window_OPENGL | SDL_Window_可调整大小);//| SDL_Window_显示);
SDL_Renderer*Renderer=SDL_CreateRenderer(窗口,-1,SDL_Renderer_加速| SDL_Renderer_PRESENTVSYNC);
SDL_事件;
SDL_点鼠标点={0,0};
///Fps变量
整型FPS计数器、FPSTART、fpsEnd;
fpstart=SDL_GetTicks();
fpsEnd=SDL_GetTicks();
fpsCounter=0;
TTF_Font*fpsFont=TTF_OpenFont(“arial.TTF”,30);
SDL_Surface*fpsSurface=TTF_RenderText_混合(fpsFont,“FPS:,{0,0,0});
SDL_纹理*fpsTexture=SDL_CreateTextureFromSurface(渲染器,fpsSurface);
SDL_自由曲面(FPS曲面);
int textW,textH,yVal;
yVal=50;
SDL_QueryTexture(fpsTexture、NULL、NULL、&textW和&textH);
SDL_Rect fpsRect={1000,yVal,textW,textH};
bool running=true;
(跑步时)
{
while(SDL_事件和事件))
{
if(event.type==SDL\u QUIT)
{
运行=错误;
打破
}
else if(event.type==SDL\u){
int x,y;
SDL_GetMouseState(x&y);
鼠标座={x,y};
打破
}
else if(event.type==SDL\u鼠标滚轮){
如果(event.wheel.y>0){///在此处向上滚动
yVal-=50;
fpsRect.y=yVal;
打破
}
如果(event.wheel.y<0){///在此处向下滚动
yVal+=50;
fpsRect.y=yVal;
打破
}
}
}
SDL_SetRenderDrawColor(渲染器,255255);
SDL_渲染器(渲染器);
//每0.5s(500ms)更新一次
fpsEnd=SDL_GetTicks();
fps计数器+=2;
如果((fpsEnd FPSTART)>500){
fpstart=SDL_GetTicks();
SDL_破坏纹理(FPS纹理);
///更改文本
字符串newText=(“FPS:+to_字符串(fpsCounter));
fpsSurface=TTF_RenderText_Blended(fpsFont,newText.c_str(),{0,0,0});
fpsTexture=SDL_CreateTextureFromSurface(渲染器,fpsSurface);
SDL_自由曲面(FPS曲面);
SDL_QueryTexture(fpsTexture、NULL、NULL、&textW和&textH);
fpsRect={1000,yVal,textW,textH};
fpsCounter=0;
}
SDL_RenderCopy(渲染器、fpsTexture、NULL和fpsRect);
SDL_渲染器呈现(渲染器);
}
SDL_破坏纹理(FPS纹理);
TTF_CloseFont(fpsFont);
SDL_渲染器(渲染器);
SDL_窗口(窗口);
TTF_Quit();
SDL_退出();
返回0;
}

我不同意关闭VSYNC是一个解决方案。不管怎样,VSYNC打开时都不应该是这样。在windows中,由于某些原因,它不是这样的,它在那里工作得很好。使用SDL_Delay()将FPS限制为显示器的刷新率也会带来同样的问题。

是否有充分的理由通过获取鼠标状态来响应每个SDL_MOUSEMOTION事件?为什么不设置一个标志,然后再获取一次鼠标状态?是的,因为如果有鼠标事件,例如,单击,我需要检查单击时鼠标点是否在框上或类似的东西上。另外,尝试从非SDL\u QUIT分支中删除
中断
。我读到,否则你会导致事件的累积。考虑队列中有10个SDLYMouSyfRevices事件:您将处理一个,然后渲染帧,等待16毫秒,处理另一个,等等。用160毫秒来处理10个鼠标运动事件而不是单个帧。从事件看,绝对不要<代码>中断< /代码>,除非您想关闭应用程序。不要在事件循环中使用
SDL\u GetMouseState
,从您得到的事件中读取鼠标位置。@peterwilson是的。“我没有帖子了,所以我无法发布新的示例”您可以随时编辑现有帖子。你不必做一个新的。

#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
#include <SDL2/SDL_image.h>
#include <string>
using std::string;
using std::to_string;





int main(int argc, char* argv[])
{


    SDL_Init(SDL_INIT_VIDEO);
    TTF_Init();

    SDL_Window *window = SDL_CreateWindow("Test Program", 0, 30, 1280, 720, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);// | SDL_WINDOW_SHOWN);
    SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC );


    SDL_Event event;

    SDL_Point mousePos = {0,0};



    ///Fps vars
    int fpsCounter, fpsStart, fpsEnd;
    fpsStart = SDL_GetTicks();
    fpsEnd = SDL_GetTicks();
    fpsCounter = 0;
    TTF_Font *fpsFont = TTF_OpenFont("arial.ttf", 30);
    SDL_Surface *fpsSurface = TTF_RenderText_Blended(fpsFont, "FPS:  ", {0,0,0});
    SDL_Texture *fpsTexture = SDL_CreateTextureFromSurface(renderer, fpsSurface);
    SDL_FreeSurface(fpsSurface);
    int textW, textH, yVal;
    yVal = 50;
    SDL_QueryTexture(fpsTexture, NULL, NULL, &textW, &textH);
    SDL_Rect fpsRect = {1000, yVal, textW, textH};



    bool running = true;
    while (running)
    {




        while ( SDL_PollEvent(&event) )
        {
            if (event.type == SDL_QUIT)
            {
                running = false;
                break;
            }


            else if (event.type == SDL_MOUSEMOTION){

                int x,y;
                SDL_GetMouseState(&x,&y);
                mousePos = {x,y};
                break;
            }


            else if (event.type == SDL_MOUSEWHEEL){

                if (event.wheel.y > 0){  ///Scrolling up here
                    yVal -= 50;
                    fpsRect.y = yVal;
                    break;
                }
                if (event.wheel.y < 0){  ///Scrolling down here
                    yVal += 50;
                    fpsRect.y = yVal;
                    break;
                }
            }

        }


        SDL_SetRenderDrawColor(renderer, 255,255,255,255);
        SDL_RenderClear(renderer);



        //Update every 0.5s (500ms)
        fpsEnd = SDL_GetTicks();
        fpsCounter += 2;
        if ( (fpsEnd-fpsStart) > 500 ){
            fpsStart = SDL_GetTicks();

            SDL_DestroyTexture(fpsTexture);

            ///Change text
            string newText = ("FPS:  " + to_string(fpsCounter));
            fpsSurface = TTF_RenderText_Blended(fpsFont, newText.c_str(), {0,0,0});
            fpsTexture = SDL_CreateTextureFromSurface(renderer, fpsSurface);
            SDL_FreeSurface(fpsSurface);
            SDL_QueryTexture(fpsTexture, NULL, NULL, &textW, &textH);
            fpsRect = {1000, yVal, textW, textH};

            fpsCounter = 0;
        }


        SDL_RenderCopy(renderer, fpsTexture, NULL, &fpsRect);



        SDL_RenderPresent(renderer);


    }


    SDL_DestroyTexture(fpsTexture);
    TTF_CloseFont(fpsFont);


    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);

    TTF_Quit();
    SDL_Quit();



    return 0;

}