-
Howdy, I'm trying to make a sprite animate with the Thor library when I press a key and stop animating when I release it.
This is pretty easy with event polling. I just did this:
while(mainWindow.PollEvent(Event))
{
...
if((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Keyboard::Right))
animator.PlayAnimation("walk", true);
if((Event.Type == sf::Event::KeyReleased) && (Event.Key.Code == sf::Keyboard::Right))
animator.StopAnimation();
if((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Keyboard::Left))
animator.PlayAnimation("walk", true);
if((Event.Type == sf::Event::KeyReleased) && (Event.Key.Code == sf::Keyboard::Left))
animator.StopAnimation();
}
//and a thing down here that stops the animation if both keys are pressed at the same time
Unfortunately, this gets totally messed up if you happen to press both left and right at the same time, and then release one of those while still holding the other. Since no new key pressed event was fired there, the sprite will be unanimated even though a key is down (therefore my sprite is sliding along without being animated).
The alternative to polling is the real-time input or w/e, but since that calls every frame, it'll screw up animator.PlayAnimation by calling it over and over while the key is pressed and restarting the animation before it even has time to reach its second frame.
I know I can do some fancy boolean state stuff to fix this (e.g. have some bool called isWalking or something, and do some things with it to circumvent a continuously restarting PlayAnimation call), but I can't logic it out myself. :(
Can you help a brother out?
-
I suggest to use the newest Thor version (the one from GitHub), it should be in sync with the latest SFML revision.
Using the Thor 2 development version, you can use real-time input. With thor::Animator::isPlayingAnimation(), you can check if an animation is playing, and not restart it in this case.
-
Oh, that sounds handy. Thank you!
It may still be good if somebody were to explain the original way I asked for as well, though.
-
I've never actually used CMake before but I've just learned how to make and compile the newest revisions of SFML and Thor. I got SFML alright, but when I try to compile Thor's makefile I am getting some errors. I'm not really sure if it's my fault or perhaps a bug somewhere, but I am stuck now nonetheless. Here's a screenshot:
(http://i.imgur.com/m0tj5K2.png)
(Sorry for kind of off-topic double post)
-
Taking a blind shot at this, but do you have the C++11 flag on?
-
Thor's CMake configuration should automatically enable -std=c++0x, you only have to take care of it when you build your own projects (but not Thor itself).
It looks like your compiler is outdated. If I remember correctly, g++ before 4.6 does not support the nullptr keyword.
-
I updated MinGW, and now I finally have the newest Thor and SFML working in my project. :)
It should not be too hard to do what I wanted to do with the animations now, but I will post in this thread again if I really can't figure it out.
By the way, is there no longer a specific default animation for Thor's animator class that plays when stopAnimation is called?
edit: Oh, that last thing I wrote is actually breaking the idea I had on how to make this work...
I replaced the default animation with just another animation called "idle", but since idle is playing when the walk animation is not, there is technically always an animation playing and isPlayingAnimation() isn't helpful to me anymore. D:
-
Ah, I see. I removed the default animation, because it was confusing and one could also play an animation oneself if no other is playing.
Something that's already planned is a function like getPlayingAnimation() that returns the ID of the current animation. I wasn't sure about how to design the API (what to return if none is playing), maybe something like bool Animator::getPlayingAnimation(Identifier& id) const
Until I implement it, you can use a bool flag that states if the idle animation is playing.
-
Big bump, I haven't been messing in SFML since I originally posted this thread but came back and tried the booleans just today. No reason to make a new thread.
I happen to be very bad at logicking out where to put booleans, so can somebody help me out?
I made a bool called "isIdle" that is initiated at the start of the program as true. I just need to know what exactly I do with it where I'm handling the animation.
if(isRightPressed == true || isLeftPressed == true)
{
animator.playAnimation("walk", true);
}
if(isRightPressed == false && isLeftPressed == false)
{
animator.playAnimation("idle", true);
}
I need it to be arranged so that playAnimation only gets called a single time for either of these (it calls every frame like this, resetting the animation to frame 1 as soon as the game loop cycles again), but I cannot for the life of me figure out what to do with the bool. I'm really sorry if it seems like I'm asking for you guys to write my program for me or something, but I've been sitting here trying to figure it out for a good while now and know it won't hit me anytime soon. :(
-
First, you don't need to explicitly compare to true or false, since your expressions are already of type bool. So write
if (isRightPressed || isLeftPressed)
...
if (!isRightPressed && !isLeftPressed)
...
Second, use events rather than real-time states (like isPressed). With the bools, I only meant you should use a variable to replace the former return value of isPlayingAnimation() in the presence of a default animation.
bool isIdle = true;
// event loop
case sf::Event::MouseButtonPressed:
animator.playAnimation("walk", true);
isIdle = false;
break;
case sf::Event::MouseButtonReleased:
animator.playAnimation("idle", true);
isIdle = true;
break;
But as mentioned, I'll definitely work on the thor::Animator API to make such tasks even easier.
-
Events are what I attempted to use in the original post, no?
Howdy, I'm trying to make a sprite animate with the Thor library when I press a key and stop animating when I release it.
This is pretty easy with event polling. I just did this:
while(mainWindow.PollEvent(Event))
{
...
if((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Keyboard::Right))
animator.PlayAnimation("walk", true);
if((Event.Type == sf::Event::KeyReleased) && (Event.Key.Code == sf::Keyboard::Right))
animator.StopAnimation();
if((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Keyboard::Left))
animator.PlayAnimation("walk", true);
if((Event.Type == sf::Event::KeyReleased) && (Event.Key.Code == sf::Keyboard::Left))
animator.StopAnimation();
}
//and a thing down here that stops the animation if both keys are pressed at the same time
Unfortunately, this gets totally messed up if you happen to press both left and right at the same time, and then release one of those while still holding the other. Since no new key pressed event was fired there, the sprite will be unanimated even though a key is down (therefore my sprite is sliding along without being animated).
I tried using real-time input as a solution to that, but it ended up becoming sort of the opposite problem by making the animation play too much. I thought there was a way to use a bool to correct the problem I am having with the real-time input without using event polling. Is there?
Also that comparison tip is handy, thanks.
-
The workaround would have become so ugly, I could no longer stand this :D
Therefore, I implemented Animator::getPlayingAnimation() which returns the ID of the currently playing animation. You may only call this function if you are sure an animation is playing, otherwise the behavior is undefined.
Now it should be simpler with real-time input. You can check if the walk animation is already playing, and not play it again in this case. Note that getPlayingAnimation() is only called if isPlayingAnimation() returns true.
if (!animator.isPlayingAnimation() || animator.getPlayingAnimation() != "walk")
animator.playAnimation("walk");
If you need this code in multiple places, I suggest you outsource it into a function.
-
Thank you so much for doing that for me! <3
My animation looks messed up, but I did some tests where I made it play when I just pressed "P" and it's no better, so I think I'm looping through the frames wrong or something. It's strange because I could've swore that when I made my original post and did the same test, it looped correctly. However, I also remember from the time of my original post doing that test would have the frames reset like what I've been trying to fix when I held down "P", and now if I include a check with getPlayingAnimation it doesn't appear to reset. The problem looks unrelated.
(If any of that even made sense)
I'll post again if I can't fix it.
-
I should have implemented this function anyway, so this problem was a good opportunity :)
If it helps, you can also have a look at the Animation example in the Thor SDK. It works differently, but might be a good base to see how to use the thor::Animator and thor::FrameAnimation classes.
-
Oh! He was totally animating correctly, I was just playing it too fast. It works!
Thank you so much for all of your help, it's really satisfying to have a character move around animated on the screen after so much time.