新增 CharacterShadowActor 类用于处理角色阴影的渲染 在 CharacterObject 中实现阴影的同步和渲染逻辑 移除 GameDebugActor 中不再使用的合成纹理预览代码 添加 EnsureCompositeTextureReady 方法确保纹理准备就绪
226 lines
6.1 KiB
C++
226 lines
6.1 KiB
C++
#include "common/debug/GameDebugActor.h"
|
|
#include "character/CharacterObject.h"
|
|
#include "map/GameMap.h"
|
|
#include "ui/NineSliceActor.h"
|
|
#include <SDL2/SDL.h>
|
|
#include <algorithm>
|
|
#include <frostbite2D/2d/text_sprite.h>
|
|
#include <frostbite2D/scene/scene.h>
|
|
#include <limits>
|
|
|
|
namespace frostbite2D {
|
|
|
|
namespace {
|
|
|
|
constexpr float kDebugHudMarginX = 12.0f;
|
|
constexpr float kDebugHudMarginY = 12.0f;
|
|
constexpr float kDebugHudPaddingX = 8.0f;
|
|
constexpr float kDebugHudPaddingY = 6.0f;
|
|
constexpr float kDebugHudLineGap = 4.0f;
|
|
constexpr char kDebugHudPopupImg[] = "sprite/interface/newstyle/windows/popup/popup.img";
|
|
|
|
void ConfigureTextLine(RefPtr<TextSprite> textSprite, const char* name,
|
|
int zOrder) {
|
|
if (!textSprite) {
|
|
return;
|
|
}
|
|
textSprite->SetName(name);
|
|
textSprite->SetFont("default");
|
|
textSprite->SetTextColor(1.0f, 1.0f, 1.0f, 1.0f);
|
|
textSprite->SetZOrder(zOrder);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
GameDebugActor::GameDebugActor() {
|
|
SetName("GameDebugActor");
|
|
SetZOrder(std::numeric_limits<int>::max());
|
|
initOverlay();
|
|
}
|
|
|
|
GameDebugActor& GameDebugActor::get() {
|
|
return *getPtr();
|
|
}
|
|
|
|
Ptr<GameDebugActor> GameDebugActor::getPtr() {
|
|
static Ptr<GameDebugActor> instance(new GameDebugActor());
|
|
return instance;
|
|
}
|
|
|
|
bool GameDebugActor::AttachToScene(Scene* scene) {
|
|
return AttachToParent(scene);
|
|
}
|
|
|
|
bool GameDebugActor::AttachToParent(Actor* parent) {
|
|
if (!parent || parent == this) {
|
|
return false;
|
|
}
|
|
|
|
Ptr<GameDebugActor> self = getPtr();
|
|
if (GetParent() == parent) {
|
|
return true;
|
|
}
|
|
|
|
if (GetParent()) {
|
|
GetParent()->RemoveChild(self);
|
|
}
|
|
|
|
parent->AddChild(self);
|
|
return GetParent() == parent;
|
|
}
|
|
|
|
void GameDebugActor::DetachFromParent() {
|
|
Ptr<GameDebugActor> self = getPtr();
|
|
if (GetParent()) {
|
|
GetParent()->RemoveChild(self);
|
|
}
|
|
}
|
|
|
|
void GameDebugActor::SetDebugMap(GameMap* map) {
|
|
if (debugMap_ && debugMap_ != map) {
|
|
debugMap_->SetDebugHighlightedMoveAreaIndex(GameMap::kInvalidMoveAreaIndex);
|
|
}
|
|
debugMap_ = map;
|
|
updateOverlay();
|
|
}
|
|
|
|
void GameDebugActor::SetTrackedCharacter(CharacterObject* character) {
|
|
trackedCharacter_ = character;
|
|
updateOverlay();
|
|
}
|
|
|
|
void GameDebugActor::ClearDebugContext() {
|
|
if (debugMap_) {
|
|
debugMap_->SetDebugHighlightedMoveAreaIndex(GameMap::kInvalidMoveAreaIndex);
|
|
}
|
|
debugMap_ = nullptr;
|
|
trackedCharacter_ = nullptr;
|
|
setOverlayVisible(false);
|
|
}
|
|
|
|
void GameDebugActor::OnUpdate(float deltaTime) {
|
|
(void)deltaTime;
|
|
updateOverlay();
|
|
}
|
|
|
|
void GameDebugActor::initOverlay() {
|
|
if (background_ || coordText_ || actionText_) {
|
|
return;
|
|
}
|
|
|
|
background_ = NineSliceActor::createFromNpk(kDebugHudPopupImg, 0);
|
|
if (background_) {
|
|
background_->SetName("debugHudBackground");
|
|
AddChild(background_);
|
|
} else {
|
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
|
"GameDebugActor: failed to load HUD background from %s",
|
|
kDebugHudPopupImg);
|
|
}
|
|
|
|
coordText_ = TextSprite::create();
|
|
ConfigureTextLine(coordText_, "debugCoordText", 1);
|
|
AddChild(coordText_);
|
|
|
|
actionText_ = TextSprite::create();
|
|
ConfigureTextLine(actionText_, "debugActionText", 1);
|
|
AddChild(actionText_);
|
|
|
|
setOverlayVisible(false);
|
|
}
|
|
|
|
void GameDebugActor::updateOverlay() {
|
|
if (!coordText_ || !actionText_) {
|
|
setOverlayVisible(false);
|
|
return;
|
|
}
|
|
|
|
updateMapDebugHighlight();
|
|
if (!trackedCharacter_) {
|
|
setOverlayVisible(false);
|
|
return;
|
|
}
|
|
|
|
const CharacterWorldPosition& worldPosition = trackedCharacter_->GetWorldPosition();
|
|
|
|
char coordTextBuffer[96];
|
|
SDL_snprintf(coordTextBuffer, sizeof(coordTextBuffer), "角色坐标: (%d, %d, %d)",
|
|
worldPosition.x, worldPosition.y, worldPosition.z);
|
|
coordText_->SetText(coordTextBuffer);
|
|
|
|
int frameCount = std::max(trackedCharacter_->GetCurrentAnimationFrameCount(), 1);
|
|
int frameIndex = std::clamp(trackedCharacter_->GetCurrentAnimationFrameIndex(), 0,
|
|
frameCount - 1);
|
|
char actionTextBuffer[128];
|
|
SDL_snprintf(actionTextBuffer, sizeof(actionTextBuffer),
|
|
"Action: %s dir:%c frame:%d/%d",
|
|
trackedCharacter_->GetCurrentAction().empty()
|
|
? "<none>"
|
|
: trackedCharacter_->GetCurrentAction().c_str(),
|
|
trackedCharacter_->GetDirection() >= 0 ? 'R' : 'L', frameIndex + 1,
|
|
frameCount);
|
|
actionText_->SetText(actionTextBuffer);
|
|
|
|
Vec2 coordTextSize = coordText_->GetTextSize();
|
|
Vec2 actionTextSize = actionText_->GetTextSize();
|
|
float panelWidth = std::max(coordTextSize.x, actionTextSize.x) + kDebugHudPaddingX * 2.0f;
|
|
|
|
float contentHeight = coordTextSize.y;
|
|
if (actionText_->IsVisible()) {
|
|
contentHeight += kDebugHudLineGap + actionTextSize.y;
|
|
}
|
|
|
|
float panelHeight = contentHeight + kDebugHudPaddingY * 2.0f;
|
|
Vec2 panelSize(panelWidth, panelHeight);
|
|
if (background_) {
|
|
background_->SetSize(panelSize);
|
|
}
|
|
|
|
SetPosition(kDebugHudMarginX, kDebugHudMarginY);
|
|
SetScale(1.0f);
|
|
|
|
float currentY = kDebugHudPaddingY;
|
|
coordText_->SetPosition(kDebugHudPaddingX, currentY);
|
|
currentY += coordTextSize.y;
|
|
|
|
if (actionText_->IsVisible()) {
|
|
currentY += kDebugHudLineGap;
|
|
actionText_->SetPosition(kDebugHudPaddingX, currentY);
|
|
currentY += actionTextSize.y;
|
|
}
|
|
|
|
setOverlayVisible(true);
|
|
}
|
|
|
|
void GameDebugActor::updateMapDebugHighlight() {
|
|
if (!debugMap_) {
|
|
return;
|
|
}
|
|
|
|
if (!trackedCharacter_ || !debugMap_->IsDebugModeEnabled()) {
|
|
debugMap_->SetDebugHighlightedMoveAreaIndex(GameMap::kInvalidMoveAreaIndex);
|
|
return;
|
|
}
|
|
|
|
const CharacterWorldPosition& worldPosition = trackedCharacter_->GetWorldPosition();
|
|
Vec3 currentWorldPos(static_cast<float>(worldPosition.x),
|
|
static_cast<float>(worldPosition.y),
|
|
static_cast<float>(worldPosition.z));
|
|
size_t moveAreaIndex = debugMap_->FindMoveAreaIndex(currentWorldPos);
|
|
debugMap_->SetDebugHighlightedMoveAreaIndex(moveAreaIndex);
|
|
}
|
|
|
|
void GameDebugActor::setOverlayVisible(bool visible) {
|
|
if (background_) {
|
|
background_->SetVisible(visible);
|
|
}
|
|
if (coordText_) {
|
|
coordText_->SetVisible(visible);
|
|
}
|
|
if (actionText_) {
|
|
actionText_->SetVisible(visible);
|
|
}
|
|
}
|
|
|
|
} // namespace frostbite2D
|