按下 space 时如何获得更平滑的旋转
How can I get smoother rotation when space is pressed
我正在制作一个游戏,当按下 space 射击敌人时,坦克的喷嘴会旋转。但是,就在一开始按下 space 时,它似乎停止了几毫秒,然后继续没有任何问题。我怎样才能使旋转从一开始就在按下 space 时平滑且一致?这是一个最小的可重现示例:
#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;
}
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
的内容,当你为 space 键获得 SDL_KEYDOWN
时将其设置为 true
,并设置为 false
当您获得相同密钥的 SDL_KEYUP
时。然后,在事件循环之外,如果设置了变量,则旋转喷嘴。
或者您可以使用 SDL_GetKeyboardState
。 SDL 会自动为每个键执行此操作,您可以使用此功能访问它维护的标志列表。
此外,在我们讨论的过程中,您通常不想使用 键码 (.sym == SDLK_SPACE
) 进行游戏控制。首选 scancodes (.scancode == SDL_SCANCODE_SPACE
)。只有在异国情调的布局(例如 AZERTY)上,差异才会变得明显:键码代表印在键帽上的字母,而扫描码代表物理键位置。例如,在 AZERTY 上你想使用 ZQSD 而不是 WASD。如果您使用扫描码,它会自动发生(SDL_SCANCODE_W
将代表 Z,依此类推)。
scaling rotation with frame-rate isn't really what I am looking for. Its a different problem
你也需要解决这个问题。如果您不希望旋转速度取决于 FPS(坏事),则必须将旋转角度乘以帧长度(可行,但这样很容易出错),或者确保您的游戏逻辑运行无论 FPS 是多少,每秒固定的次数(我更喜欢这个解决方案)。参见 Fix Your Timestep!。
我正在制作一个游戏,当按下 space 射击敌人时,坦克的喷嘴会旋转。但是,就在一开始按下 space 时,它似乎停止了几毫秒,然后继续没有任何问题。我怎样才能使旋转从一开始就在按下 space 时平滑且一致?这是一个最小的可重现示例:
#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;
}
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
的内容,当你为 space 键获得 SDL_KEYDOWN
时将其设置为 true
,并设置为 false
当您获得相同密钥的 SDL_KEYUP
时。然后,在事件循环之外,如果设置了变量,则旋转喷嘴。
或者您可以使用 SDL_GetKeyboardState
。 SDL 会自动为每个键执行此操作,您可以使用此功能访问它维护的标志列表。
此外,在我们讨论的过程中,您通常不想使用 键码 (.sym == SDLK_SPACE
) 进行游戏控制。首选 scancodes (.scancode == SDL_SCANCODE_SPACE
)。只有在异国情调的布局(例如 AZERTY)上,差异才会变得明显:键码代表印在键帽上的字母,而扫描码代表物理键位置。例如,在 AZERTY 上你想使用 ZQSD 而不是 WASD。如果您使用扫描码,它会自动发生(SDL_SCANCODE_W
将代表 Z,依此类推)。
scaling rotation with frame-rate isn't really what I am looking for. Its a different problem
你也需要解决这个问题。如果您不希望旋转速度取决于 FPS(坏事),则必须将旋转角度乘以帧长度(可行,但这样很容易出错),或者确保您的游戏逻辑运行无论 FPS 是多少,每秒固定的次数(我更喜欢这个解决方案)。参见 Fix Your Timestep!。