Add camera zone lock

This commit is contained in:
2026-06-09 14:28:36 +08:00
parent c1096f0ed5
commit 3a56db3dc7
9 changed files with 146 additions and 19 deletions
+11
View File
@@ -34,6 +34,17 @@ struct BattleZoneDefinition {
std::vector<SpawnPoint> enemySpawns;
};
enum class BattleZoneDebugState {
Idle,
Active,
Cleared
};
struct BattleZoneDebugInfo {
size_t zoneIndex = 0;
BattleZoneDebugState state = BattleZoneDebugState::Idle;
};
struct StageLayer {
std::string id;
StageLayerRole role = StageLayerRole::LevelVisual;
+36 -5
View File
@@ -37,15 +37,43 @@ void drawCross(const frostbite2D::Vec2& position,
color);
}
BattleZoneDebugState resolveZoneState(
size_t zoneIndex, const std::vector<BattleZoneDebugInfo>* debugInfo) {
if (!debugInfo) {
return BattleZoneDebugState::Idle;
}
for (const BattleZoneDebugInfo& info : *debugInfo) {
if (info.zoneIndex == zoneIndex) {
return info.state;
}
}
return BattleZoneDebugState::Idle;
}
frostbite2D::Color zoneColor(BattleZoneDebugState state) {
switch (state) {
case BattleZoneDebugState::Active:
return frostbite2D::Color(1.0f, 0.82f, 0.15f, 0.95f);
case BattleZoneDebugState::Cleared:
return frostbite2D::Color(0.45f, 0.48f, 0.52f, 0.65f);
case BattleZoneDebugState::Idle:
default:
return frostbite2D::Color(0.95f, 0.25f, 0.25f, 0.9f);
}
}
} // namespace
void DebugOverlay::Render(const LevelDefinition& level, const DebugFlags& flags,
const frostbite2D::Rect* playerBounds) const {
const frostbite2D::Rect* playerBounds,
const std::vector<BattleZoneDebugInfo>*
battleZoneDebug) const {
if (flags.showCollision) {
drawCollision(level);
}
if (flags.showBattleZones) {
drawBattleZones(level);
drawBattleZones(level, battleZoneDebug);
}
if (flags.showSpawnPoints) {
drawSpawnPoints(level);
@@ -65,9 +93,12 @@ void DebugOverlay::drawActorBounds(const frostbite2D::Rect& bounds) const {
drawOutline(bounds, frostbite2D::Color(1.0f, 0.78f, 0.1f, 0.9f));
}
void DebugOverlay::drawBattleZones(const LevelDefinition& level) const {
for (const BattleZoneDefinition& zone : level.battleZones) {
drawOutline(zone.trigger, frostbite2D::Color(0.95f, 0.25f, 0.25f, 0.9f),
void DebugOverlay::drawBattleZones(
const LevelDefinition& level,
const std::vector<BattleZoneDebugInfo>* battleZoneDebug) const {
for (size_t i = 0; i < level.battleZones.size(); ++i) {
const BattleZoneDefinition& zone = level.battleZones[i];
drawOutline(zone.trigger, zoneColor(resolveZoneState(i, battleZoneDebug)),
3.0f);
drawOutline(zone.cameraBounds,
frostbite2D::Color(0.25f, 0.55f, 1.0f, 0.75f), 2.0f);
+6 -2
View File
@@ -4,18 +4,22 @@
#include "../data/level_definition.h"
#include <frostbite2D/types/type_math.h>
#include <vector>
namespace ns_game {
class DebugOverlay {
public:
void Render(const LevelDefinition& level, const DebugFlags& flags,
const frostbite2D::Rect* playerBounds) const;
const frostbite2D::Rect* playerBounds,
const std::vector<BattleZoneDebugInfo>* battleZoneDebug) const;
private:
void drawCollision(const LevelDefinition& level) const;
void drawActorBounds(const frostbite2D::Rect& bounds) const;
void drawBattleZones(const LevelDefinition& level) const;
void drawBattleZones(
const LevelDefinition& level,
const std::vector<BattleZoneDebugInfo>* battleZoneDebug) const;
void drawSpawnPoints(const LevelDefinition& level) const;
};
+4
View File
@@ -27,6 +27,10 @@ void CameraController::Configure(const CameraControllerConfig& config) {
config_ = config;
}
void CameraController::SetWorldBounds(const frostbite2D::Rect& worldBounds) {
config_.worldBounds = worldBounds;
}
void CameraController::SnapToTarget(frostbite2D::Camera& camera,
const frostbite2D::Rect& targetBounds) {
camera.setPosition(clampToWorld(
+1
View File
@@ -16,6 +16,7 @@ struct CameraControllerConfig {
class CameraController {
public:
void Configure(const CameraControllerConfig& config);
void SetWorldBounds(const frostbite2D::Rect& worldBounds);
void SnapToTarget(frostbite2D::Camera& camera,
const frostbite2D::Rect& targetBounds);
void Update(frostbite2D::Camera& camera, const frostbite2D::Rect& targetBounds,
+64 -1
View File
@@ -12,6 +12,9 @@ namespace ns_game {
void WhiteboxScene::onEnter() {
frostbite2D::Scene::onEnter();
level_ = CreateWhiteboxLevel();
battleZoneStates_.clear();
battleZoneStates_.resize(level_.battleZones.size());
activeBattleZoneIndex_ = -1;
player_ = frostbite2D::MakePtr<PlayerActor>();
player_->SetTopLeftPosition(level_.playerSpawn);
@@ -22,6 +25,7 @@ void WhiteboxScene::onEnter() {
void WhiteboxScene::Update(float deltaTime) {
frostbite2D::Scene::Update(deltaTime);
updateBattleZones();
updateCamera(deltaTime);
}
@@ -33,6 +37,11 @@ bool WhiteboxScene::OnEvent(const frostbite2D::Event& event) {
toggleDebugOverlay();
return true;
}
if (!keyEvent.isRepeat() &&
keyEvent.getKeyCode() == frostbite2D::KeyCode::F2) {
clearActiveBattleZone();
return true;
}
}
return frostbite2D::Scene::OnEvent(event);
@@ -43,7 +52,10 @@ void WhiteboxScene::Render() {
frostbite2D::Scene::Render();
const frostbite2D::Rect playerBounds =
player_ ? player_->GetWorldBounds() : frostbite2D::Rect::Zero();
debugOverlay_.Render(level_, debugFlags_, player_ ? &playerBounds : nullptr);
const std::vector<BattleZoneDebugInfo> battleZoneDebug =
buildBattleZoneDebugInfo();
debugOverlay_.Render(level_, debugFlags_, player_ ? &playerBounds : nullptr,
&battleZoneDebug);
}
frostbite2D::Camera* WhiteboxScene::activeCamera() const {
@@ -54,6 +66,22 @@ frostbite2D::Camera* WhiteboxScene::activeCamera() const {
return renderer->getCamera();
}
std::vector<BattleZoneDebugInfo> WhiteboxScene::buildBattleZoneDebugInfo()
const {
std::vector<BattleZoneDebugInfo> debugInfo;
debugInfo.reserve(battleZoneStates_.size());
for (size_t i = 0; i < battleZoneStates_.size(); ++i) {
BattleZoneDebugState state = BattleZoneDebugState::Idle;
if (battleZoneStates_[i].cleared) {
state = BattleZoneDebugState::Cleared;
} else if (activeBattleZoneIndex_ == static_cast<int>(i)) {
state = BattleZoneDebugState::Active;
}
debugInfo.push_back(BattleZoneDebugInfo{i, state});
}
return debugInfo;
}
void WhiteboxScene::configureCamera() {
auto* camera = activeCamera();
if (!camera) {
@@ -83,6 +111,41 @@ void WhiteboxScene::toggleDebugOverlay() {
debugFlags_.showSpawnPoints = enabled;
}
void WhiteboxScene::clearActiveBattleZone() {
if (activeBattleZoneIndex_ < 0 ||
activeBattleZoneIndex_ >= static_cast<int>(battleZoneStates_.size())) {
return;
}
battleZoneStates_[static_cast<size_t>(activeBattleZoneIndex_)].cleared = true;
activeBattleZoneIndex_ = -1;
cameraController_.SetWorldBounds(level_.cameraBounds);
}
void WhiteboxScene::updateBattleZones() {
if (!player_) {
return;
}
if (activeBattleZoneIndex_ >= 0) {
return;
}
const frostbite2D::Rect playerBounds = player_->GetWorldBounds();
for (size_t i = 0; i < level_.battleZones.size(); ++i) {
BattleZoneRuntime& runtime = battleZoneStates_[i];
if (runtime.cleared ||
!level_.battleZones[i].trigger.intersects(playerBounds)) {
continue;
}
runtime.triggered = true;
activeBattleZoneIndex_ = static_cast<int>(i);
cameraController_.SetWorldBounds(level_.battleZones[i].cameraBounds);
break;
}
}
void WhiteboxScene::updateCamera(float deltaTime) {
if (!player_) {
return;
+12
View File
@@ -9,6 +9,8 @@
#include <frostbite2D/scene/scene.h>
#include <frostbite2D/types/type_math.h>
#include <string>
#include <vector>
namespace ns_game {
@@ -20,13 +22,23 @@ public:
void Render() override;
private:
struct BattleZoneRuntime {
bool triggered = false;
bool cleared = false;
};
frostbite2D::Camera* activeCamera() const;
std::vector<BattleZoneDebugInfo> buildBattleZoneDebugInfo() const;
void configureCamera();
void toggleDebugOverlay();
void clearActiveBattleZone();
void updateBattleZones();
void updateCamera(float deltaTime);
LevelDefinition level_;
DebugFlags debugFlags_;
std::vector<BattleZoneRuntime> battleZoneStates_;
int activeBattleZoneIndex_ = -1;
CameraController cameraController_;
StageRenderer stageRenderer_;
DebugOverlay debugOverlay_;