pythonmacossdl-3

Square distortion during window resizing problem


I tried to make a square that maintains its size and aspect ratio during window resizing using SDL3 and SDL_SetRenderLogicalPresentation() with the SDL_LOGICAL_PRESENTATION_LETTERBOX mode:

import sdl3

# Function to draw a square
def draw_square(renderer, x, y, size):
    sdl3.SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255)  # White color
    rect = sdl3.SDL_FRect(x=x, y=y, w=size, h=size)
    sdl3.SDL_RenderFillRect(renderer, rect)

# Initialize SDL3
if sdl3.SDL_Init(sdl3.SDL_INIT_VIDEO) < 0:
    print(f"SDL initialization error: {sdl3.SDL_GetError().decode()}")
    exit(1)

# Create window
window = sdl3.SDL_CreateWindow(b"Hello World", 640, 480, sdl3.SDL_WINDOW_RESIZABLE)
if not window:
    print(f"Window creation error: {sdl3.SDL_GetError().decode()}")
    exit(1)

# Create renderer
renderer = sdl3.SDL_CreateRenderer(window, b"metal")
if not renderer:
    print(f"Renderer creation error: {sdl3.SDL_GetError().decode()}")
    exit(1)

# Set logical rendering size
logical_width, logical_height = 640, 480
sdl3.SDL_SetRenderLogicalPresentation(renderer, logical_width, logical_height, sdl3.SDL_LOGICAL_PRESENTATION_LETTERBOX)

# Parameters for positioning the square
square_size = 100  # Fixed square size
square_x = (logical_width - square_size) / 2  # Center horizontally
square_y = (logical_height - square_size) / 2  # Center vertically

running = True
while running:
    # Event handling
    event = sdl3.SDL_Event()
    while sdl3.SDL_PollEvent(event):
        if event.type == sdl3.SDL_EVENT_QUIT:
            running = False

    # Rendering
    sdl3.SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255)  # Black background
    sdl3.SDL_RenderClear(renderer)
    # Draw square with fixed size and centered position
    draw_square(renderer, square_x, square_y, square_size)
    sdl3.SDL_RenderPresent(renderer)

# Cleanup
sdl3.SDL_DestroyRenderer(renderer)
sdl3.SDL_DestroyWindow(window)
sdl3.SDL_Quit()

Currently, the square only resets to its original width and height after I release the mouse button (when resizing ends). During the resizing process itself, the square gets stretched or squashed — it deforms.

Is this the expected behavior of SDL_SetRenderLogicalPresentation? How can I make the square that never deforms at all, no matter how the window is resized? Are there workarounds or best practices for this? (Mac user)

For example, would converting the square into a texture or something similar help keep its aspect ratio stable during resizing?

My code written in Python but feel free to answer in any programming language, main goal is to get the way how to do window resizing without distortion.


Solution

  • you should use the SDL Main Callbacks API it can be done from python

    import os, ctypes, time
    
    os.environ["SDL_MAIN_USE_CALLBACKS"] = "1"
    
    import sdl3
    
    renderer = ctypes.POINTER(sdl3.SDL_Renderer)()
    window = ctypes.POINTER(sdl3.SDL_Window)()
    
    
    @sdl3.SDL_AppInit_func
    def SDL_AppInit(appstate, argc, argv):
        if not sdl3.SDL_Init(sdl3.SDL_INIT_VIDEO):
            sdl3.SDL_Log("Couldn't initialize SDL: %s", sdl3.SDL_GetError())
            return sdl3.SDL_APP_FAILURE
    
        if not sdl3.SDL_CreateWindowAndRenderer("Hello, World!".encode(), 640, 480, sdl3.SDL_WINDOW_RESIZABLE, window, renderer):
            sdl3.SDL_Log("Couldn't create window/renderer: %s", sdl3.SDL_GetError())
            return sdl3.SDL_APP_FAILURE
    
        sdl3.SDL_SetRenderVSync(renderer, 1)
    
        # Set logical rendering size
        logical_width, logical_height = 640, 480
        sdl3.SDL_SetRenderLogicalPresentation(renderer, logical_width, logical_height,
                                              sdl3.SDL_LOGICAL_PRESENTATION_LETTERBOX)
    
        return sdl3.SDL_APP_CONTINUE
    
    
    @sdl3.SDL_AppEvent_func
    def SDL_AppEvent(appstate, event):
        if sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_QUIT:
            return sdl3.SDL_APP_SUCCESS
    
        return sdl3.SDL_APP_CONTINUE
    
    def draw_square(renderer, x, y, size):
        sdl3.SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255)  # White color
        rect = sdl3.SDL_FRect(x=x, y=y, w=size, h=size)
        sdl3.SDL_RenderFillRect(renderer, rect)
    
    @sdl3.SDL_AppIterate_func
    def SDL_AppIterate(appstate):
        # Rendering
        sdl3.SDL_SetRenderDrawColor(renderer, 120, 0, 0, 255)  # Red background
        sdl3.SDL_RenderClear(renderer)
    
        # Set logical rendering size
        logical_width, logical_height = 640, 480
    
        # Parameters for positioning the square
        square_size = 100  # Fixed square size
        square_x = (logical_width - square_size) / 2  # Center horizontally
        square_y = (logical_height - square_size) / 2  # Center vertically
    
        # Draw square with fixed size and centered position
        draw_square(renderer, square_x, square_y, square_size)
        sdl3.SDL_RenderPresent(renderer)
        return sdl3.SDL_APP_CONTINUE
    
    
    @sdl3.SDL_AppQuit_func
    def SDL_AppQuit(appstate, result):
        ...  # SDL will clean up the window/renderer for us.
    

    you can now resize the window without distorting the box.

    the reason this works is because you give SDL3 your draw function, and SDL3 will call it when it sees the window being resized.