Preserving aspect ratio in fullscreen mode is crucial for maintaining the visual integrity of your game across different screen sizes. Here's a comprehensive approach to handle this in SDL2:
First, determine the aspect ratio of your game's native resolution:
const int GAME_WIDTH = 1280;
const int GAME_HEIGHT = 720;
const float GAME_ASPECT_RATIO = GAME_WIDTH /
static_cast<float>(GAME_HEIGHT);
Create a borderless fullscreen window that covers the entire screen:
SDL_Window* window = SDL_CreateWindow(
"Fullscreen Game", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, 0, 0,
SDL_WINDOW_FULLSCREEN_DESKTOP);
Determine the scaling factors to fit the game resolution into the screen while preserving aspect ratio:
int screenWidth, screenHeight;
SDL_GetWindowSize(window, &screenWidth,
&screenHeight);
float scaleX = screenWidth / static_cast<float>(
GAME_WIDTH);
float scaleY = screenHeight / static_cast<float>
(GAME_HEIGHT);
float scale = std::min(scaleX, scaleY);
int scaledWidth = static_cast<int>(GAME_WIDTH *
scale);
int scaledHeight = static_cast<int>(GAME_HEIGHT
* scale);
Determine the size and position of black bars to maintain aspect ratio:
int xOffset = (screenWidth - scaledWidth) / 2;
int yOffset = (screenHeight - scaledHeight) / 2;
SDL_Rect gameViewport = {
xOffset, yOffset, scaledWidth, scaledHeight};
Create a renderer and set the viewport:
SDL_Renderer* renderer =
SDL_CreateRenderer(window, -1,
SDL_RENDERER_ACCELERATED);
SDL_RenderSetViewport(renderer, &gameViewport);
// Clear the entire screen (including
// letterbox/pillarbox areas)
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear (renderer);
Render your game content within the viewport:
void RenderGame(SDL_Renderer* renderer) {
// Clear only the game area
SDL_SetRenderDrawColor(renderer, 50, 50, 50,
255);
SDL_Rect fullViewport = {
0, 0, GAME_WIDTH, GAME_HEIGHT};
SDL_RenderFillRect(renderer, &fullViewport);
// Render game content here
SDL_SetRenderDrawColor(renderer, 255, 0, 0,
255);
SDL_Rect rect = {100, 100, 200, 200};
SDL_RenderFillRect(renderer, &rect);
SDL_RenderPresent(renderer);
}
Recalculate the viewport when the window is resized:
void HandleWindowResize(SDL_Window* window,
SDL_Renderer*
renderer) {
int screenWidth, screenHeight;
SDL_GetWindowSize(window, &screenWidth,
&screenHeight);
float scaleX = screenWidth / static_cast<
float>(GAME_WIDTH);
float scaleY = screenHeight / static_cast<
float>(GAME_HEIGHT);
float scale = std::min(scaleX, scaleY);
int scaledWidth = static_cast<int>(GAME_WIDTH
* scale);
int scaledHeight = static_cast<int>(
GAME_HEIGHT * scale);
int xOffset = (screenWidth - scaledWidth) / 2;
int yOffset = (screenHeight - scaledHeight) /
2;
SDL_Rect gameViewport = {
xOffset, yOffset, scaledWidth,
scaledHeight};
SDL_RenderSetViewport(renderer,
&gameViewport);
}
// In your event loop:
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_WINDOWEVENT &&
event.window.event ==
SDL_WINDOWEVENT_RESIZED) {
HandleWindowResize(window, renderer);
}
// Handle other events...
}
By implementing this approach, your game will maintain its aspect ratio in fullscreen mode across different screen sizes. The game content will be scaled to fit the screen as large as possible while preserving its original proportions, and black bars (letterboxing or pillarboxing) will be added as needed to fill the remaining space.
This method ensures that your game looks consistent and visually appealing regardless of the display's aspect ratio, providing a professional fullscreen experience for your players.
Answers to questions are automatically generated and may not have been reviewed.
Learn techniques for scaling images and working with aspect ratios