Hi guys. I have been using SFML for 2 months. As I learned the command queue system, I made a small test that you can move a tank. I decided to add accelerate each time unit, rather than keep velocity frame-independent.
The code looks like this:
void World::adaptEntityVelocity(Entity& entity, sf::Time dt)
{
static constexpr float a = 500.0f;//acceleration
static constexpr float msp = 400.0f;//max speed
float velo = entity.getVelocity();
//clamp velo to [-msp,msp]
velo = std::min(msp, std::max(- msp, velo));
if(velo > 0)
entity.setVelocity(std::max(0.0f, velo - a * dt.asSeconds()));
if(velo < 0)
entity.setVelocity(std::min(0.0f, velo + a * dt.asSeconds()));
}
//...
adaptEntityVelocity(mPlayer, dt);
//...
mPlayer.move(mPlayer.getVelocity() * dt.asSeconds();
It worked just find until I use sf::RenderWindow::setFrameLimit(). It somehow makes the player moves slightly faster in 60 fps (compared to ~450 fps without setting limit) and crazily fast in 10fps. I think the problem is the time Game::update() and Game::processInput() system is also affected by setFrameLimit(). So I decided not to use setFrameLimit(), but I don’t want to let the game run as fast as possible because that hurts GPU. But if I only limit render frequency the CPU will run massively fast and consume lots of energy (same when you run an endless while() loop). Then I come up with an idea: limit Game::render() to 60 fps and game loop to 500fps. This is the code:
void Game::run()
{
sf::Clock dtClock;
sf::Time timeSinceLastFrame = sf::Time::Zero;
while(mWindow.isOpen())
{
sf::Time elapsed = dtClock.restart();
//limit loops per second;
if (elapsed < sf::seconds(0.002f))
{
sf::sleep(sf::seconds(0.002f) - elapsed);
elapsed += dtClock.restart();
}
timeSinceLastFrame += elapsed;
while(timeSinceLastFrame >= TIMEPERFRAME)
{
timeSinceLastFrame -= TIMEPERFRAME;
processInput();
update(TIMEPERFRAME);
}
updateStat(elapsed);
render(elapsed); // pass a time variable to count and set limit
}
}
Render function:
void Game::render(sf::Time dt)
{
mRenderTime += dt;
if(mRenderTime >= sf::seconds(1.0f / 60.0f))
{
mRenderCount ++;
mRenderTime -= sf::seconds(1.0f / 60.0f);
mWindow.clear(sf::Color(0x00000000ff));
mWorld.draw();
mWindow.setView(mWindow.getDefaultView());
mWindow.draw(mStatistics);
mWindow.display();
}
}
So what I want to know is would this work on any OP with various speed? Or is it just in my own laptop?
P/s: this is what I got after all: a decent render rate and a limited loops per frame