实现虚拟分辨率渲染系统,支持不同缩放模式 重构相机控制器以使用虚拟分辨率计算可见区域 移除硬编码的屏幕尺寸,改为动态获取 添加分辨率状态管理及相关工具函数 更新窗口和渲染器以处理分辨率变化
150 lines
3.9 KiB
C++
150 lines
3.9 KiB
C++
#include "world/GameTown.h"
|
|
#include "character/CharacterObject.h"
|
|
#include <SDL2/SDL.h>
|
|
#include <algorithm>
|
|
#include <cmath>
|
|
|
|
namespace frostbite2D {
|
|
|
|
namespace {
|
|
|
|
Vec2 RoundWorldPoint(const Vec2& pos) {
|
|
return Vec2(static_cast<float>(std::lround(pos.x)),
|
|
static_cast<float>(std::lround(pos.y)));
|
|
}
|
|
|
|
} // namespace
|
|
|
|
GameTown::GameTown() {
|
|
EnableEventReceive();
|
|
}
|
|
|
|
bool GameTown::Init(int index, const std::string& townPath) {
|
|
game::TownConfig config;
|
|
if (!game::loadTownConfig(townPath, config)) {
|
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "GameTown: failed to init town %d (%s)",
|
|
index, townPath.c_str());
|
|
return false;
|
|
}
|
|
|
|
name_ = config.townName;
|
|
enteringTitle_ = config.enteringTitle;
|
|
enteringCutscene_ = config.enteringCutscene;
|
|
needQuestId_ = config.needQuestId;
|
|
needLevel_ = config.needLevel;
|
|
mapList_.clear();
|
|
curMapIndex_ = -1;
|
|
sariaRoomId_ = -1;
|
|
sariaRoomPos_ = Vec2(-1.0f, -1.0f);
|
|
|
|
for (const auto& [areaId, areaConfig] : config.areas) {
|
|
auto map = MakePtr<GameMap>();
|
|
if (!map->LoadMap(areaConfig.mapPath)) {
|
|
continue;
|
|
}
|
|
|
|
MapInfo info;
|
|
info.areaId = areaId;
|
|
info.map = map;
|
|
info.type = areaConfig.mapType;
|
|
info.generatePos = areaConfig.generatePos;
|
|
mapList_.push_back(info);
|
|
|
|
if (info.type == "gate") {
|
|
sariaRoomId_ = areaId;
|
|
sariaRoomPos_ = areaConfig.generatePos;
|
|
}
|
|
}
|
|
|
|
std::sort(mapList_.begin(), mapList_.end(),
|
|
[](const MapInfo& a, const MapInfo& b) { return a.areaId < b.areaId; });
|
|
return !mapList_.empty();
|
|
}
|
|
|
|
RefPtr<GameMap> GameTown::GetArea(int index) const {
|
|
auto it = std::find_if(mapList_.begin(), mapList_.end(),
|
|
[index](const MapInfo& info) { return info.areaId == index; });
|
|
if (it == mapList_.end()) {
|
|
return nullptr;
|
|
}
|
|
return it->map;
|
|
}
|
|
|
|
RefPtr<GameMap> GameTown::GetCurrentArea() const {
|
|
if (curMapIndex_ == -1) {
|
|
return nullptr;
|
|
}
|
|
|
|
return GetArea(curMapIndex_);
|
|
}
|
|
|
|
void GameTown::AddCharacter(RefPtr<Actor> actor, int areaIndex) {
|
|
int targetMapIndex = areaIndex;
|
|
if (areaIndex == -2) {
|
|
if (sariaRoomId_ != -1) {
|
|
targetMapIndex = sariaRoomId_;
|
|
} else {
|
|
targetMapIndex = mapList_.empty() ? -1 : mapList_.front().areaId;
|
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
|
"GameTown: no gate area configured, fallback to first area %d",
|
|
targetMapIndex);
|
|
}
|
|
}
|
|
|
|
auto mapIt = std::find_if(mapList_.begin(), mapList_.end(),
|
|
[targetMapIndex](const MapInfo& info) {
|
|
return info.areaId == targetMapIndex;
|
|
});
|
|
if (mapIt == mapList_.end()) {
|
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
|
"GameTown: target area %d not found, fallback to first map", targetMapIndex);
|
|
if (mapList_.empty()) {
|
|
return;
|
|
}
|
|
mapIt = mapList_.begin();
|
|
}
|
|
|
|
if (curMapIndex_ != -1) {
|
|
auto oldMap = GetArea(curMapIndex_);
|
|
if (oldMap) {
|
|
RemoveChild(oldMap);
|
|
}
|
|
}
|
|
|
|
if (actor && actor->GetParent()) {
|
|
actor->GetParent()->RemoveChild(actor);
|
|
}
|
|
|
|
AddChild(mapIt->map);
|
|
cameraController_.SetMap(mapIt->map.Get());
|
|
cameraController_.SetTarget(actor.Get());
|
|
cameraController_.SnapToDefaultFocus();
|
|
|
|
if (actor) {
|
|
cameraController_.SetDebugEnabled(false);
|
|
if (areaIndex == -2 && sariaRoomPos_.x >= 0.0f && sariaRoomPos_.y >= 0.0f) {
|
|
Vec2 spawnPos = RoundWorldPoint(sariaRoomPos_);
|
|
if (auto* character = dynamic_cast<CharacterObject*>(actor.Get())) {
|
|
character->SetCharacterPosition(spawnPos);
|
|
} else {
|
|
actor->SetPosition(spawnPos);
|
|
}
|
|
}
|
|
mapIt->map->AddObject(actor);
|
|
cameraController_.SetFocus(actor->GetPosition());
|
|
} else {
|
|
cameraController_.SetDebugEnabled(true);
|
|
}
|
|
|
|
mapIt->map->Enter();
|
|
|
|
curMapIndex_ = mapIt->areaId;
|
|
}
|
|
|
|
void GameTown::Update(float deltaTime) {
|
|
Actor::Update(deltaTime);
|
|
cameraController_.Update(deltaTime);
|
|
}
|
|
|
|
} // namespace frostbite2D
|