Refactored step 1: Core Architecture Setup

This commit is contained in:
2025-08-17 10:22:21 +02:00
parent 2e4a981254
commit 36f849ba36
9 changed files with 952 additions and 53 deletions

View File

@ -0,0 +1,252 @@
#include "RenderManager.h"
#include <SDL3/SDL.h>
#include <algorithm>
RenderManager::RenderManager() = default;
RenderManager::~RenderManager() {
if (m_initialized) {
shutdown();
}
}
bool RenderManager::initialize(int width, int height, const std::string& title) {
if (m_initialized) {
SDL_LogWarn(SDL_LOG_CATEGORY_RENDER, "RenderManager already initialized");
return true;
}
SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "Initializing RenderManager (%dx%d)", width, height);
// Create window
m_window = SDL_CreateWindow(
title.c_str(),
width, height,
SDL_WINDOW_RESIZABLE
);
if (!m_window) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Failed to create window: %s", SDL_GetError());
return false;
}
// Create renderer
m_renderer = SDL_CreateRenderer(m_window, nullptr);
if (!m_renderer) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Failed to create renderer: %s", SDL_GetError());
SDL_DestroyWindow(m_window);
m_window = nullptr;
return false;
}
// Enable VSync
SDL_SetRenderVSync(m_renderer, 1);
// Store window dimensions
m_windowWidth = width;
m_windowHeight = height;
m_logicalWidth = width;
m_logicalHeight = height;
// Set initial logical size
setLogicalSize(width, height);
m_initialized = true;
SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "RenderManager initialized successfully");
return true;
}
void RenderManager::shutdown() {
if (!m_initialized) {
return;
}
SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "Shutting down RenderManager");
if (m_renderer) {
SDL_DestroyRenderer(m_renderer);
m_renderer = nullptr;
}
if (m_window) {
SDL_DestroyWindow(m_window);
m_window = nullptr;
}
m_initialized = false;
SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "RenderManager shutdown complete");
}
void RenderManager::beginFrame() {
if (!m_initialized || !m_renderer) {
return;
}
// Clear the screen
clear(12, 12, 16, 255); // Dark background similar to original
}
void RenderManager::endFrame() {
if (!m_initialized || !m_renderer) {
return;
}
SDL_RenderPresent(m_renderer);
}
void RenderManager::setLogicalSize(int width, int height) {
if (!m_initialized || !m_renderer) {
return;
}
m_logicalWidth = width;
m_logicalHeight = height;
updateLogicalScale();
}
void RenderManager::setViewport(int x, int y, int width, int height) {
if (!m_initialized || !m_renderer) {
return;
}
SDL_Rect viewport = { x, y, width, height };
SDL_SetRenderViewport(m_renderer, &viewport);
}
void RenderManager::setScale(float scaleX, float scaleY) {
if (!m_initialized || !m_renderer) {
return;
}
m_scaleX = scaleX;
m_scaleY = scaleY;
SDL_SetRenderScale(m_renderer, scaleX, scaleY);
}
void RenderManager::resetViewport() {
if (!m_initialized || !m_renderer) {
return;
}
SDL_SetRenderViewport(m_renderer, nullptr);
updateLogicalScale();
}
void RenderManager::clear(Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
if (!m_initialized || !m_renderer) {
return;
}
SDL_SetRenderDrawColor(m_renderer, r, g, b, a);
SDL_RenderClear(m_renderer);
}
void RenderManager::renderTexture(SDL_Texture* texture, const SDL_FRect* src, const SDL_FRect* dst) {
if (!m_initialized || !m_renderer || !texture) {
return;
}
SDL_RenderTexture(m_renderer, texture, src, dst);
}
void RenderManager::renderTexture(SDL_Texture* texture, float x, float y) {
if (!texture) {
return;
}
float w, h;
SDL_GetTextureSize(texture, &w, &h);
SDL_FRect dst = { x, y, w, h };
renderTexture(texture, nullptr, &dst);
}
void RenderManager::renderTexture(SDL_Texture* texture, float x, float y, float w, float h) {
if (!texture) {
return;
}
SDL_FRect dst = { x, y, w, h };
renderTexture(texture, nullptr, &dst);
}
void RenderManager::renderRect(const SDL_FRect& rect, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
if (!m_initialized || !m_renderer) {
return;
}
SDL_SetRenderDrawColor(m_renderer, r, g, b, a);
SDL_RenderFillRect(m_renderer, &rect);
}
void RenderManager::renderLine(float x1, float y1, float x2, float y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
if (!m_initialized || !m_renderer) {
return;
}
SDL_SetRenderDrawColor(m_renderer, r, g, b, a);
SDL_RenderLine(m_renderer, x1, y1, x2, y2);
}
void RenderManager::renderPoint(float x, float y, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
if (!m_initialized || !m_renderer) {
return;
}
SDL_SetRenderDrawColor(m_renderer, r, g, b, a);
SDL_RenderPoint(m_renderer, x, y);
}
void RenderManager::handleWindowResize(int newWidth, int newHeight) {
if (!m_initialized) {
return;
}
SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "Window resized to %dx%d", newWidth, newHeight);
m_windowWidth = newWidth;
m_windowHeight = newHeight;
updateLogicalScale();
}
void RenderManager::setFullscreen(bool fullscreen) {
if (!m_initialized || !m_window) {
return;
}
if (m_isFullscreen == fullscreen) {
return;
}
SDL_SetWindowFullscreen(m_window, fullscreen ? SDL_WINDOW_FULLSCREEN : 0);
m_isFullscreen = fullscreen;
// Update window size after fullscreen change
SDL_GetWindowSize(m_window, &m_windowWidth, &m_windowHeight);
updateLogicalScale();
}
void RenderManager::getWindowSize(int& width, int& height) const {
width = m_windowWidth;
height = m_windowHeight;
}
void RenderManager::updateLogicalScale() {
if (!m_initialized || !m_renderer) {
return;
}
// Calculate scale to fit logical size into window
float scaleX = static_cast<float>(m_windowWidth) / static_cast<float>(m_logicalWidth);
float scaleY = static_cast<float>(m_windowHeight) / static_cast<float>(m_logicalHeight);
// Use uniform scaling to maintain aspect ratio
float scale = std::min(scaleX, scaleY);
if (scale <= 0.0f) {
scale = 1.0f;
}
setScale(scale, scale);
// Set viewport to fill the entire window
setViewport(0, 0, m_windowWidth, m_windowHeight);
}

View File

@ -0,0 +1,79 @@
#pragma once
#include <SDL3/SDL.h>
#include <string>
/**
* RenderManager - Abstracts SDL rendering functionality
*
* Responsibilities:
* - Manage SDL_Window and SDL_Renderer lifecycle
* - Provide high-level rendering interface
* - Handle viewport and scaling logic
* - Abstract SDL-specific details from game code
*/
class RenderManager {
public:
RenderManager();
~RenderManager();
// Initialization and cleanup
bool initialize(int width, int height, const std::string& title);
void shutdown();
// Frame management
void beginFrame();
void endFrame();
// Viewport and scaling
void setLogicalSize(int width, int height);
void setViewport(int x, int y, int width, int height);
void setScale(float scaleX, float scaleY);
void resetViewport();
// Basic rendering operations
void clear(Uint8 r = 0, Uint8 g = 0, Uint8 b = 0, Uint8 a = 255);
// Texture rendering
void renderTexture(SDL_Texture* texture, const SDL_FRect* src, const SDL_FRect* dst);
void renderTexture(SDL_Texture* texture, float x, float y);
void renderTexture(SDL_Texture* texture, float x, float y, float w, float h);
// Primitive rendering
void renderRect(const SDL_FRect& rect, Uint8 r, Uint8 g, Uint8 b, Uint8 a = 255);
void renderLine(float x1, float y1, float x2, float y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a = 255);
void renderPoint(float x, float y, Uint8 r, Uint8 g, Uint8 b, Uint8 a = 255);
// Window management
void handleWindowResize(int newWidth, int newHeight);
void setFullscreen(bool fullscreen);
void getWindowSize(int& width, int& height) const;
// Direct access to SDL objects (temporary, will be removed later)
SDL_Renderer* getSDLRenderer() const { return m_renderer; }
SDL_Window* getSDLWindow() const { return m_window; }
// State queries
bool isInitialized() const { return m_initialized; }
bool isFullscreen() const { return m_isFullscreen; }
private:
// SDL objects
SDL_Window* m_window = nullptr;
SDL_Renderer* m_renderer = nullptr;
// Window properties
int m_windowWidth = 0;
int m_windowHeight = 0;
int m_logicalWidth = 0;
int m_logicalHeight = 0;
float m_scaleX = 1.0f;
float m_scaleY = 1.0f;
// State
bool m_initialized = false;
bool m_isFullscreen = false;
// Helper methods
void updateLogicalScale();
};