【问题标题】:Fixed Timestep at 2500 FPS?固定时间步长为 2500 FPS?
【发布时间】:2014-10-12 14:00:06
【问题描述】:

我正在使用 SFML 制作 2D 平台游戏。我阅读了很多时间步长文章,但它们对我来说效果不佳。我正在以 2500 FPS 的时间步长实现它,在我的台式电脑上它非常流畅,在我的笔记本电脑上它达到了 300 FPS(我检查了 Fraps),它在笔记本电脑上不是那么流畅,但仍然可以播放。

这里是sn-ps的代码:

sf::Clock clock;
const sf::Time TimePerFrame = sf::seconds(1.f/2500.f);
sf::Time TimeSinceLastUpdate = sf::Time::Zero;
sf::Time elapsedTime;

这些是变量,这里是游戏循环,

while(!quit){
        elapsedTime = clock.restart();
        TimeSinceLastUpdate += elapsedTime;

        while (TimeSinceLastUpdate > TimePerFrame){
            TimeSinceLastUpdate -= TimePerFrame;
            Player::instance()->handleAll();
        }

        Player::instance()->render();
}

在 Player.h 中,我有运动常数,

    const float GRAVITY = 0.35      /2500.0f; // Uses += every frame
    const float JUMP_SPEED = -400.0f/2500.0f; //SPACE -> movementSpeed.y = JUMP_SPEED;

    //When character is touching to ground
    const float LAND_ACCEL = 0.075  /2500.0f; // These are using += 
    const float LAND_DECEL = 1.5    /2500.0f;
    const float LAND_FRICTION = 0.5 /2500.0f;
    const float LAND_STARTING_SPEED = 0.075; // This uses =, instead of +=

在Player类的handleAll函数中,有

cImage.move(movementSpeed);
checkCollision();

最后,checkCollision 函数简单地检查角色的主边界框是否从每一侧与对象的矩形相交,将速度 x 或 y 设置为 0,然后通过将角色位置设置为边缘来修复重叠。

//Collision
if(masterBB().intersects(objectsIntersecting[i]->GetAABB())){
    //HORIZONTAL
    if(leftBB().intersects(objectsIntersecting[i]->GetAABB())){
        if(movementSpeed.x < 0)
            movementSpeed.x = 0;
        cImage.setPosition(objectsIntersecting[i]->GetAABB().left + objectsIntersecting[i]->GetAABB().width + leftBB().width , cImage.getPosition().y);
    }
    else if(rightBB().intersects(objectsIntersecting[i]->GetAABB())){
        if(movementSpeed.x > 0)
            movementSpeed.x = 0;
        cImage.setPosition(objectsIntersecting[i]->GetAABB().left - rightBB().width , cImage.getPosition().y);
    }

    //VERTICAL
    if(movementSpeed.y < 0 && topBB().intersects(objectsIntersecting[i]->GetAABB())){
        movementSpeed.y = 0;
        cImage.setPosition(cImage.getPosition().x , objectsIntersecting[i]->GetAABB().top + objectsIntersecting[i]->GetAABB().height + masterBB().height/2);
    }

    if(movementSpeed.y > 0 && bottomBB().intersects(objectsIntersecting[i]->GetAABB())){
        movementSpeed.y = 0;
        cImage.setPosition(cImage.getPosition().x , objectsIntersecting[i]->GetAABB().top - masterBB().height/2);
        //and some state updates
    }
}

我尝试像百万次一样使用 60 FPS 时间步长,但所有速度变量都变得如此缓慢,我不能简单地对所有常量执行 *2500.0f / 60.0f,感觉不一样。如果我得到接近的常数,感觉“还可以”,但是当碰撞发生时,角色的位置一直在设置并且它飞出地图,因为每帧都应用高速常数导致物体上的大圈我猜...

我需要补充一下,正常情况下,我拿时间步码使用的书

cImage.move(movementSpeed*TimePerFrame.asSeconds());

但正如你所见,我只是将 /2500.0f 放在每个常量上,我不使用它。

那么,每帧 1/2500 秒好吗?如果没有,如何将所有这些更改为 1/60.0f?

【问题讨论】:

  • 您可以让模拟以比动画更高的速率运行,或者您可以在移动之前检查碰撞并根据此调整运动。例如。在移动之前检查新的边界框是否有碰撞,如果它与某物相交,则找出确切的撞击点和时间,然后根据它计算新的路径
  • 2500 帧/秒?!你是认真的吗?

标签: c++ time game-physics sfml clock


【解决方案1】:

你做错了。

您的显示器很可能具有 60 Hz (= 60 FPS) 的刷新率,因此尝试以 2500 FPS 的速度渲染图像是对资源的巨大浪费。如果选择 2500 FPS 的唯一原因是你的运动不一样,你有没有想过,问题可能出在运动代码上?

您最多可以实现一个固定的时间步长 (famous article),这样您的物理可以以您想要的任何速率运行(2500“FPS”仍然很疯狂,所以不要这样做)并且独立于你的渲染率。所以即使你得到一些不同的 FPS,它也不会影响你的物理。

【讨论】:

  • 如果我将它设置为 60 fps 并且用户有一个 144 hz 的显示器怎么办?他会觉得很波涛汹涌。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-11-12
  • 1970-01-01
  • 2013-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多