feat(渲染): 实现NPC和地图层的渲染优化
重构NPC渲染逻辑,将交互高亮同步移至Render方法 为NpcAnimation添加帧激活检查以避免无效纹理刷新 为GameMapLayer添加调试覆盖层画布,优化可行区域和移动区域渲染 更新测试场景地图路径和相机控制器设置
This commit is contained in:
@@ -93,9 +93,9 @@ private:
|
|||||||
int backgroundRepeatWidth_ = 0;
|
int backgroundRepeatWidth_ = 0;
|
||||||
/// 地图配置里的整体 Y 偏移;既影响层位置,也影响地板校准。
|
/// 地图配置里的整体 Y 偏移;既影响层位置,也影响地板校准。
|
||||||
int mapOffsetY_ = 0;
|
int mapOffsetY_ = 0;
|
||||||
bool debugMode_ = true;
|
bool debugMode_ = false;
|
||||||
/// 硬编码调试开关:关闭后忽略可行走区域检测,允许角色自由移动。
|
/// 硬编码调试开关:关闭后忽略可行走区域检测,允许角色自由移动。
|
||||||
bool movableAreaCheckEnabled_ = false;
|
bool movableAreaCheckEnabled_ = true;
|
||||||
/// 当前地图正在播放的背景音乐。
|
/// 当前地图正在播放的背景音乐。
|
||||||
Ptr<Music> currentMusic_;
|
Ptr<Music> currentMusic_;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <frostbite2D/2d/canvas_actor.h>
|
||||||
#include <frostbite2D/2d/actor.h>
|
#include <frostbite2D/2d/actor.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -18,15 +19,29 @@ public:
|
|||||||
void AddObject(RefPtr<Actor> obj);
|
void AddObject(RefPtr<Actor> obj);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void EnsureDebugOverlayCanvases();
|
||||||
|
void RefreshFeasibleAreaOverlay();
|
||||||
|
void RefreshMoveAreaOverlay();
|
||||||
|
Rect ComputeFeasibleAreaOverlayBounds() const;
|
||||||
|
Rect ComputeMoveAreaOverlayBounds() const;
|
||||||
|
void DrawFeasibleAreaOverlay() const;
|
||||||
|
void DrawMoveAreaOverlay() const;
|
||||||
|
|
||||||
struct DebugMoveAreaInfo {
|
struct DebugMoveAreaInfo {
|
||||||
Rect rect;
|
Rect rect;
|
||||||
size_t index = kInvalidMoveAreaIndex;
|
size_t index = kInvalidMoveAreaIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
RefPtr<CanvasActor> feasibleAreaOverlayCanvas_ = nullptr;
|
||||||
|
RefPtr<CanvasActor> moveAreaOverlayCanvas_ = nullptr;
|
||||||
std::vector<Vec2> feasibleAreaPolygon_;
|
std::vector<Vec2> feasibleAreaPolygon_;
|
||||||
std::vector<Rect> feasibleAreaFillRects_;
|
std::vector<Rect> feasibleAreaFillRects_;
|
||||||
std::vector<DebugMoveAreaInfo> moveAreaInfoList_;
|
std::vector<DebugMoveAreaInfo> moveAreaInfoList_;
|
||||||
size_t highlightedMoveAreaIndex_ = kInvalidMoveAreaIndex;
|
size_t highlightedMoveAreaIndex_ = kInvalidMoveAreaIndex;
|
||||||
|
Rect feasibleAreaOverlayBounds_;
|
||||||
|
Rect moveAreaOverlayBounds_;
|
||||||
|
bool feasibleAreaOverlayDirty_ = true;
|
||||||
|
bool moveAreaOverlayDirty_ = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace frostbite2D
|
} // namespace frostbite2D
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Update(float deltaTime) override;
|
void Update(float deltaTime) override;
|
||||||
|
void Render() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void EnsureInteractionHighlight();
|
void EnsureInteractionHighlight();
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "map/GameMapLayer.h"
|
#include "map/GameMapLayer.h"
|
||||||
#include "common/math/GameMath.h"
|
#include "common/math/GameMath.h"
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <frostbite2D/graphics/renderer.h>
|
#include <frostbite2D/graphics/renderer.h>
|
||||||
@@ -14,7 +15,54 @@ constexpr float kDebugEdgePointSize = 5.0f;
|
|||||||
constexpr float kDebugVertexSize = 9.0f;
|
constexpr float kDebugVertexSize = 9.0f;
|
||||||
constexpr float kDebugEdgeStep = 4.0f;
|
constexpr float kDebugEdgeStep = 4.0f;
|
||||||
|
|
||||||
void DrawPolygonOutline(const std::vector<Vec2>& polygon, const Vec2& worldOrigin,
|
struct BoundsAccumulator {
|
||||||
|
bool valid = false;
|
||||||
|
float left = 0.0f;
|
||||||
|
float top = 0.0f;
|
||||||
|
float right = 0.0f;
|
||||||
|
float bottom = 0.0f;
|
||||||
|
|
||||||
|
void IncludePoint(const Vec2& point) {
|
||||||
|
if (!valid) {
|
||||||
|
valid = true;
|
||||||
|
left = point.x;
|
||||||
|
top = point.y;
|
||||||
|
right = point.x;
|
||||||
|
bottom = point.y;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
left = std::min(left, point.x);
|
||||||
|
top = std::min(top, point.y);
|
||||||
|
right = std::max(right, point.x);
|
||||||
|
bottom = std::max(bottom, point.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IncludeRect(const Rect& rect) {
|
||||||
|
if (rect.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IncludePoint(Vec2(rect.left(), rect.top()));
|
||||||
|
IncludePoint(Vec2(rect.right(), rect.bottom()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Rect Build(float padding) const {
|
||||||
|
if (!valid) {
|
||||||
|
return Rect::Zero();
|
||||||
|
}
|
||||||
|
|
||||||
|
float paddedLeft = std::floor(left - padding);
|
||||||
|
float paddedTop = std::floor(top - padding);
|
||||||
|
float paddedRight = std::ceil(right + padding);
|
||||||
|
float paddedBottom = std::ceil(bottom + padding);
|
||||||
|
return Rect(paddedLeft, paddedTop,
|
||||||
|
std::max(paddedRight - paddedLeft, 1.0f),
|
||||||
|
std::max(paddedBottom - paddedTop, 1.0f));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void DrawPolygonOutline(const std::vector<Vec2>& polygon, const Vec2& drawOrigin,
|
||||||
const Color& color) {
|
const Color& color) {
|
||||||
if (polygon.size() < 2) {
|
if (polygon.size() < 2) {
|
||||||
return;
|
return;
|
||||||
@@ -22,8 +70,8 @@ void DrawPolygonOutline(const std::vector<Vec2>& polygon, const Vec2& worldOrigi
|
|||||||
|
|
||||||
auto& renderer = Renderer::get();
|
auto& renderer = Renderer::get();
|
||||||
for (size_t i = 0; i < polygon.size(); ++i) {
|
for (size_t i = 0; i < polygon.size(); ++i) {
|
||||||
Vec2 start = worldOrigin + polygon[i];
|
Vec2 start = drawOrigin + polygon[i];
|
||||||
Vec2 end = worldOrigin + polygon[(i + 1) % polygon.size()];
|
Vec2 end = drawOrigin + polygon[(i + 1) % polygon.size()];
|
||||||
Vec2 delta = end - start;
|
Vec2 delta = end - start;
|
||||||
float length = delta.length();
|
float length = delta.length();
|
||||||
int steps = std::max(1, static_cast<int>(std::ceil(length / kDebugEdgeStep)));
|
int steps = std::max(1, static_cast<int>(std::ceil(length / kDebugEdgeStep)));
|
||||||
@@ -41,10 +89,10 @@ void DrawPolygonOutline(const std::vector<Vec2>& polygon, const Vec2& worldOrigi
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DrawPolygonVertices(const std::vector<Vec2>& polygon,
|
void DrawPolygonVertices(const std::vector<Vec2>& polygon,
|
||||||
const Vec2& worldOrigin, const Color& color) {
|
const Vec2& drawOrigin, const Color& color) {
|
||||||
auto& renderer = Renderer::get();
|
auto& renderer = Renderer::get();
|
||||||
for (const auto& vertex : polygon) {
|
for (const auto& vertex : polygon) {
|
||||||
Vec2 point = worldOrigin + vertex;
|
Vec2 point = drawOrigin + vertex;
|
||||||
renderer.drawQuad(
|
renderer.drawQuad(
|
||||||
Rect(point.x - kDebugVertexSize * 0.5f,
|
Rect(point.x - kDebugVertexSize * 0.5f,
|
||||||
point.y - kDebugVertexSize * 0.5f, kDebugVertexSize,
|
point.y - kDebugVertexSize * 0.5f, kDebugVertexSize,
|
||||||
@@ -57,49 +105,197 @@ void DrawPolygonVertices(const std::vector<Vec2>& polygon,
|
|||||||
|
|
||||||
void GameMapLayer::Render() {
|
void GameMapLayer::Render() {
|
||||||
Actor::Render();
|
Actor::Render();
|
||||||
|
EnsureDebugOverlayCanvases();
|
||||||
|
|
||||||
Vec2 worldOrigin = GetWorldTransform().transformPoint(Vec2::Zero());
|
if (feasibleAreaOverlayDirty_) {
|
||||||
|
RefreshFeasibleAreaOverlay();
|
||||||
|
}
|
||||||
|
if (moveAreaOverlayDirty_) {
|
||||||
|
RefreshMoveAreaOverlay();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (feasibleAreaOverlayCanvas_ && feasibleAreaOverlayCanvas_->IsVisible()) {
|
||||||
|
feasibleAreaOverlayCanvas_->SetPosition(
|
||||||
|
GetWorldTransform().transformPoint(feasibleAreaOverlayBounds_.origin));
|
||||||
|
feasibleAreaOverlayCanvas_->SetOpacity(GetWorldOpacity());
|
||||||
|
feasibleAreaOverlayCanvas_->Render();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (moveAreaOverlayCanvas_ && moveAreaOverlayCanvas_->IsVisible()) {
|
||||||
|
moveAreaOverlayCanvas_->SetPosition(
|
||||||
|
GetWorldTransform().transformPoint(moveAreaOverlayBounds_.origin));
|
||||||
|
moveAreaOverlayCanvas_->SetOpacity(GetWorldOpacity());
|
||||||
|
moveAreaOverlayCanvas_->Render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameMapLayer::EnsureDebugOverlayCanvases() {
|
||||||
|
auto initCanvas = [this](RefPtr<CanvasActor>& canvas, const char* label,
|
||||||
|
std::function<void()> callback) {
|
||||||
|
if (canvas) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas = MakePtr<CanvasActor>();
|
||||||
|
if (!canvas || !canvas->Init(1, 1)) {
|
||||||
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"GameMapLayer: failed to initialize %s canvas", label);
|
||||||
|
canvas.Reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas->SetVisible(false);
|
||||||
|
canvas->SetClearColor(Colors::Transparent);
|
||||||
|
canvas->SetCustomDrawCallback(callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
initCanvas(feasibleAreaOverlayCanvas_, "feasible area overlay",
|
||||||
|
[this]() { DrawFeasibleAreaOverlay(); });
|
||||||
|
initCanvas(moveAreaOverlayCanvas_, "move area overlay",
|
||||||
|
[this]() { DrawMoveAreaOverlay(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameMapLayer::RefreshFeasibleAreaOverlay() {
|
||||||
|
feasibleAreaOverlayDirty_ = false;
|
||||||
|
if (!feasibleAreaOverlayCanvas_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
feasibleAreaOverlayBounds_ = ComputeFeasibleAreaOverlayBounds();
|
||||||
|
if (feasibleAreaOverlayBounds_.empty()) {
|
||||||
|
feasibleAreaOverlayCanvas_->SetVisible(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int width =
|
||||||
|
std::max(static_cast<int>(std::lround(feasibleAreaOverlayBounds_.width())), 1);
|
||||||
|
int height =
|
||||||
|
std::max(static_cast<int>(std::lround(feasibleAreaOverlayBounds_.height())), 1);
|
||||||
|
if (!feasibleAreaOverlayCanvas_->SetCanvasSize(width, height)) {
|
||||||
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"GameMapLayer: failed to resize feasible area overlay canvas to %dx%d",
|
||||||
|
width, height);
|
||||||
|
feasibleAreaOverlayCanvas_->SetVisible(false);
|
||||||
|
feasibleAreaOverlayDirty_ = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
feasibleAreaOverlayCanvas_->SetVisible(true);
|
||||||
|
feasibleAreaOverlayCanvas_->SetDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameMapLayer::RefreshMoveAreaOverlay() {
|
||||||
|
moveAreaOverlayDirty_ = false;
|
||||||
|
if (!moveAreaOverlayCanvas_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
moveAreaOverlayBounds_ = ComputeMoveAreaOverlayBounds();
|
||||||
|
if (moveAreaOverlayBounds_.empty()) {
|
||||||
|
moveAreaOverlayCanvas_->SetVisible(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int width =
|
||||||
|
std::max(static_cast<int>(std::lround(moveAreaOverlayBounds_.width())), 1);
|
||||||
|
int height =
|
||||||
|
std::max(static_cast<int>(std::lround(moveAreaOverlayBounds_.height())), 1);
|
||||||
|
if (!moveAreaOverlayCanvas_->SetCanvasSize(width, height)) {
|
||||||
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"GameMapLayer: failed to resize move area overlay canvas to %dx%d",
|
||||||
|
width, height);
|
||||||
|
moveAreaOverlayCanvas_->SetVisible(false);
|
||||||
|
moveAreaOverlayDirty_ = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
moveAreaOverlayCanvas_->SetVisible(true);
|
||||||
|
moveAreaOverlayCanvas_->SetDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
Rect GameMapLayer::ComputeFeasibleAreaOverlayBounds() const {
|
||||||
|
BoundsAccumulator bounds;
|
||||||
|
for (const auto& rect : feasibleAreaFillRects_) {
|
||||||
|
bounds.IncludeRect(rect);
|
||||||
|
}
|
||||||
|
for (const auto& point : feasibleAreaPolygon_) {
|
||||||
|
bounds.IncludePoint(point);
|
||||||
|
}
|
||||||
|
|
||||||
|
float padding = std::max(kDebugEdgePointSize, kDebugVertexSize) * 0.5f;
|
||||||
|
return bounds.Build(padding);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rect GameMapLayer::ComputeMoveAreaOverlayBounds() const {
|
||||||
|
BoundsAccumulator bounds;
|
||||||
|
for (const auto& moveArea : moveAreaInfoList_) {
|
||||||
|
bounds.IncludeRect(moveArea.rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
float padding = std::max(kDebugEdgePointSize, kDebugVertexSize) * 0.5f;
|
||||||
|
return bounds.Build(padding);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameMapLayer::DrawFeasibleAreaOverlay() const {
|
||||||
|
if (feasibleAreaOverlayBounds_.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec2 drawOrigin(-feasibleAreaOverlayBounds_.origin.x,
|
||||||
|
-feasibleAreaOverlayBounds_.origin.y);
|
||||||
|
|
||||||
for (const auto& rect : feasibleAreaFillRects_) {
|
for (const auto& rect : feasibleAreaFillRects_) {
|
||||||
Rect drawRect(worldOrigin.x + rect.origin.x, worldOrigin.y + rect.origin.y,
|
Rect drawRect(drawOrigin.x + rect.origin.x, drawOrigin.y + rect.origin.y,
|
||||||
rect.width(), rect.height());
|
rect.width(), rect.height());
|
||||||
Renderer::get().drawQuad(drawRect, Color(0.0f, 1.0f, 0.0f, kDebugAreaAlpha));
|
Renderer::get().drawQuad(drawRect, Color(0.0f, 1.0f, 0.0f, kDebugAreaAlpha));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (feasibleAreaPolygon_.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color outlineColor(0.0f, 1.0f, 0.0f, kDebugOutlineAlpha);
|
||||||
|
DrawPolygonOutline(feasibleAreaPolygon_, drawOrigin, outlineColor);
|
||||||
|
DrawPolygonVertices(feasibleAreaPolygon_, drawOrigin, outlineColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameMapLayer::DrawMoveAreaOverlay() const {
|
||||||
|
if (moveAreaOverlayBounds_.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec2 drawOrigin(-moveAreaOverlayBounds_.origin.x, -moveAreaOverlayBounds_.origin.y);
|
||||||
|
|
||||||
for (const auto& moveArea : moveAreaInfoList_) {
|
for (const auto& moveArea : moveAreaInfoList_) {
|
||||||
bool isHighlighted = moveArea.index == highlightedMoveAreaIndex_;
|
bool isHighlighted = moveArea.index == highlightedMoveAreaIndex_;
|
||||||
Color fillColor =
|
Color fillColor =
|
||||||
isHighlighted ? Color(0.0f, 1.0f, 1.0f, 0.60f)
|
isHighlighted ? Color(0.0f, 1.0f, 1.0f, 0.60f)
|
||||||
: Color(0.0f, 0.0f, 1.0f, kDebugAreaAlpha);
|
: Color(0.0f, 0.0f, 1.0f, kDebugAreaAlpha);
|
||||||
Rect drawRect(worldOrigin.x + moveArea.rect.origin.x,
|
Rect drawRect(drawOrigin.x + moveArea.rect.origin.x,
|
||||||
worldOrigin.y + moveArea.rect.origin.y,
|
drawOrigin.y + moveArea.rect.origin.y,
|
||||||
moveArea.rect.width(), moveArea.rect.height());
|
moveArea.rect.width(), moveArea.rect.height());
|
||||||
Renderer::get().drawQuad(drawRect, fillColor);
|
Renderer::get().drawQuad(drawRect, fillColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!feasibleAreaPolygon_.empty()) {
|
for (const auto& moveArea : moveAreaInfoList_) {
|
||||||
Color outlineColor(0.0f, 1.0f, 0.0f, kDebugOutlineAlpha);
|
|
||||||
DrawPolygonOutline(feasibleAreaPolygon_, worldOrigin, outlineColor);
|
|
||||||
DrawPolygonVertices(feasibleAreaPolygon_, worldOrigin, outlineColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& moveArea : moveAreaInfoList_) {
|
|
||||||
std::vector<Vec2> polygon = gameMath::BuildRectPolygon(moveArea.rect);
|
std::vector<Vec2> polygon = gameMath::BuildRectPolygon(moveArea.rect);
|
||||||
if (polygon.empty()) {
|
if (polygon.empty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isHighlighted = moveArea.index == highlightedMoveAreaIndex_;
|
bool isHighlighted = moveArea.index == highlightedMoveAreaIndex_;
|
||||||
Color moveAreaOutlineColor =
|
Color moveAreaOutlineColor =
|
||||||
isHighlighted ? Color(0.0f, 1.0f, 1.0f, 1.0f)
|
isHighlighted ? Color(0.0f, 1.0f, 1.0f, 1.0f)
|
||||||
: Color(0.0f, 0.0f, 1.0f, kDebugOutlineAlpha);
|
: Color(0.0f, 0.0f, 1.0f, kDebugOutlineAlpha);
|
||||||
DrawPolygonOutline(polygon, worldOrigin, moveAreaOutlineColor);
|
DrawPolygonOutline(polygon, drawOrigin, moveAreaOutlineColor);
|
||||||
DrawPolygonVertices(polygon, worldOrigin, moveAreaOutlineColor);
|
DrawPolygonVertices(polygon, drawOrigin, moveAreaOutlineColor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameMapLayer::SetDebugFeasibleAreaPolygon(const std::vector<Vec2>& polygon) {
|
void GameMapLayer::SetDebugFeasibleAreaPolygon(const std::vector<Vec2>& polygon) {
|
||||||
feasibleAreaPolygon_ = polygon;
|
feasibleAreaPolygon_ = polygon;
|
||||||
feasibleAreaFillRects_ = gameMath::BuildPolygonFillRects(feasibleAreaPolygon_);
|
feasibleAreaFillRects_ = gameMath::BuildPolygonFillRects(feasibleAreaPolygon_);
|
||||||
|
feasibleAreaOverlayDirty_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameMapLayer::AddDebugMoveAreaInfo(const Rect& rect, size_t index) {
|
void GameMapLayer::AddDebugMoveAreaInfo(const Rect& rect, size_t index) {
|
||||||
@@ -108,10 +304,16 @@ void GameMapLayer::AddDebugMoveAreaInfo(const Rect& rect, size_t index) {
|
|||||||
debugArea.index = index;
|
debugArea.index = index;
|
||||||
|
|
||||||
moveAreaInfoList_.push_back(std::move(debugArea));
|
moveAreaInfoList_.push_back(std::move(debugArea));
|
||||||
|
moveAreaOverlayDirty_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameMapLayer::SetDebugHighlightedMoveAreaIndex(size_t index) {
|
void GameMapLayer::SetDebugHighlightedMoveAreaIndex(size_t index) {
|
||||||
|
if (highlightedMoveAreaIndex_ == index) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
highlightedMoveAreaIndex_ = index;
|
highlightedMoveAreaIndex_ = index;
|
||||||
|
moveAreaOverlayDirty_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameMapLayer::ClearDebugAreaInfo() {
|
void GameMapLayer::ClearDebugAreaInfo() {
|
||||||
@@ -119,6 +321,17 @@ void GameMapLayer::ClearDebugAreaInfo() {
|
|||||||
feasibleAreaFillRects_.clear();
|
feasibleAreaFillRects_.clear();
|
||||||
moveAreaInfoList_.clear();
|
moveAreaInfoList_.clear();
|
||||||
highlightedMoveAreaIndex_ = kInvalidMoveAreaIndex;
|
highlightedMoveAreaIndex_ = kInvalidMoveAreaIndex;
|
||||||
|
feasibleAreaOverlayBounds_ = Rect::Zero();
|
||||||
|
moveAreaOverlayBounds_ = Rect::Zero();
|
||||||
|
feasibleAreaOverlayDirty_ = true;
|
||||||
|
moveAreaOverlayDirty_ = true;
|
||||||
|
|
||||||
|
if (feasibleAreaOverlayCanvas_) {
|
||||||
|
feasibleAreaOverlayCanvas_->SetVisible(false);
|
||||||
|
}
|
||||||
|
if (moveAreaOverlayCanvas_) {
|
||||||
|
moveAreaOverlayCanvas_->SetVisible(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameMapLayer::AddObject(RefPtr<Actor> obj) {
|
void GameMapLayer::AddObject(RefPtr<Actor> obj) {
|
||||||
|
|||||||
@@ -152,6 +152,10 @@ bool NpcAnimation::GetDisplayLocalBounds(Rect& outBounds) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool NpcAnimation::EnsureCompositeTextureReady() {
|
bool NpcAnimation::EnsureCompositeTextureReady() {
|
||||||
|
if (!Renderer::get().isFrameActive()) {
|
||||||
|
return HasCompositeTexture();
|
||||||
|
}
|
||||||
|
|
||||||
RefreshCompositeTextureIfNeeded();
|
RefreshCompositeTextureIfNeeded();
|
||||||
return HasCompositeTexture();
|
return HasCompositeTexture();
|
||||||
}
|
}
|
||||||
@@ -242,6 +246,10 @@ void NpcAnimation::RefreshCompositeTextureIfNeeded() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Renderer::get().isFrameActive()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
CompositeFrameInfo info = GetCurrentCompositeFrameInfo();
|
CompositeFrameInfo info = GetCurrentCompositeFrameInfo();
|
||||||
if (!info.valid) {
|
if (!info.valid) {
|
||||||
compositeDirty_ = false;
|
compositeDirty_ = false;
|
||||||
|
|||||||
@@ -89,7 +89,6 @@ void NpcObject::SetDirection(int direction) {
|
|||||||
animation_->SetDirection(direction_);
|
animation_->SetDirection(direction_);
|
||||||
}
|
}
|
||||||
RefreshNameLabel();
|
RefreshNameLabel();
|
||||||
SyncInteractionHighlight();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NpcObject::SetNpcPosition(const Vec2& pos) {
|
void NpcObject::SetNpcPosition(const Vec2& pos) {
|
||||||
@@ -163,7 +162,11 @@ bool NpcObject::IsAnimationFinished() const {
|
|||||||
|
|
||||||
void NpcObject::Update(float deltaTime) {
|
void NpcObject::Update(float deltaTime) {
|
||||||
Actor::Update(deltaTime);
|
Actor::Update(deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NpcObject::Render() {
|
||||||
SyncInteractionHighlight();
|
SyncInteractionHighlight();
|
||||||
|
Actor::Render();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NpcObject::EnsureInteractionHighlight() {
|
void NpcObject::EnsureInteractionHighlight() {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace frostbite2D {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr char kTestMapPath[] = "map/elvengard/d_elvengard.map";
|
constexpr char kTestMapPath[] = "map/cataclysm/town/seria_room/elvengard.map";
|
||||||
constexpr int kTestNpcId = 2;
|
constexpr int kTestNpcId = 2;
|
||||||
constexpr float kTestNpcOffsetX = 180.0f;
|
constexpr float kTestNpcOffsetX = 180.0f;
|
||||||
constexpr float kTestNpcOffsetY = -24.0f;
|
constexpr float kTestNpcOffsetY = -24.0f;
|
||||||
@@ -28,6 +28,9 @@ void GameMapTestScene::onEnter() {
|
|||||||
SceneManager::get().PushUIScene(debugScene_);
|
SceneManager::get().PushUIScene(debugScene_);
|
||||||
|
|
||||||
if (initialized_) {
|
if (initialized_) {
|
||||||
|
cameraController_.SetMap(map_.Get());
|
||||||
|
cameraController_.SetTarget(character_.Get());
|
||||||
|
cameraController_.SetDebugEnabled(false);
|
||||||
debugScene_->SetDebugContext(map_.Get(), character_.Get());
|
debugScene_->SetDebugContext(map_.Get(), character_.Get());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -45,6 +48,8 @@ void GameMapTestScene::onEnter() {
|
|||||||
}
|
}
|
||||||
AddChild(map_);
|
AddChild(map_);
|
||||||
|
|
||||||
|
character_.Reset();
|
||||||
|
npc_.Reset();
|
||||||
{
|
{
|
||||||
ScopedStartupTrace stageTrace("GameMapTestScene character construction");
|
ScopedStartupTrace stageTrace("GameMapTestScene character construction");
|
||||||
character_ = MakePtr<CharacterObject>();
|
character_ = MakePtr<CharacterObject>();
|
||||||
@@ -53,8 +58,7 @@ void GameMapTestScene::onEnter() {
|
|||||||
"GameMapTestScene: failed to construct default character");
|
"GameMapTestScene: failed to construct default character");
|
||||||
character_.Reset();
|
character_.Reset();
|
||||||
} else {
|
} else {
|
||||||
Vec2 spawnPos =
|
Vec2 spawnPos = map_->ClampCameraFocus(map_->GetDefaultCameraFocus(), 1.0f);
|
||||||
map_->ClampCameraFocus(map_->GetDefaultCameraFocus(), 1.0f);
|
|
||||||
character_->SetCharacterPosition(spawnPos);
|
character_->SetCharacterPosition(spawnPos);
|
||||||
character_->EnableEventReceive();
|
character_->EnableEventReceive();
|
||||||
character_->SetEventPriority(-100);
|
character_->SetEventPriority(-100);
|
||||||
|
|||||||
Reference in New Issue
Block a user