Hi.
I just found out about SFML and have been developing games for a few years now. I absolutely love the API. One question however is regarding the apparent ability for SFML to handle most of the timing and updating groundwork. I am writing a simple pong clone all in one file in case I had trouble and am finding some oddities in the updating of the paddle locations. Here is the source for my main loop. I do enable vertical sync in the initialization phase.
// Start the game loop
while (window.isOpen())
{
// Restart the clock and get the delta time
time = clock.restart();
float dt = time.asSeconds();
// Poll for events
sf::Event event;
while (window.pollEvent(event))
{
// Close window : exit
if (event.type == sf::Event::Closed)
window.close();
// Escape pressed : exit
if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape)
window.close();
// Check for user input
if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Down)
player1.y += 10 * dt;
// Check for user input
if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Up)
player1.y -= 10 * dt;
}
// Update the object positions
paddle1.setPosition(player1.x, player1.y);
paddle2.setPosition(player2.x, player2.y);
// Clear screen
window.clear();
// Draw the sprites
window.draw(background);
window.draw(paddle1);
window.draw(paddle2);
window.draw(ball);
window.draw(text);
// Update the window
window.display();
}
It compiles fine but the paddle moves way too slowly. I tried multiplying the number by 1000, to where is got to a reasonable speed but it was jerky and not smooth. Has anyone dealt with this? I don't really need a super accurate fixed timestep loop. I should also add that my player1 and 2 are structs with a simple x and y float.
Thank you.
It's a perfectly normal calculation that makes your paddles move so slowly. If you got a fix framerate due to VSync (= 60fps) you'd get 0.016 for dt, thus:
10px/s * 0.016s = 0.16px
So your paddle moves 0.16px per frame, which isn't that fast.
Also I'd suggest to use the class sf::Keyboard with its function isKeyPressed() instead of working with events, because evens get triggered only so often and at the beginning there's a repeate delay.
// Check for user input
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
player1.y += 40 * dt;
// Check for user input
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
player1.y -= 40 * dt;
Also keep in mind with the current update code, your dt doesn't take in account the time spend on the event handling or the position setting. So you should put it just before the draw statements.
I changed the keyboard input method and there was no change. So it seems my main loop is being updated with a weird delta time. Any idea how to fix it to be more smooth?
I hope you only relate this to the smoothness and not to the low speed (otherwise you'd have completly ignored the first part of my previous answer...). ;)
You hopefully took it out of the event loop, right?
I've taken your code and implemented a quick test case and it works fine, no choppy movements:
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow window( sf::VideoMode( 800, 600 ), "Test" );
window.setVerticalSyncEnabled( true );
sf::Vector2f player1(10, 10);
sf::Vector2f player2(590, 10);
sf::RectangleShape paddle1(sf::Vector2f(10, 30));
sf::RectangleShape paddle2(sf::Vector2f(10, 30));
sf::Clock clock;
sf::Time time;
float dt = 0;
const int speed = 100;
// Start the game loop
while (window.isOpen())
{
// Poll for events
sf::Event event;
while (window.pollEvent(event))
{
// Close window : exit
if (event.type == sf::Event::Closed)
window.close();
// Escape pressed : exit
if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape)
window.close();
}
// Check for user input
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
player1.y += speed * dt;
// Check for user input
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
player1.y -= speed * dt;
// Restart the clock and get the delta time
time = clock.restart();
dt = time.asSeconds();
// Update the object positions
paddle1.setPosition(player1.x, player1.y);
paddle2.setPosition(player2.x, player2.y);
// Clear screen
window.clear();
// Draw the sprites
window.draw(paddle1);
window.draw(paddle2);
// Update the window
window.display();
}
return EXIT_SUCCESS;
}
Also if you think the delta time is too small, then you should either work with a fixed timestep (http://gafferongames.com/game-physics/fix-your-timestep/), or only updated it every second (or half a second).
I changed the keyboard input method and there was no change. So it seems my main loop is being updated with a weird delta time. Any idea how to fix it to be more smooth?
I hope you only relate this to the smoothness and not to the low speed (otherwise you'd have completly ignored the first part of my previous answer...). ;)
You hopefully took it out of the event loop, right?
I've taken your code and implemented a quick test case and it works fine, no choppy movements:
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow window( sf::VideoMode( 800, 600 ), "Test" );
window.setVerticalSyncEnabled( true );
sf::Vector2f player1(10, 10);
sf::Vector2f player2(590, 10);
sf::RectangleShape paddle1(sf::Vector2f(10, 30));
sf::RectangleShape paddle2(sf::Vector2f(10, 30));
sf::Clock clock;
sf::Time time;
float dt = 0;
const int speed = 100;
// Start the game loop
while (window.isOpen())
{
// Poll for events
sf::Event event;
while (window.pollEvent(event))
{
// Close window : exit
if (event.type == sf::Event::Closed)
window.close();
// Escape pressed : exit
if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape)
window.close();
}
// Check for user input
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
player1.y += speed * dt;
// Check for user input
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
player1.y -= speed * dt;
// Restart the clock and get the delta time
time = clock.restart();
dt = time.asSeconds();
// Update the object positions
paddle1.setPosition(player1.x, player1.y);
paddle2.setPosition(player2.x, player2.y);
// Clear screen
window.clear();
// Draw the sprites
window.draw(paddle1);
window.draw(paddle2);
// Update the window
window.display();
}
return EXIT_SUCCESS;
}
Also if you think the delta time is too small, then you should either work with a fixed timestep (http://gafferongames.com/game-physics/fix-your-timestep/), or only updated it every second (or half a second).
Very very bizarre. I modified your loop and it worked perfectly. Still not sure what the case was in my code. And was there really a necessity to move the delta update? Wouldn't it make sense to get the delta time before the update rather than after.
Thank you again! :D