SFML community forums
Help => Graphics => Topic started by: billboard_baggins on February 17, 2012, 11:52:26 pm
-
Not sure if this belongs here, but, here is my issue: my little animation function doesn't loop. I have a class for "asteroids" and this member function animates a spinning motion (no user input required, happens every render cycle). Here is my code ("frames" is a vector array and "frame" is an iterator):
void Asteroid::animate()
{
if ( frame == frames.end() ) frame = frames.begin();
//if frame time has elapsed, move to next frame in animation
if ( frameClock.GetElapsedTime().AsMilliseconds() >= frameTime.AsMilliseconds() )
{
mySprite.SetTextureRect(*frame); //set frame
++frame;
//reset clock
frameClock.Restart();
}
}
The code does partially work, as it loops through the 7 frames once. However, after that the asteroid simply disappears (as if the 'frame = frames.begin()' isn't working). Any help is appreciated!
-
what happens after you reach max frames?
++frame? max Is?
-
try to use front() instead of begin()
-
When it reaches max frames (there are 7 "frames" or sf::IntRects inside the "frames" vector) it is supposed to return to the first spot in the vector so the animation loops.
I tried setting frame = frames.front() but it spit out an error saying it wasn't a valid candidate.
-
use frames[ index ] ?
-
Using frames[index] gives me the same error. Logically the code makes sense to me so I'm really confused why it isn't working (unless my understanding of vector iterators is wrong...)
-
vector::end
"Returns an iterator referring to the past-the-end element in the vector container."
http://www.cplusplus.com/reference/stl/vector/end/
It seems end() is not really the last element. Try something like end() -1 ...
-
I just tried some variations of that but no luck. I also tried setting it to begin()+1 just to see if that made a difference, but it didn't. I'm convinced it has to do with the resetting of the iterator since it runs through the animation once perfectly fine.
-
if ( frame == frames.end() ) frame = frames.begin();
should be correct. Try to find out with the debugger why this if statement is not executed. Hint: frame - frames.begin() returns the iterator offset.
By the way,
frameClock.GetElapsedTime().AsMilliseconds() >= frameTime.AsMilliseconds()
can be replaced with
frameClock.GetElapsedTime() >= frameTime
-
Where is frameTime changed? I'm assuming this relates to the iterator frame? Is it updated when the frame iterator is incremented?
-
frameTime never changes, it just represents when to update the frame (in milliseconds). It is set when an asteroid object is instantiated.
Nexus, I will try the debugger and let you know. Also, thanks for the tip, I tend to write out more code than needed.
-
Based on the information I have I wrote a small test project.
It uses the function that you provided and it proves that there is nothing wrong with the frames, the code below works like it should.
The problem lies with your frameTime (which I didn't use) or somewhere else in your project.
struct Asteroid
{
void animate()
{
if ( frame == frames.end() )
frame = frames.begin();
mySprite.SetTextureRect(*frame);
++frame;
}
}
sf::Sprite mySprite;
std::vector<sf::IntRect> frames;
std::vector<sf::IntRect>::iterator frame;
};
int main()
{
Asteroid test;
test.frames.push_back(sf::IntRect(0, 0, 100, 100));
test.frames.push_back(sf::IntRect(0, 0, 200, 200));
test.frames.push_back(sf::IntRect(0, 0, 300, 300));
test.frames.push_back(sf::IntRect(0, 0, 400, 400));
test.frame = test.frames.begin();
while (true)
{
test.animate();
sf::Sleep(sf::Milliseconds(100));
}
}