c++ - SFML C++ 我错误地使用了增量时间......正确的方法是什么

标签 c++ sfml timedelta

我正在尝试制作一个小行星克隆,到目前为止我已经让我的飞船飞起来了。然而,它的速度也取决于 FPS。因此,为了减轻这种情况,我已经读到我必须将我的控制变量乘以 deltaTime(如果我收集正确的话,帧之间的时间)。然而,当我尝试实现时,这艘船拒绝移动。我认为这是由于可能隐式舍入为 0(转换为 int?)但没有发出警告。我做错了什么?

代码如下:

sf::Vector2f newPosition(0,0);
sf::Vector2f velocity(0,0);
float acceleration = 3.0f;
float angle = 0;
float angularVelocity = 5;
float velDecay = 0.99f;


sf::Clock deltaClock;

window.setFramerateLimit(60);
while (window.isOpen())
{
    sf::Time deltaTime = deltaClock.restart();
    sf::Event event;
    while (window.pollEvent(event))
    {
        if (event.type == sf::Event::Closed || ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape)))
            window.close();
    }
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
    {
        if(velocity.x < 10)velocity.x += acceleration * deltaTime.asSeconds();
        if(velocity.y < 10)velocity.y += acceleration * deltaTime.asSeconds();
        angle = player.getRotation() - 90;
    }
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
    {
        if(velocity.x > 0)velocity.x -= acceleration * deltaTime.asSeconds();
        else velocity.x = 0;
        if(velocity.y > 0)velocity.y -= acceleration * deltaTime.asSeconds();
        else velocity.y = 0;
    }
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
    {
        player.rotate(-angularVelocity);
    }
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
    {
        player.rotate(angularVelocity);
    }

    newPosition.x = player.getPosition().x + (velocity.x * cos(angle * (M_PI / 180.0))) * deltaTime.asSeconds();
    newPosition.y = player.getPosition().y + (velocity.y * sin(angle * (M_PI / 180.0))) * deltaTime.asSeconds();    
    player.setPosition(newPosition);

    velocity.x *= velDecay;
    velocity.y *= velDecay;

    window.clear();
    window.draw(background);
    window.draw(player);
    window.draw(debugText);
    window.display();
}

最佳答案

我无法运行您的代码,因此我不能 100% 确定,但以下内容看起来不正确:

速度计算

velocity.x = (player.getPosition().x + (acceleration * cos(angle * (M_PI / 180.0)) * deltaTime.asSeconds()));
velocity.y = (player.getPosition().y + (acceleration * sin(angle * (M_PI / 180.0)) * deltaTime.asSeconds()));   

试着把它改成这样:

velocity.x = (player.getVelocity().x + (acceleration * cos(angle * (M_PI / 180.0)) * deltaTime.asSeconds()));
velocity.y = (player.getVelocity().y + (acceleration * sin(angle * (M_PI / 180.0)) * deltaTime.asSeconds()));   

这是利用简单的物理方程 vf = vi + a*t 但采用 x,y 分量方式。我相信使用 Position.x 和 Position.y 会完全覆盖这个等式。

注意:语法方面,我给你的代码可能行不通。将任何代码放入 player.getVelocity().x 中,这将使您获得玩家在 X 方向上的当前速度。对 Y 方向做同样的事情。

新位置的设置

我不确定 player.setPosition(velocity); 是否正确。如果 setPosition 函数负责执行以下操作:

newPosition.x = oldPosition.x + (velocity.x/dt)

在 x 和 y 方向上,那应该可行。

但如果它只是在做:

newPosition.x = velocity.x

那么我相信这会是错误的并导致不正确的模拟。

总体

您的代码中可能存在其他数学错误。特别是关于你如何计算加速度。我没有仔细检查这个,目前我没有时间。如果您进行了我提到的调整但仍然无效,请给我评论,我可以在有空的时候尝试查看更多。我现在有自己的游戏要开发。

编辑1:

您的代码看起来好多了。从这里开始,我将添加更改加速度的代码。假设按下 w 键将打开“推进器”,这会为您提供 2 的加速度。当没有按下任何键时,加速度会随着时间的推移而降低(回到零)。不是每帧。在你每帧乘以 0.99 之前。这意味着如果您获得 120 fps(在像这样的简单游戏中完全有可能),半秒内加速度可能为零。你需要根据你的 dt 变量让它降级。但是,一旦它达到零,您仍将拥有正速度。通常这个速度会因重力而随着时间的推移而降低,但在太空中,重力与你在地球上发现的相比会非常小(-9.8m/s 或 -32 ft/s)。所以也许你可以对你的速度实现重力衰减,这也是及时计算的

您可以忽略重力并让它们按下 S 键并应用负加速度 (-2),然后像您所做的那样将其应用于您的速度。这将允许负值降低你的速度,并且可以被认为是你的船在相反方向打开推进器。

当然,作为游戏开发者,您可以作弊并防止您的速度低于零(如果您希望玩家只向前移动)并且当您检测到负速度时,将 Velocity 设置为 0,将 acceleration 设置为 0 .

注意:正向和负向都会发生“降级”加速度,并且会向零“降级”。您将不得不修改这些值并进行测试,看看感觉如何。加速度应该每秒降低 1 吗?您甚至应该使用 2 和 -2 的值作为我之前提到的加速度值吗? 2 和 -2 可能有效,但也许 3 和 -3 更好?这些都是您通过测试可以自己回答的问题。

我希望这能给你更多的想法,帮助你彻底解决问题!让我知道进展如何。

关于c++ - SFML C++ 我错误地使用了增量时间......正确的方法是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17124380/

相关文章:

python - 查找多个 datetime.timedelta 对象的最小公倍数

c++ - 如何在 Eclipse 中配置 Crypto++?

c++ - 在 C++11 标准中,为什么要保留 char 类型实现相关性?

c++ - 在什么情况下您会得到 __declspec(dllimport) 的未解析外部符号?

c++ - 在游戏循环中使用 sleep() 会使增量时间不稳定

c++ - C++ SFML Gamedev书-ResourceHolder类中的未解析外部符号

c++ - lambda 函数不是 throw_move_assignable 吗?

c++ - C++ 服务器上的线程同步

python - 解析 xs :duration datatype into a Python datetime. timedelta 对象?

Python:如何从 datetime.timedelta 对象中获取时间?