SDL 鼠标事件处理速度不够快

问题描述 投票:0回答:2

我已经使用 SDL 几天了,虽然我认为我已经掌握了它的窍门,但我在菜单方面遇到了一个小问题。更具体地说,是菜单中的按钮。当鼠标移动得不太快时,它们可以完美地工作,但是当我稍微加快速度时(在按钮之间移动光标,不断地使按钮从“正常”精灵重绘到“鼠标悬停精灵”),它就会滞后落后,有时根本不更新,并且开始出现小错误。

这是我关于一般按钮和事件管理的所有代码:

while(!Exit)
{
while(SDL_PollEvent(&Ev))
    {

        curTime = SDL_GetTicks();
        if((ControlVar == 1 && Ev.type == SDL_MOUSEMOTION) || (ControlVar == 1 && Ev.type == SDL_MOUSEBUTTONDOWN) || (ControlVar == 1 && Ev.type == SDL_MOUSEBUTTONUP)) {
            But1.doAction();
            But2.doAction();
            But3.doAction();

                if(curTime > lastTime + 25) {
                SDL_RenderClear(Screen);
                ApplyImage("Menu.png");

                But1.Draw();
                But2.Draw();
                But3.Draw();

                SDL_RenderPresent(Screen);
                lastTime = SDL_GetTicks();
            }

        }

        if(Ev.type == SDL_QUIT)
            Exit = true;
    }
SDL_Delay(10);
}

并且:

class Button {
int Id;
int Clip;
SDL_Rect box;
std::string Filepath;

public:

    Button::Button(int number, int X, int Y, std::string filename)
    {
    Id = number;
    Clip = 0;
    box.x = X;
    box.y = Y;
    box.w = 300;
    box.h = 40;

    Filepath = filename;
    }

    void Draw()
    {
    SDL_Texture *tex = nullptr;
    SDL_Rect targetRec;
    tex = IMG_LoadTexture(Screen, Filepath.c_str());
    targetRec.h = 40;
    targetRec.w = 300;
    targetRec.x = 0;
    targetRec.y = Clip * 40;

    SDL_RenderCopy(Screen, tex, &targetRec, &box);

    SDL_DestroyTexture(tex);
    }

    void doAction()
    {
        if(Ev.motion.x > box.x && Ev.motion.x < box.x+box.w && Ev.motion.y > box.y && Ev.motion.y < box.y+box.h)
        {
            if(Ev.type == SDL_MOUSEMOTION && Clip != 2)
                Clip = 1;

            if(Ev.type == SDL_MOUSEBUTTONDOWN && Ev.button.button == SDL_BUTTON_LEFT)
                Clip = 2;

            if(Ev.type == SDL_MOUSEBUTTONUP && Ev.button.button == SDL_BUTTON_LEFT)
                Clip = 1;
        }
        else if(Clip != 0)
            Clip = 0;
    }
};
c++ events mouse sdl
2个回答
4
投票

尝试将

SDL_RenderPresent(Screen);
移动到
while(SDL_PollEvent(&Ev))
循环之外。通过像这样调用 SDL_RenderPresent,您可能每秒只轮询 60 个事件(如果启用了垂直同步,则每帧一个事件),从而导致您看到的延迟。 如果将 SDL_RenderPresent 移到事件循环之外,您将能够处理队列中可用的尽可能多的事件,完成后,您将呈现帧并等待垂直同步。


0
投票

10多年过去了,不知道是否真的是同样的情况,但也许有人会发现它有用。我也有类似的行为:

  • 我想通过按住右键拖动鼠标来旋转相机(绕垂直轴)。
  • 它滞后了很多:开始旋转相机需要一段时间,然后它会旋转一点而鼠标没有任何动作等。

问题似乎是我对队列中的一个事件执行了 1 个操作。其余事件将保留在队列中,并将在主循环的下一帧中进行处理。

我更改了输入处理,以便从整个事件队列中仅生成一个“最终”操作。并且只有“一个动作”是在主循环的框架中完成的。 IE。将其转换为 OP 代码,它看起来像这样: while(!Exit) { bool doActions=false, drawButtons=false; while(SDL_PollEvent(&Ev)) { if(Ev.type == SDL_QUIT) { Exit = true; break; // no need to process the rest of events in SDL } doActions = (ControlVar == 1 && Ev.type == SDL_MOUSEMOTION) || (ControlVar == 1 && Ev.type == SDL_MOUSEBUTTONDOWN) || (ControlVar == 1 && Ev.type == SDL_MOUSEBUTTONUP); // i.e. this bool is for the button actions under the first if: // if((ControlVar == 1 && Ev.type == SDL_MOUSEMOTION) || (ControlVar == 1 && Ev.type == SDL_MOUSEBUTTONDOWN) || (ControlVar == 1 && Ev.type == SDL_MOUSEBUTTONUP)) { // But1.doAction(); // But2.doAction(); // But3.doAction(); curTime = SDL_GetTicks(); drawButtons = doActions && curTime > (lastTime + 25); // and this bool is for the nested if // if(curTime > lastTime + 25) { ... } if (drawButtons) lastTime = SDL_GetTicks(); } // here, all events are drained from the queue // and we picked up the last event to determine what action to execute: if (doActions) { But1.doAction(); But2.doAction(); But3.doAction(); if (drawButtons) { SDL_RenderClear(Screen); ApplyImage("Menu.png"); But1.Draw(); But2.Draw(); But3.Draw(); SDL_RenderPresent(Screen); lastTime = SDL_GetTicks(); } } SDL_Delay(10); }

我不确定它是否与 OP 案例相符。我的原始代码没有在主循环的一帧中处理所有队列。也许,这只是一个愚蠢的错误。

它似乎还修复(或几乎修复)另一个小问题:移动的 3D 网格在相机同时旋转和移动时会有点晃动。一定是因为旋转和移动不是在同一帧中完成的。虽然,我不确定这个。

© www.soinside.com 2019 - 2024. All rights reserved.