feat(animation): 添加动画状态回调支持
refactor(character): 重构角色动作处理逻辑 feat(swordman): 实现剑士基础攻击和技能1处理 refactor(state): 优化状态机与动作上下文管理 feat(input): 改进输入系统支持动作请求队列 refactor(movement): 重构移动系统支持行走/奔跑模式
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
#include "character/CharacterAnimation.h"
|
||||
#include "character/CharacterObject.h"
|
||||
#include <SDL2/SDL.h>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
|
||||
namespace frostbite2D {
|
||||
namespace {
|
||||
@@ -38,6 +40,8 @@ bool CharacterAnimation::Init(CharacterObject* parent,
|
||||
actionAnimations_.clear();
|
||||
currentActionTag_.clear();
|
||||
direction_ = 1;
|
||||
actionFrameFlagCallback_ = nullptr;
|
||||
actionEndCallback_ = nullptr;
|
||||
|
||||
for (const auto& [actionName, actionPath] : config.animationPath) {
|
||||
for (const char* slotName : kAvatarParts) {
|
||||
@@ -142,6 +146,56 @@ std::string CharacterAnimation::DescribeAvailableActions() const {
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
Animation* CharacterAnimation::GetPrimaryAnimation(const std::string& actionName) const {
|
||||
auto it = actionAnimations_.find(actionName);
|
||||
if (it == actionAnimations_.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (const auto& animation : it->second) {
|
||||
if (animation && animation->IsUsable()) {
|
||||
return animation.Get();
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& animation : it->second) {
|
||||
if (animation) {
|
||||
return animation.Get();
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Animation* CharacterAnimation::GetCurrentPrimaryAnimation() const {
|
||||
if (currentActionTag_.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
return GetPrimaryAnimation(currentActionTag_);
|
||||
}
|
||||
|
||||
void CharacterAnimation::RefreshRuntimeCallbacks() {
|
||||
auto currentIt = actionAnimations_.find(currentActionTag_);
|
||||
if (currentIt == actionAnimations_.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Animation* primaryAnimation = GetPrimaryAnimation(currentActionTag_);
|
||||
for (auto& animation : currentIt->second) {
|
||||
if (!animation) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (animation.Get() == primaryAnimation) {
|
||||
animation->changeFrameCallback_ = actionFrameFlagCallback_;
|
||||
animation->endCallback_ = actionEndCallback_;
|
||||
} else {
|
||||
animation->changeFrameCallback_ = nullptr;
|
||||
animation->endCallback_ = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CharacterAnimation::SetAction(const std::string& actionName) {
|
||||
auto nextIt = actionAnimations_.find(actionName);
|
||||
if (nextIt == actionAnimations_.end()) {
|
||||
@@ -172,6 +226,7 @@ bool CharacterAnimation::SetAction(const std::string& actionName) {
|
||||
animation->SetVisible(true);
|
||||
}
|
||||
currentActionTag_ = actionName;
|
||||
RefreshRuntimeCallbacks();
|
||||
SetDirection(direction_);
|
||||
return true;
|
||||
}
|
||||
@@ -191,4 +246,51 @@ void CharacterAnimation::SetDirection(int direction) {
|
||||
}
|
||||
}
|
||||
|
||||
bool CharacterAnimation::IsCurrentActionFinished() const {
|
||||
const Animation* primaryAnimation = GetCurrentPrimaryAnimation();
|
||||
if (!primaryAnimation) {
|
||||
return false;
|
||||
}
|
||||
return !primaryAnimation->IsUsable();
|
||||
}
|
||||
|
||||
int CharacterAnimation::GetCurrentFrameIndex() const {
|
||||
const Animation* primaryAnimation = GetCurrentPrimaryAnimation();
|
||||
return primaryAnimation ? primaryAnimation->GetCurrentFrameIndex() : 0;
|
||||
}
|
||||
|
||||
int CharacterAnimation::GetCurrentFrameCount() const {
|
||||
const Animation* primaryAnimation = GetCurrentPrimaryAnimation();
|
||||
return primaryAnimation ? primaryAnimation->GetTotalFrameCount() : 0;
|
||||
}
|
||||
|
||||
float CharacterAnimation::GetCurrentNormalizedProgress() const {
|
||||
int totalFrames = GetCurrentFrameCount();
|
||||
if (totalFrames <= 1) {
|
||||
return IsCurrentActionFinished() ? 1.0f : 0.0f;
|
||||
}
|
||||
|
||||
float progress = static_cast<float>(GetCurrentFrameIndex())
|
||||
/ static_cast<float>(totalFrames - 1);
|
||||
return std::clamp(progress, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
animation::AniFrame CharacterAnimation::GetCurrentFrameInfo() const {
|
||||
const Animation* primaryAnimation = GetCurrentPrimaryAnimation();
|
||||
if (!primaryAnimation) {
|
||||
return animation::AniFrame();
|
||||
}
|
||||
return primaryAnimation->GetCurrentFrameInfo();
|
||||
}
|
||||
|
||||
void CharacterAnimation::SetActionFrameFlagCallback(ActionFrameFlagCallback callback) {
|
||||
actionFrameFlagCallback_ = std::move(callback);
|
||||
RefreshRuntimeCallbacks();
|
||||
}
|
||||
|
||||
void CharacterAnimation::SetActionEndCallback(ActionEndCallback callback) {
|
||||
actionEndCallback_ = std::move(callback);
|
||||
RefreshRuntimeCallbacks();
|
||||
}
|
||||
|
||||
} // namespace frostbite2D
|
||||
|
||||
Reference in New Issue
Block a user