1

我正在尝试制作一个小行星克隆,到目前为止,我已经让我的船飞起来了。但是它的速度也取决于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();
}
4

1 回答 1

4

我无法运行您的代码,因此我不能 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 但采用 ax,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 并将加速度设置为 0。

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

我希望这能给您更多的想法,并帮助您完全解决您的问题!让我知道事情的后续。

于 2013-06-15T16:05:19.270 回答