Control Frame Rates in SFML

Started by
10 comments, last by frob 9 years, 10 months ago

Hi

I'm at the beginning of learning SFML , i wrote a program to show the character moving around but it moves too fast

i want to control its speed and calculate frame rates per second but i have no idea how to do that

here is my code


#ifdef SFML_STATIC
#pragma comment(lib, "glew.lib")
#pragma comment(lib, "freetype.lib")
#pragma comment(lib, "jpeg.lib")
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "gdi32.lib")  
#endif // SFML_STATIC


#include <SFML/Graphics.hpp>
#include <iostream>
#include <string>

const int Window_Width = 800;
const int Window_Height = 600;
const std::string Window_Name = "My First SFML Game";

int main()
{
	sf::RenderWindow window(sf::VideoMode(Window_Width, Window_Height), Window_Name, sf::Style::Close);
	window.setPosition(sf::Vector2i(250, 50));  // change position of the window
	window.setKeyRepeatEnabled(false);

	enum Dirction{ Down, Left, Right, Up };
	sf::Vector2i source(1, 0);

	sf::Texture pTexture;
	sf::Sprite sPlayer;
	if (!pTexture.loadFromFile("Player.png")){
		std::cout << "Error loading the Texture" << std::endl;
		return -1;
	}

	sPlayer.setTexture(pTexture);  //Sprite
	sf::Event MyEvent;
	
	while (window.isOpen())
	{
		
		while (window.pollEvent(MyEvent))
		{
			switch (MyEvent.type)
			{
			case sf::Event::Closed:
				window.close();
				break;
			}

		}

		if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)){
			source.y = Down;
			sPlayer.move(0,1);
		}
		else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)){
			source.y = Left;
			sPlayer.move(-1, 0);
		}
		else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)){
			source.y = Right;
			sPlayer.move(1, 0);
		}
		else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)){
			source.y = Up;
			sPlayer.move(0, -1);
		}
		
		source.x++;
		if (source.x * 32 >= pTexture.getSize().x)
				source.x = 0;
		
		window.clear();
		sPlayer.setTextureRect(sf::IntRect(source.x * 32, source.y*32, 32, 32));
		window.draw(sPlayer);
		window.display();
	}
	return EXIT_SUCCESS;
}

Thanks

Advertisement

int main() {
	
	sf::Clock clock;
	float last_render = 0;

	gameIsRunning = true;
	while (gameIsRunning) {
		//**Do your simulation*/

		//Is it time to render?
		if (last_render - clock.getElapsedTime.asSeconds() > 1/60) {// 1:60 for 60 FPS
			//Update the last_render variable			
			last_render = clock.getElapsedTime.asSeconds();
			
			//**Do your rendering*/

		}
	}
}

I haven't tested my code. If someone spots any mistakes please let me know;

Give your character a speed. In other words, determine how long it should take your character to move from point 1 to point 2.

Then use sfml's getElapsedTime function to determine how much time has passed since the previous simulation step and move your character over the appropriate distance.

 


int main() {
	
	sf::Clock clock;
	float last_render = 0;

	gameIsRunning = true;
	while (gameIsRunning) {
		//**Do your simulation*/

		//Is it time to render?
		if (last_render - clock.getElapsedTime.asSeconds() > 1/60) {// 1:60 for 60 FPS
			//Update the last_render variable			
			last_render = clock.getElapsedTime.asSeconds();
			
			//**Do your rendering*/

		}
	}
}

I haven't tested my code. If someone spots any mistakes please let me know;

i don't whats the mistake but it doesn't work :/

Give your character a speed. In other words, determine how long it should take your character to move from point 1 to point 2.

Then use sfml's getElapsedTime function to determine how much time has passed since the previous simulation step and move your character over the appropriate distance.

i don't know how to detrmine the time could you please write the code :D

It's a function of sf::Clock, see dejaime's piece of code.

Something like:

newpos = oldpos + speed * clock.getElapsedTime().asMilliseconds();

Where speed is the number of positions to move per millisecond. This code doesn't take the direction into account.

 

It's a function of sf::Clock, see dejaime's piece of code.

Something like:

newpos = oldpos + speed * clock.getElapsedTime().asMilliseconds();

Where speed is the number of positions to move per millisecond. This code doesn't take the direction into account.

i didn't understand :(

but i watched CodingMadeEay tutorial and it warked but i don't know why did he put 100 to FrameSwitch and 500 for the FrameSpeed.


float FrameCounter=0, FrameSwitch=100, FrameSpeed=500;

FrameCounter += FrameSpeed * MyClock.restart().asSeconds();
if (FrameCounter >= FrameSwitch){
	FrameCounter = 0;
}

Speed is measured as distance over time, like miles/hour, or km/h. For computers, you could use pixels/second to determine how fast a character moves on the screen. Doing this provides you a very easy way of determining where a character should be placed on the screen, based on his x and y speed in pixels/second.

To determine how many pixels a object should move, you take the elapsed time in seconds since he last moved, and you multiply it by his speed.

So, if your character moves 100 pixels/second on the x-axis, and if 0.033 seconds have elapsed (30 fps), and the character is currently at x location 50, after this frame he'll be at:

50 pixels + 100 pixels/second * 0.033 seconds = 53.3 pixels

You need to keep track of the location as a float to allow for smooth movements at a high frame rate.


// deltaTime is the time in seconds since the last update
void Object::Move(float deltaTime)
{
  // move the player
  m_position.x = m_position.x + m_velocity.x * deltaTime;
  m_position.y = m_position.y + m_velocity.y * deltaTime;
}

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

Speed is measured as distance over time, like miles/hour, or km/h. For computers, you could use pixels/second to determine how fast a character moves on the screen. Doing this provides you a very easy way of determining where a character should be placed on the screen, based on his x and y speed in pixels/second.

To determine how many pixels a object should move, you take the elapsed time in seconds since he last moved, and you multiply it by his speed.

So, if your character moves 100 pixels/second on the x-axis, and if 0.033 seconds have elapsed (30 fps), and the character is currently at x location 50, after this frame he'll be at:

50 pixels + 100 pixels/second * 0.033 seconds = 53.3 pixels

You need to keep track of the location as a float to allow for smooth movements at a high frame rate.


// deltaTime is the time in seconds since the last update
void Object::Move(float deltaTime)
{
  // move the player
  m_position.x = m_position.x + m_velocity.x * deltaTime;
  m_position.y = m_position.y + m_velocity.y * deltaTime;
}

Thank you

Cap that delta before you pass it around everywhere as well. If, say, your virus checker decides to do its thing or whatever, you can suddenly be passing a massive delta around and your simulation can jump by a massive amount.

When you are comfortable with a variable timestep, it would be worth taking a look at this article. Fixed timestep, variable render is the most stable way to go. It is very hard to keep even a simple simulation predictable and stable using variable rate timestep for simulation.

Even outside of physics sims, if for example, you have a platform game, you want your character to jump to the same height each time, this is difficult if you have a variable update step.

Even outside of physics sims, if for example, you have a platform game, you want your character to jump to the same height each time, this is difficult if you have a variable update step.

It is one of several exploit areas that 'bad guys' like to try.

Shift the OS system clock forward one second when jump is pressed, suddenly you jump ten times higher than everyone else. Shift the clock while mining resources, shift the clock when a timed event is taking place, shift the clock when anything is being visibly tallied over time, shift the clock during any duration-based processing. Imagine Team Fortress if I could shift the clock forward a few seconds as the medic is charging up the heavy?

Many industries (not just games) get bit by this.

Forward-shifting is usually not too detrimental. The number of seconds is just really huge, your character jumps into the air and flies off to oblivion or the ceiling.

On the funner side, what happens when the clock moves backward? Behind your back the OS might decide it is time to sync up with the time servers and shifts the time back by a few milliseconds, a few seconds, or hours, or even days. There is no warning to the programs, just suddenly the time is radically different.

Consider something trivial in a game: MoneyEarned = MoneyPerSecond * SecondsElapsed;

Now consider that line when the OS coincidentally adjusted for daylight savings time, either forward or backward. Perhaps you are suddenly rich. Perhaps you are suddenly very poor. Or perhaps the programmers validated the time increments.

How about this one: NextEventScheduledTime = Now + RandomDelay;
Follow that by the OS shifting the clock, it is now last Thursday. The next event was supposed to happen every few seconds, it now won't trigger for several days.

Failure to consider time this way has cost a lot of businesses a lot of money. Microsoft Azure (the cloud computing infrastructure) didn't account for it and on leap day 2012 they went down, taking hundreds of enterprise customers with it. MS refunded several million dollars from that mistake. That year Linux also tripped over a leap-second issue where precision timers were basically locked on a rapid cycle trying to catch up, the kernel thought it was an infinite loop and crashed, bringing down thousands of servers around the world and making sysadmins freak out as the leap-second was processed in time zone after time zone.

Time is tricky on computers. It does not flow regularly, nor does it always move forward. Always validate it.

This topic is closed to new replies.

Advertisement