I'm using SFML with C++ to try and move a sprite with a certain texture applied, but it isn't moving as I want it to.
I'm new to SFML, I read the tutorials about movement on the sfml website, and I watched a number of tutorials on Youtube about this. The stuff I saw is either very basic, or complicated enough at the moment (mostly game development stuff)
#include <SFML/Graphics.hpp>
#include <thread>
#include <chrono>
#include<iostream>
using namespace sf;
using namespace std;
int main()
{
sf::RenderWindow window(sf::VideoMode(600, 600), "test!");
Texture t;
t.loadFromFile("/*texture directory*/");
Sprite s(t);
s.setScale(Vector2f(0.25f, 0.25f));
float temp = 0;
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
window.clear(Color::White);
window.draw(s);
window.display();
s.move(Vector2f(temp, temp));
for (int i = 0; i < 3; i++) {
if (i == 0) {
this_thread::sleep_for(chrono::milliseconds(1000));
temp = 10;
}
else if (i == 1) {
this_thread::sleep_for(chrono::milliseconds(1000));
temp = 20;
}
else {
this_thread::sleep_for(chrono::milliseconds(1000));
temp = -10;
}
}
}
return 0;
}
I'm expecting the sprite to move to (10,10), then after a second, (20,20), then after a second, move back to (10,10). Instead, the sprite is moving only (-10,-10) every three seconds, so it's only taking the value of temp at the end of the loop. Same thing goes for setPosition as well.
There's something very basic at work here, but researching lead me to even more questions than answers, and that's why I've come here.
The outermost while
loop manages drawing. You have put another for
loop inside it. The inner loop has to finish before the outer can continue in its iteration, i.e. drawing another frame. The execution does not happen asynchronously, therefore your for
loop with std::this_thread::sleep_for
calls blocks the render loop for 3 seconds total. It makes it changes to temp
, which is unconditionally -10
at the end.
What you want to do instead, is create state that persists through the render loop and make a little state machine. This state will be your i
. Declare and initialize it near temp
(well, you could use temp
as well in your if
statements) and remove the for
loop. Do not forget to set i
back to 0
when you're setting temp
to -10
, if you wish to continue the animation.
Another, possible but inferior approach is to:
temp
, but remember to update s
beforehand.Lastly, I believe sf::Sprite
has member functions for accessing the state, not only modifications, so you should be able to work just with s
, not needing temp
. Keep it simple and think in terms of control flow.