按下空格时如何使旋转更平稳

时间:2020-10-02 22:56:54

标签: c++ sdl-2

我正在做一个游戏,当按下空间射击敌人时,坦克的喷嘴会旋转。但是,就在刚按下空格时,它似乎停了几毫秒,然后继续进行,没有任何问题。如何从一开始就按下空间,使旋转平滑且一致?这是一个最小的可重现示例:

#include "SDL.h"
#include <iostream>

class Nozzle
{
public:
    void draw(SDL_Renderer* renderer, int cx, int cy, int l)
    {
        float x = ((float)cos(angle) * l) + cx;
        float y = ((float)sin(angle) * l) + cy;
        SDL_RenderDrawLine(renderer, cx, cy, (int)x, (int)y);
    }

    void plusAngle(float a)
    {
        angle += a;
    }

private:
    float angle = 0.0f;
};


int main(int argc, char* argv[])
{
    SDL_Window* window = SDL_CreateWindow("RGame", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1200, 600, false);
    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);
    SDL_Event event;
    Nozzle nozzle;
    bool running = true;

    while (running)
    {
        while (SDL_PollEvent(&event))
        {
            if (event.type == SDL_QUIT)
                running = false;
            if (event.type == SDL_KEYDOWN)
            {
                if (event.key.keysym.sym == SDLK_SPACE)
                    nozzle.plusAngle(0.1f);
            }
        }

        SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
        SDL_RenderClear(renderer);
        SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
        nozzle.draw(renderer, 600, 300, 70);
        
        SDL_RenderPresent(renderer);
        
    }

    SDL_DestroyWindow(window);
    SDL_Quit();

    return 1;
}

1 个答案:

答案 0 :(得分:1)

if (event.type == SDL_KEYDOWN)
{
    if (event.key.keysym.sym == SDLK_SPACE)
        nozzle.plusAngle(0.1f);
}

这不是您在游戏中进行控制的方式。

如果您打开文本编辑器并按住一个键,您会看到一个字母被键入,然后在延迟之后,源源不断的重复输入相同的字母。 SDL做同样的事情,它以这种方式为您提供伪造的重复“按键失败”事件。通常用于编辑文本,而不用于游戏控件。 (那些重复的事件以event.key.repeat == true标记)。

您应该做的是创建bool space_key_down之类的东西,在获得true的空格键时将其设置为SDL_KEYDOWN,而在获得{时将其设置为false {1}}用于相同的密钥。然后,在事件循环之外,如果设置了变量,则旋转喷嘴。

或者您可以使用SDL_KEYUP。 SDL为每个键自动执行此操作,您可以使用此功能访问其维护的标志列表。

此外,在我们进行游戏时,您通常不希望将键码SDL_GetKeyboardState)用于游戏控件。首选 scancodes .sym == SDLK_SPACE)。区别仅在特殊的布局(例如AZERTY)上变得明显:键代码代表键帽上印刷的字母,而扫描代码代表物理键位置。例如,在AZERTY上,您要使用 Z Q S D 而不是 W A S D 。如果您使用扫描码,它将自动发生(.scancode == SDL_SCANCODE_SPACE代表 Z ,依此类推)。


用帧速率缩放旋转并不是我真正想要的。这是一个不同的问题

您也需要解决此问题。如果您不希望旋转速度取决于FPS(不好的事情),则必须将旋转角度乘以帧长(它可以工作,但是很容易以这种方式犯错),或者确保您的游戏逻辑能够运行固定每秒的固定时间,与FPS无关(我更喜欢这种解决方案)。参见Fix Your Timestep!