SFML C ++我使用delta时间错了......什么是正确的方法

时间:2013-06-15 13:54:22

标签: 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();
}

1 个答案:

答案 0 :(得分:3)

我无法运行您的代码,因此我不能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

然后我相信这是错误的,导致模拟不当。

总体

您的代码中可能存在其他数学错误。特别是你如何计算加速度。我没有仔细检查这一点,此刻我没有时间。如果你做了我提到的调整但仍然没有工作,请给我一个评论,我可以尝试在有空的时候查看更多。我现在有一个自己的游戏去上班。

EDIT1:

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

OR

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

当然你可以作为游戏开发者作弊并防止你的速度低于零(如果你想让玩家只向前移动)而当你检测到一个负速度时,将Velocity设置为0并将加速度设置为0

注意:加速度“降级”将发生在正面和负面,它将“降级”为零。你将不得不修补这些价值观并进行测试,看看感觉是否合适。加速度应该每秒降低1次吗?你甚至应该使用2和-2的值作为前面提到的加速度值吗? 2和-2可能有效,但3和-3可能更好?这些都是您通过测试自己回答的问题。

我希望这能为您提供更多想法,并帮助您充分解决问题!让我知道它是怎么回事。