feat(场景管理): 添加UIScene支持并重构场景管理器

refactor(渲染器): 优化相机切换时的渲染批处理

feat(调试工具): 新增游戏调试UI场景和九宫格面板组件

fix(动画系统): 跳过缺失的动画资源加载并记录日志

perf(资源加载): 使用BinaryFileStreamReader优化NPK文件解析

feat(地图系统): 支持多边形可行走区域调试显示

style(代码格式): 清理多余空格和统一文件编码

docs(注释): 补充关键类和方法的文档说明

test(启动跟踪): 添加启动过程性能跟踪工具

chore(依赖): 添加SDL2_ttf库支持
This commit is contained in:
2026-04-06 01:18:21 +08:00
parent 6cd1b42fef
commit bcc285eed6
36 changed files with 2675 additions and 513 deletions

View File

@@ -1,5 +1,6 @@
#include "character/CharacterAnimation.h"
#include "character/CharacterObject.h"
#include <frostbite2D/resource/pvf_archive.h>
#include <SDL2/SDL.h>
#include <algorithm>
#include <array>
@@ -38,6 +39,8 @@ bool CharacterAnimation::Init(CharacterObject* parent,
const CharacterEquipmentManager& equipmentManager) {
parent_ = parent;
actionAnimations_.clear();
missingAnimationPaths_.clear();
skippedMissingAnimationCount_ = 0;
currentActionTag_.clear();
direction_ = 1;
actionFrameFlagCallback_ = nullptr;
@@ -56,6 +59,12 @@ bool CharacterAnimation::Init(CharacterObject* parent,
return false;
}
if (skippedMissingAnimationCount_ > 0) {
SDL_Log("CharacterAnimation: skipped %zu missing animation loads across %zu unique paths for job %d",
skippedMissingAnimationCount_, missingAnimationPaths_.size(),
config.jobId);
}
return true;
}
@@ -77,6 +86,10 @@ void CharacterAnimation::CreateAnimationBySlot(
const character::CharacterConfig& config,
const CharacterEquipmentManager& equipmentManager) {
if (slotName == std::string("skin_avatar")) {
if (shouldSkipMissingAnimation(actionPath)) {
return;
}
Animation::ReplaceData replaceData(0, 0);
if (const auto* equip = equipmentManager.GetEquip(slotName)) {
auto it = equip->jobAnimations.find(config.jobId);
@@ -114,6 +127,10 @@ void CharacterAnimation::CreateAnimationBySlot(
}
std::string aniPath = equipDir + "/" + variation.animationGroup + actionPathTail;
if (shouldSkipMissingAnimation(aniPath)) {
continue;
}
auto animation = MakePtr<Animation>(
aniPath, FormatImgPath,
Animation::ReplaceData(variation.imgFormat[0], variation.imgFormat[1]));
@@ -128,6 +145,23 @@ void CharacterAnimation::CreateAnimationBySlot(
}
}
bool CharacterAnimation::shouldSkipMissingAnimation(const std::string& aniPath) {
PvfArchive& pvf = PvfArchive::get();
std::string normalizedPath = pvf.normalizePath(aniPath);
if (missingAnimationPaths_.find(normalizedPath) != missingAnimationPaths_.end()) {
++skippedMissingAnimationCount_;
return true;
}
if (pvf.hasFile(normalizedPath)) {
return false;
}
missingAnimationPaths_.insert(std::move(normalizedPath));
++skippedMissingAnimationCount_;
return true;
}
std::string CharacterAnimation::DescribeAvailableActions() const {
if (actionAnimations_.empty()) {
return "<none>";