This is part of an ongoing series where we write a complete 2D game engine in C++ and SFML. A new tutorial is released every Monday. You can find the complete list of tutorials here and download the source code from the projects GitHub page.
Last week I said that we would spend this week adding a method of transitioning to different animations so that when we finish shooting a projectile we can play the idle animation, however, after some consideration I’ve come up with a better solution (at least for now). We’ll still want a transition system but we also want to add a data structure to handle the transitions which is a large project that will get in the way of what we’re trying to achieve at the moment (a working projectile system). I’m going to devote more time to update the animation system in a future tutorial.
At the moment In C_ProjectileAttack::Update we check if the ‘e’ key is pressed and if it is we tell the animation system to play the projectile animation. Which mostly works but we can make a small change here which will solve our transition problem.
void C_ProjectileAttack::Update(float deltaTime)
{
if(input->IsKeyDown(Input::Key::E))
{
animation->SetAnimationState(AnimationState::Projectile);
}
else if (input->IsKeyUp(Input::Key::E))
{
animation->SetAnimationState(AnimationState::Idle);
}
}
Instead of just checking if the ‘e’ key is pressed we now perform two checks:
- When it is first pressed we start the projectile animation.
- When the key is released we transition to the idle state.
Simple but effective. If you run the game now you’ll see the effect for yourself.We now want to loop the projectile animation so that while the projectile attack button is held we play the animation. Make this change this in SceneGame.
void SceneGame::OnCreate()
{
…
/*************************
* Projectile Animations *
*************************/
const bool projectileAnimationLooped = true;
…
}
Now holding down the attack button will play the projectile animation on a loop.
Projectile Animation Looped.
With that small change, we have resolved our transition issue. Although this should only be considered a temporary solution. As the number of animations grow and the interactions between them become ever more complex we will need something more robust.You may have noticed that the player can still move while ‘shooting’ a projectile. Well, they can move while playing the projectile animation as we are yet to create the actual projectiles. For now, we want the player to be stationary while shooting, although this design decision may change as we playtest the game. To stop movement while shooting we’ll update C_KeyboardMovement by re-adding a reference to the animation component that we removed when we created the velocity component.
#include "C_Animation.hpp"
class C_KeyboardMovement : public Component
{
…
private:
…
std::shared_ptr<C_Animation> animation;
};
Then in the Update function we check if the animation state is projectile and if it is we set the players velocity to 0 to stop any existing movement and return from the function to prevent the player from moving.
void C_KeyboardMovement::Update(float deltaTime)
{
if(input == nullptr)
{
return;
}
//TODO: keyboardmovement should not interact with animation component.
if(animation->GetAnimationState() == AnimationState::Projectile)
{
velocity->Set(0.f, 0.f);
return;
}
…
}
Don’t forget to assign the animation component in the Awake function. More information on what the Awake function is and when it is called can be found here.
void C_KeyboardMovement::Awake()
{
...
animation = owner->GetComponent<C_Animation>();
}
When we create a method of inter-system communication such as an event system, we’ll once again remove the animation component from the keyboard movement as we really don’t want it there. Ideally, the movement and animation systems should be kept as separate as possible.
That’s all for this week, next week we’ll start work on actually spawning projectiles and making them collide with the environment. As always, if you have any suggestions for what you would like covered or are having any trouble implementing a feature, then let me know in the comments and I’ll get back to you as soon as I can.
Thank you for reading 🙂