Animation Controller
Un AnimationController, est une class construite comme une state machine.
C'est une class abstraite dont vous allez devoir créer vos propres classes héritées.
Par exemple un AnimationController_Player.
Vous y établirez alors tout les AnimationState dont vous aurez besoin, et pourrez lier les état aux fonctions voulues.
Exemple d'AnimationController:
.h :
#pragma once
#include <Legacy/AnimationController.h>
using namespace lg;
class AnimationController_Player : public AnimationController
{
public:
AnimationController_Player(std::shared_ptr<Animator> _animator);
//Fonction héritée de AnimationController, obligatoire à definir car virtuelle pure à la base.
virtual void InitAnimationController() override;
//Fonctions personnelles de ce controller pour organiser sa procédure
void InitAnimationStates();
void InitAndAssigneAnimations();
//Les états
std::shared_ptr<AnimationState> idleState;
std::shared_ptr<AnimationState> walkState;
//Les fonctions liées aux phases des etats
void OnEnter_Idle();
void OnUpdate_Idle();
void OnExit_Idle();
void OnEnter_Walk();
void OnUpdate_Walk();
void OnExit_Walk();
void OnEnd_Walk();
//L'update non obligatoire, peut avoir une utilité de debug
virtual void Update() override;
//Une fonction de test lié au systeme de frame event
void TestFunction();
};
.cpp:
#include "AnimationController_Player.h"
#include <iostream>
#include <SFML/Window.hpp>
AnimationController_Player::AnimationController_Player(std::shared_ptr<Animator> _animator)
: AnimationController(_animator){}
//Fonction d'initialisation obligatoire
void AnimationController_Player::InitAnimationController()
{
//Procédure personnelle:
InitAnimationStates();
InitAndAssigneAnimations();
//Utilisation de la fonctionnalité d'ajout de state
AddStateToMachine(idleState);
AddStateToMachine(walkState);
//State de depart
SetState(idleState);
}
void AnimationController_Player::InitAnimationStates()
{
//Création des AnimationState. Une fonction static simplifiant la syntaxe
//Le nom donné est important, il sert ensuite de clef pour la map qui contient les states
idleState = AnimationState::CreateState("idle");
walkState = AnimationState::CreateState("walk");
//Assignation des fonctions
//Afin que le systeme soit generique, les AnimationState sont dotées de variables
//de type std::function<void()>.
//On peut alors assigner n'importe quelle fonction de meme signature sur ces "slot"
idleState->OnEnter = [this]() { this->OnEnter_Idle(); };
idleState->OnExit = [this]() {this->OnExit_Idle(); };
walkState->OnEnter = [this]() { this->OnEnter_Walk(); };
walkState->OnExit = [this]() {this->OnExit_Walk(); };
walkState->OnEnd = [this]() {this->OnEnd_Walk(); };
}
void AnimationController_Player::InitAndAssigneAnimations()
{
//Création des animations
auto idleAnimation = new Animation();
idleAnimation->SetLooping(true);
//Création des séquences droite et gauche de l'animation Idle
auto idleRightSequence = idleAnimation->GenerateSequence(0, 0, 48, 48, 9);
auto idleLeftSequence = idleAnimation->GenerateSequence(0, 48, 48, 48, 9);
//Assignation des séquences à leur index
idleAnimation->SetSequence(0, idleRightSequence);
idleAnimation->SetSequence(1, idleLeftSequence);
//Application de la séquence de départ
idleAnimation->SetSequenceKey(0);
idleAnimation->ActivateFirstSequence();
idleAnimation->SetAnimationFrequency(0.05f);
//Assignation de l'animation au state correspondant
idleState->SetAnimation(idleAnimation);
//Création d'une fonction de test,
//Appliquée sur la frame 5 de l'animation idle.
auto function = [this]() { TestFunction(); };
idleAnimation->SetFrameEvent(5, function);
//Meme procédure pour l'animation walk
auto walkAnimation = new Animation();
walkAnimation->SetLooping(true);
auto walkRightSequence = walkAnimation->GenerateSequence(0, 48 * 2, 48, 48, 4);
auto walkLeftSequence = walkAnimation->GenerateSequence(0, 48 * 3, 48, 48, 4);
walkAnimation->SetSequence(0, walkRightSequence);
walkAnimation->SetSequence(1, walkLeftSequence);
walkAnimation->SetSequenceKey(0);
walkAnimation->ActivateFirstSequence();
walkAnimation->SetAnimationFrequency();
walkState->SetAnimation(walkAnimation);
}
#pragma region WALK
void AnimationController_Player::OnEnter_Walk()
{
//Il est important de lancer la fonction Enter d'un state,
//car c'est elle qui se charge de reset le compteur de frame et le timer de l'animation.
walkState->Enter();
}
void AnimationController_Player::OnExit_Walk()
{
//Cet appel n'est pas important pour l'instant
walkState->Exit();
}
void AnimationController_Player::OnEnd_Walk()
{
//Cet appel a End est important car il s'assure que l'animation est stoppée.
walkState->End();
}
//Override de l'update inutile à moins de vouloir debug quelque chose.
void AnimationController_Player::Update()
{
AnimationController::Update();
}
#pragma endregion
#pragma region Idle
void AnimationController_Player::OnEnter_Idle()
{
idleState->Enter();
}
void AnimationController_Player::OnExit_Idle() {}
#pragma endregion
void AnimationController_Player::TestFunction()
{
std::cout << "test event" << std::endl;
}