mirror of
https://github.com/zhenyan121/SporeBG-Conid.git
synced 2026-04-10 06:14:08 +08:00
Let UI render on the physical screen rather than the logical screen
This commit is contained in:
@@ -30,7 +30,7 @@ bool GameApplication::initialize() {
|
||||
// 字体管理
|
||||
m_fontManager = std::make_unique<FontManager>();
|
||||
// 文字渲染
|
||||
m_textRenderer = std::make_unique<TextRenderer>(m_windowManager->GetRenderer(), m_fontManager.get());
|
||||
m_textRenderer = std::make_unique<TextRenderer>(m_windowManager->GetRenderer(), m_fontManager.get(), m_windowManager->getViewport());
|
||||
|
||||
m_uiRenderer = std:: make_unique<UIRenderer>(m_windowManager->GetRenderer(), m_textRenderer.get());
|
||||
|
||||
@@ -54,12 +54,27 @@ SDL_AppResult GameApplication::handleInputEvent(SDL_Event* event) {
|
||||
}
|
||||
m_sceneManager->handleMousePosition(input.mouseCurrentPosition);
|
||||
m_windowManager->setFullscreen(input.isFullscreen);
|
||||
// 改变窗口时清理旧的缓存
|
||||
if (event->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED) {
|
||||
m_textRenderer->clearCache();
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
void GameApplication::run() {
|
||||
m_windowManager->Clear();
|
||||
|
||||
m_sceneManager->updateCurrent();
|
||||
m_sceneManager->renderCurrent();
|
||||
|
||||
m_windowManager->Clear();
|
||||
m_windowManager->beginWorld();
|
||||
m_sceneManager->renderWorld();
|
||||
m_windowManager->endWorld();
|
||||
|
||||
m_windowManager->beginUI();
|
||||
m_sceneManager->renderUI();
|
||||
m_windowManager->endUI();
|
||||
|
||||
m_windowManager->Present();
|
||||
}
|
||||
@@ -21,7 +21,7 @@ private:
|
||||
std::unique_ptr<TextRenderer> m_textRenderer;
|
||||
std::unique_ptr<UIRenderer> m_uiRenderer;
|
||||
|
||||
GameConfig m_config;
|
||||
WindowConfig m_config;
|
||||
|
||||
public:
|
||||
GameApplication();
|
||||
|
||||
@@ -10,14 +10,14 @@ WindowManager::~WindowManager() {
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
bool WindowManager::Initialize(GameConfig& config) {
|
||||
m_logicalWidth = config.logicalWidth;
|
||||
m_logicalHeight = config.logicalHeight;
|
||||
bool WindowManager::Initialize(WindowConfig& config) {
|
||||
m_viewport.logicalWidth = config.logicalWidth;
|
||||
m_viewport.logicalHeight = config.logicalHeight;
|
||||
// 创建窗口(支持高DPI和横屏)[3,4](@ref)
|
||||
m_window = SDL_CreateWindow(
|
||||
"孢子棋", // 窗口标题,显示在标题栏上
|
||||
m_logicalWidth, // 窗口的逻辑宽度(例如 800),用于统一布局,不受屏幕 DPI 影响
|
||||
m_logicalHeight, // 窗口的逻辑高度(例如 600)
|
||||
m_viewport.logicalWidth, // 窗口的逻辑宽度(例如 800),用于统一布局,不受屏幕 DPI 影响
|
||||
m_viewport.logicalHeight, // 窗口的逻辑高度(例如 600)
|
||||
SDL_WINDOW_HIGH_PIXEL_DENSITY | // 启用高像素密度支持(HiDPI/Retina),确保在高分屏上画面清晰
|
||||
SDL_WINDOW_RESIZABLE // 允许用户调整窗口大小(可拉伸)
|
||||
);
|
||||
@@ -52,8 +52,8 @@ bool WindowManager::Initialize(GameConfig& config) {
|
||||
m_renderer,
|
||||
SDL_PIXELFORMAT_RGBA8888,
|
||||
SDL_TEXTUREACCESS_TARGET,
|
||||
m_logicalWidth,
|
||||
m_logicalHeight
|
||||
m_viewport.logicalWidth,
|
||||
m_viewport.logicalHeight
|
||||
);
|
||||
// 设置纹理缩放模式为最近邻
|
||||
SDL_SetTextureScaleMode(m_logicalTexture, SDL_SCALEMODE_NEAREST);
|
||||
@@ -67,13 +67,12 @@ void WindowManager::Shutdown() {
|
||||
}
|
||||
|
||||
void WindowManager::Clear() {
|
||||
// 1. 设置渲染目标为逻辑纹理
|
||||
SDL_SetRenderTarget(m_renderer, m_logicalTexture);
|
||||
|
||||
// 设置画笔颜色
|
||||
SDL_SetRenderDrawColor(m_renderer, 255, 255, 255, 255);
|
||||
// 使用画笔颜色填充整个逻辑画布
|
||||
// 使用画笔颜色填充整个画布
|
||||
SDL_RenderClear(m_renderer);
|
||||
|
||||
onWindowResize();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -89,21 +88,40 @@ void WindowManager::Clear() {
|
||||
|
||||
void WindowManager::Present() {
|
||||
|
||||
// 4. 切回默认渲染目标(窗口)
|
||||
SDL_SetRenderTarget(m_renderer, nullptr);
|
||||
SDL_RenderClear(m_renderer); // 清的是窗口(黑边
|
||||
SDL_FRect dstRect;
|
||||
calculateDstRect(dstRect);
|
||||
|
||||
|
||||
//SDL_FRect dstRect;
|
||||
//calculateDstRect(dstRect);
|
||||
|
||||
SDL_RenderTexture (
|
||||
m_renderer,
|
||||
m_logicalTexture, // 源:你已经画好的逻辑画布
|
||||
nullptr, // srcRect:源区域(nullptr = 整张)
|
||||
&dstRect // dstRect:贴到哪里 & 贴多大
|
||||
&m_viewport.dst // dstRect:贴到哪里 & 贴多大
|
||||
);
|
||||
SDL_RenderPresent(m_renderer);
|
||||
}
|
||||
|
||||
|
||||
void WindowManager::beginWorld() {
|
||||
// 设置渲染目标为逻辑纹理
|
||||
SDL_SetRenderTarget(m_renderer, m_logicalTexture);
|
||||
}
|
||||
|
||||
void WindowManager::endWorld() {
|
||||
|
||||
}
|
||||
|
||||
void WindowManager::beginUI() {
|
||||
// 设置渲染目标为窗口
|
||||
SDL_SetRenderTarget(m_renderer, nullptr);
|
||||
}
|
||||
|
||||
void WindowManager::endUI() {
|
||||
// 恢复渲染目标为默认(窗口)
|
||||
SDL_SetRenderTarget(m_renderer, nullptr);
|
||||
}
|
||||
|
||||
SDL_Renderer* WindowManager::GetRenderer() {
|
||||
return m_renderer;
|
||||
}
|
||||
@@ -121,7 +139,7 @@ bool WindowManager::setFullscreen(bool isFullscreen) {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
void WindowManager::calculateDstRect(SDL_FRect& dstRect) {
|
||||
// 获取窗口的实际尺寸(像素)
|
||||
SDL_GetWindowSize(m_window, &m_windowWidth, &m_windowHeight);
|
||||
@@ -136,4 +154,59 @@ void WindowManager::calculateDstRect(SDL_FRect& dstRect) {
|
||||
// 居中显示
|
||||
dstRect.x = static_cast<float>((m_windowWidth - dstRect.w) / 2);
|
||||
dstRect.y = static_cast<float>((m_windowHeight - dstRect.h) / 2);
|
||||
}
|
||||
}
|
||||
*/
|
||||
void WindowManager::onWindowResize() {
|
||||
|
||||
// =================================================
|
||||
// 1. 查询窗口的真实像素尺寸
|
||||
// 注意:这是“窗口坐标空间”的大小
|
||||
// =================================================
|
||||
SDL_GetWindowSize(
|
||||
m_window,
|
||||
&m_viewport.windowWidth,
|
||||
&m_viewport.windowHeight
|
||||
);
|
||||
|
||||
// =================================================
|
||||
// 2. 计算 X / Y 方向最多能放大多少倍
|
||||
// 使用整数除法,保证整数缩放(像素不模糊)
|
||||
// =================================================
|
||||
int scaleX = m_viewport.windowWidth / m_viewport.logicalWidth;
|
||||
int scaleY = m_viewport.windowHeight / m_viewport.logicalHeight;
|
||||
|
||||
// =================================================
|
||||
// 3. 取较小值,保证逻辑画面完整显示
|
||||
// 同时确保最小为 1(窗口再小也能画)
|
||||
// =================================================
|
||||
m_viewport.scale = std::max(1, std::min(scaleX, scaleY));
|
||||
|
||||
// =================================================
|
||||
// 4. 计算逻辑画面放大后的实际尺寸
|
||||
// =================================================
|
||||
m_viewport.dst.w =
|
||||
static_cast<float>(m_viewport.logicalWidth *
|
||||
m_viewport.scale);
|
||||
|
||||
m_viewport.dst.h =
|
||||
static_cast<float>(m_viewport.logicalHeight *
|
||||
m_viewport.scale);
|
||||
|
||||
// =================================================
|
||||
// 5. 计算居中偏移(letterbox / pillarbox)
|
||||
// =================================================
|
||||
m_viewport.dst.x =
|
||||
(m_viewport.windowWidth - m_viewport.dst.w) * 0.5f;
|
||||
|
||||
m_viewport.dst.y =
|
||||
(m_viewport.windowHeight - m_viewport.dst.h) * 0.5f;
|
||||
|
||||
// 到这里为止:
|
||||
// - scale 可供所有系统使用
|
||||
// - dst 是渲染 & 输入转换的唯一依据
|
||||
// - windowSize 不需要再到处 SDL_GetWindowSize
|
||||
}
|
||||
|
||||
Viewport const& WindowManager::getViewport() const {
|
||||
return m_viewport;
|
||||
}
|
||||
|
||||
@@ -6,16 +6,26 @@ public:
|
||||
WindowManager();
|
||||
~WindowManager();
|
||||
// 初始化
|
||||
bool Initialize(GameConfig& config);
|
||||
bool Initialize(WindowConfig& config);
|
||||
//关闭
|
||||
void Shutdown();
|
||||
//清理上一帧窗口
|
||||
|
||||
void beginWorld();
|
||||
|
||||
void endWorld();
|
||||
|
||||
void beginUI();
|
||||
|
||||
void endUI();
|
||||
|
||||
void Clear();
|
||||
//呈现窗口
|
||||
void Present();
|
||||
bool setFullscreen(bool isFullscreen);
|
||||
|
||||
|
||||
const Viewport& getViewport() const;
|
||||
|
||||
SDL_Renderer* GetRenderer();
|
||||
SDL_Window* GetWindow();
|
||||
|
||||
@@ -23,13 +33,15 @@ public:
|
||||
private:
|
||||
SDL_Window* m_window;
|
||||
SDL_Renderer* m_renderer;
|
||||
int m_logicalWidth;
|
||||
int m_logicalHeight;
|
||||
int m_windowWidth;
|
||||
int m_windowHeight;
|
||||
Viewport m_viewport;
|
||||
//int m_logicalWidth;
|
||||
//int m_logicalHeight;
|
||||
//int m_windowWidth;
|
||||
//int m_windowHeight;
|
||||
bool m_isFullscreen = false;
|
||||
SDL_Texture* m_logicalTexture = nullptr;
|
||||
// 计算缩放后的目标矩形
|
||||
void calculateDstRect(SDL_FRect& dstRect);
|
||||
//void calculateDstRect(SDL_FRect& dstRect);
|
||||
void onWindowResize();
|
||||
|
||||
};
|
||||
Reference in New Issue
Block a user