#include "camera/GameCameraController.h" #include "map/GameMap.h" #include #include #include #include #include namespace frostbite2D { namespace { constexpr float kScreenWidth = 1280.0f; constexpr float kScreenHeight = 720.0f; constexpr int kDebugStickDeadzone = 8000; float normalizeControllerAxis(int16 value) { float magnitude = static_cast(value); if (std::abs(magnitude) <= static_cast(kDebugStickDeadzone)) { return 0.0f; } float sign = magnitude < 0.0f ? -1.0f : 1.0f; float normalized = (std::abs(magnitude) - static_cast(kDebugStickDeadzone)) / (32767.0f - static_cast(kDebugStickDeadzone)); return std::clamp(normalized, 0.0f, 1.0f) * sign; } } GameCameraController::~GameCameraController() { closeDebugController(); } void GameCameraController::SetMap(GameMap* map) { map_ = map; initialized_ = false; } void GameCameraController::SetTarget(Actor* target) { target_ = target; } void GameCameraController::ClearTarget() { target_ = nullptr; } void GameCameraController::SetDebugEnabled(bool enabled) { debugEnabled_ = enabled; if (debugEnabled_) { openDebugController(); } else { closeDebugController(); } } void GameCameraController::SetZoom(float zoom) { zoom_ = std::max(zoom, 0.01f); if (map_) { focus_ = map_->ClampCameraFocus(focus_, zoom_); } applyFocus(); } void GameCameraController::SetFocus(const Vec2& focus) { focus_ = map_ ? map_->ClampCameraFocus(focus, zoom_) : focus; initialized_ = true; applyFocus(); } void GameCameraController::SnapToDefaultFocus() { if (!map_) { return; } focus_ = map_->ClampCameraFocus(map_->GetDefaultCameraFocus(), zoom_); initialized_ = true; applyFocus(); } void GameCameraController::Update(float deltaTime) { if (!map_) { return; } if (!initialized_) { SnapToDefaultFocus(); } if (target_) { Vec2 targetFocus = target_->GetPosition(); float t = std::clamp(deltaTime * followLerpSpeed_, 0.0f, 1.0f); focus_ = focus_ + (targetFocus - focus_) * t; } else if (debugEnabled_) { updateDebugInput(deltaTime); } focus_ = map_->ClampCameraFocus(focus_, zoom_); applyFocus(); } void GameCameraController::openDebugController() { if (debugController_ && SDL_GameControllerGetAttached(debugController_)) { return; } closeDebugController(); int joystickCount = SDL_NumJoysticks(); for (int i = 0; i < joystickCount; ++i) { if (!SDL_IsGameController(i)) { continue; } debugController_ = SDL_GameControllerOpen(i); if (debugController_) { return; } } } void GameCameraController::closeDebugController() { if (!debugController_) { return; } SDL_GameControllerClose(debugController_); debugController_ = nullptr; } void GameCameraController::updateDebugInput(float deltaTime) { const uint8* keyboardState = SDL_GetKeyboardState(nullptr); float moveX = 0.0f; float moveY = 0.0f; if (keyboardState) { if (keyboardState[SDL_SCANCODE_A]) { moveX -= 1.0f; } if (keyboardState[SDL_SCANCODE_D]) { moveX += 1.0f; } if (keyboardState[SDL_SCANCODE_W]) { moveY -= 1.0f; } if (keyboardState[SDL_SCANCODE_S]) { moveY += 1.0f; } } if (debugEnabled_ && !debugController_) { openDebugController(); } if (debugController_ && !SDL_GameControllerGetAttached(debugController_)) { closeDebugController(); openDebugController(); } if (debugController_ && SDL_GameControllerGetAttached(debugController_)) { moveX += normalizeControllerAxis( SDL_GameControllerGetAxis(debugController_, SDL_CONTROLLER_AXIS_LEFTX)); moveY += normalizeControllerAxis( SDL_GameControllerGetAxis(debugController_, SDL_CONTROLLER_AXIS_LEFTY)); } moveX = std::clamp(moveX, -1.0f, 1.0f); moveY = std::clamp(moveY, -1.0f, 1.0f); if (moveX == 0.0f && moveY == 0.0f) { return; } focus_.x += moveX * debugMoveSpeed_ * deltaTime; focus_.y += moveY * debugMoveSpeed_ * deltaTime; } void GameCameraController::applyFocus() const { Camera* camera = Renderer::get().getCamera(); if (!camera || !map_) { return; } float halfWidth = kScreenWidth * 0.5f / zoom_; float halfHeight = kScreenHeight * 0.5f / zoom_; Vec2 cameraPos(focus_.x - halfWidth, focus_.y - halfHeight); camera->setZoom(zoom_); camera->setPosition(cameraPos); map_->ApplyCameraFocus(focus_); } } // namespace frostbite2D