#include "camera_controller.h" #include #include 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::SetWorldBounds(const frostbite2D::Rect& worldBounds) { const float width = std::max(worldBounds.width(), config_.viewportWidth); const float height = std::max(worldBounds.height(), config_.viewportHeight); config_.worldBounds = frostbite2D::Rect(worldBounds.left(), worldBounds.top(), width, height); } 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