Add player camera controller

This commit is contained in:
2026-06-09 14:11:12 +08:00
parent 8a89346978
commit 47936abed0
6 changed files with 156 additions and 26 deletions
+72
View File
@@ -0,0 +1,72 @@
#include "camera_controller.h"
#include <algorithm>
#include <cmath>
namespace ns_game {
namespace {
float clampValue(float value, float minValue, float maxValue) {
if (maxValue < minValue) {
return minValue;
}
return std::clamp(value, minValue, maxValue);
}
float smoothFactor(float smoothing, float deltaTime) {
if (smoothing <= 0.0f) {
return 1.0f;
}
return 1.0f - std::exp(-smoothing * std::max(deltaTime, 0.0f));
}
} // namespace
void CameraController::Configure(const CameraControllerConfig& config) {
config_ = config;
}
void CameraController::SnapToTarget(frostbite2D::Camera& camera,
const frostbite2D::Rect& targetBounds) {
camera.setPosition(clampToWorld(
resolveDesiredPosition(camera.getPosition(), targetBounds)));
}
void CameraController::Update(frostbite2D::Camera& camera,
const frostbite2D::Rect& targetBounds,
float deltaTime) {
const frostbite2D::Vec2 current = camera.getPosition();
const frostbite2D::Vec2 desired =
clampToWorld(resolveDesiredPosition(current, targetBounds));
const float t = smoothFactor(config_.smoothing, deltaTime);
camera.setPosition(frostbite2D::Vec2(
current.x + (desired.x - current.x) * t,
current.y + (desired.y - current.y) * t));
}
frostbite2D::Vec2 CameraController::resolveDesiredPosition(
const frostbite2D::Vec2& currentPosition,
const frostbite2D::Rect& targetBounds) const {
frostbite2D::Vec2 desired = currentPosition;
const float targetCenterX = targetBounds.left() + targetBounds.width() * 0.5f;
const float screenX = targetCenterX - currentPosition.x;
if (screenX < config_.deadZone.left()) {
desired.x = targetCenterX - config_.deadZone.left();
} else if (screenX > config_.deadZone.right()) {
desired.x = targetCenterX - config_.deadZone.right();
}
desired.y = config_.worldBounds.top();
return desired;
}
frostbite2D::Vec2 CameraController::clampToWorld(
const frostbite2D::Vec2& position) const {
return frostbite2D::Vec2(
clampValue(position.x, config_.worldBounds.left(),
config_.worldBounds.right() - config_.viewportWidth),
clampValue(position.y, config_.worldBounds.top(),
config_.worldBounds.bottom() - config_.viewportHeight));
}
} // namespace ns_game