I currently follow the SFML Game Development example for checking the time frame update between the previous and the current frame, for frame per second in my main loop.
However, I want to set the limit to 60FPS, as in the moment it going to 1000s. I am setting the limit right after creating the window as written in the documentation, however I'm getting a jittery effect on my spaceships.
This is my current code. What would be the best practice to use setFramerateLimit with main loop calculations to update on each frame? (render, movement,input etc)
int main()
{
sf::Texture mPlayerTexture;
sf::Sprite mPlayer;
sf::Texture mBackgroundTexture;
sf::Sprite mBackground;
sf::RenderWindow window(sf::VideoMode(game->getWindowWidth(), game->getWindowHeight()), "SFML Application");
//static const sf::Time TimePerFrame;
window.setFramerateLimit(60);
if (!mPlayerTexture.loadFromFile("Media/Textures/PixelSpaceships/blue_01.png"))
{
// Handle loading error
}
if (!mBackgroundTexture.loadFromFile("Media/Textures/Space.jpg")) {
// Handle loading error
}
mBackground.setTexture(mBackgroundTexture);
mBackground.setOrigin(game->getWindowWidth() / 2.f, game->getWindowHeight() / 2.f);
mBackground.setPosition(game->getWindowWidth() / 2.f, game->getWindowHeight() / 2.f);
// Set Texture and Position
mPlayer.setTexture(mPlayerTexture);
mPlayer.setOrigin(24.f, 24.f);
mPlayer.setPosition(game->getWindowWidth() / 2.f, game->getWindowHeight() / 2.f);
//enemy.enemyInstantiator(2, 100.f, 50.f);
//enemyInstantiator(10, 100.f, 150.f);
// Statistics Initialisation
sf::Font mFont;
sf::Text mStatisticsText;
mFont.loadFromFile("Media/Sansation.ttf");
mStatisticsText.setFont(mFont);
mStatisticsText.setPosition(5.f, 5.f);
mStatisticsText.setCharacterSize(10);
// Enemy Creation // Separate method in main
std::vector<Enemy> *enemyList = new std::vector<Enemy>();
float xPosition = 100.f;
float yPosition = 50.f;
float yOffset = 50.f;
float xOffset = 60.f;
for (int i = 0; i < NUMBER_OF_ALIENS; i++) {
Enemy alien(i, enemySpeed);
alien.getSprite().setOrigin(24.f, 24.f);
alien.setLocation(xPosition + (i * xOffset), yPosition);
alien.getSprite().setRotation(180.f);
enemyList->push_back(alien);
//std::cout << "I have " << enemyList->size() << " spaceships" << std::endl;
}
//std::cout << "I have " << enemyList->size() << " spaceships";
/*
//create a an array of enemys
Enemy alienArray = new Enemy[];
for (int i = 0; i < NUMBER_OF_ALIENS; i++)
{
Enemy alien(i, enemySpeed);
alien.setLocation(i * 50.f + 50.f, alien.getSprite().getGlobalBounds().height / 2);
alienArray;
}
*/
//game->run();
// Measure elapsed time
sf::Clock clock;
sf::Time timeSinceLastUpdate = sf::Time::Zero;
while (window.isOpen())
{
// Puts the time counter back to zero and also returns the time elapsed since the clock was started
sf::Time deltaTime = clock.restart();
timeSinceLastUpdate += deltaTime;
while (timeSinceLastUpdate > TimePerFrame) // fixed time steps
{
timeSinceLastUpdate -= TimePerFrame; // solves problem with variable delta time, each frame is unique
processEvents(window);
//update(TimePerFrame);
// Player 1 movement
sf::Vector2f movement(0.f, 0.f);
if (mIsMovingUp)
movement.y -= playerSpeed;
if (mIsMovingDown)
movement.y += playerSpeed;
if (mIsMovingLeft)
movement.x -= playerSpeed;
if (mIsMovingRight)
movement.x += playerSpeed;
// shooting logic
// Possibly this will be the data that needs to be sent to server
mPlayer.move(movement * TimePerFrame.asSeconds()); // Time.deltaTime frame independent movement
// for each player eventually
screenBound(mPlayer);
// screenbound enemies or else check that they do not go off bounds and change direction
// Enemy Behaviour // Move to separate method
sf::Vector2f enemyMovement(1.f, 0.f);
float yOffset = 50.f;
float xOffset = 60.f;
// Be careful with iterators as when deleting it will automatically jump to the next item in vector
for (std::vector<Enemy>::iterator i = enemyList->begin(); i != enemyList->end(); ++i) // CAUTION & solved everything again - lesson in C++, if we don't get address, we always create a copy and modify it, which is not what we want
{
std::cout << "Direction before working move " << direction << std::endl;
i->getSprite().move(enemyMovement * direction); // Issue detected direction only changing sign if greater or less than screen bounds once
if (i->getSprite().getPosition().x + i->getSprite().getLocalBounds().width / 2 > game->getWindowWidth() ||
i->getSprite().getPosition().x - i->getSprite().getLocalBounds().width / 2 < game->getWindowWidth() - game->getWindowWidth()) { // this will be 0
direction = -(direction);
std::cout << "Direction inside if statement " << direction << std::endl;
// another for loop move all down by yOffset
for (std::vector<Enemy>::iterator i = enemyList->begin(); i != enemyList->end(); ++i) {
i->getSprite().setPosition(i->getSprite().getPosition().x, i->getSprite().getPosition().y + yOffset);
//enemy.move(0.f, enemy.getPosition().y + yOffset);
}
//enemy.setPosition(enemy.getPosition().x, enemy.getPosition().y + yOffset); // y axis is inverted in SFML
//return 0; // move to separate method
}
if (i->getSprite().getPosition().y > game->getWindowHeight() - mPlayer.getLocalBounds().height) {
//removeEnemy(enemy);
// ALIVE is false, then draw based on whether alien is alive or not
std::cout << "Everyone should be dead game over!" << std::endl;
return 0; // change state to paused
}
}
}
updateStatistics(deltaTime, mStatisticsText);
// Render All
// Remember draw order is important
window.clear();
window.draw(mBackground);
window.draw(mPlayer);
window.draw(mStatisticsText);
for (std::vector<Enemy>::iterator i = enemyList->begin(); i != enemyList->end(); ++i) {
if (i->isAlive()) {
i->draw(window);
std::cout << "Enemy " << i->getID() << " position - " << i->getLocation().x << " " << i->getLocation().y << std::endl;
}
}
//for (Enemy& enemy : enemyList) {
// if (enemy.isAlive()) {
// enemy.draw(window);
// }
//}
//enemy.render(alienArray, mWindow);
/*
for (int i = 0; i < mEnemies.size(); i++)
{
sf::Sprite temp = mEnemies.at(i);
mWindow.draw(temp);
}
*/
window.display();
}
return 0;
}