Warning: Undefined array key "HTTP_ACCEPT_LANGUAGE" in /var/www/vhosts/bilgigunlugum.net/httpdocs/index.php on line 43
SDL Game Programming

SDL3 Oyun Programlama sayfalarımız yayında...

Ana sayfa > Oyun programlama > SDL3 programming > Multi-window operations

Multi-window operations

In this section, we will examine the program that resizes and moves the main window with window operations, detects whether the mouse is inside the main window, and switches the main window between full screen and normal view with key operations for two different windows.

When the program runs, the following operations are performed in addition to the basic operations:

  1. At the beginning of the program, the following global variables are first defined:
    • int window_id, window_id2: Window ID
    • int window_width, window_width2: Main window width
    • int window_height, window_height2: Main window height
    • int window_x, window_x2: Main window x coordinate
    • int window_y, window_y2: Main window y coordinate
    • bool mouse_in, mouse_in2: Mouse position variables
    • bool full_screen, full_screen2: Full screen control variables
    • bool window_show, window_show2: Window control variables
  2. In init_window() function, the SDL_INIT_VIDEO value is activated with the SDL_Init() function. The SDL_CreateWindowAndRenderer() function creates two windows and a renderer that can be resized.
  3. In the init_vars() function,
    • Global variables are assigned an initial value.
    • The coordinates of the windows are obtained with the SDL_GetWindowPosition() function and assigned to the window_x, window_y, window_x2 and window_y2 variables.
  4. In load_img() function, a texture is created for the background of each window with the IMG_LoadTexture() function.
  5. In process_event() function,
    • When one of the windows is shown with the SDL_EVENT_WINDOW_SHOWN option, the window_show variable of the relevant window is set to true.
    • When one of the windows is hidden with the SDL_EVENT_WINDOW_HIDDEN option operations, the window_show variable of the relevant window is set to false.
    • With the SDL_EVENT_WINDOW_RESIZED option, when one of the windows is resized, the new dimensions of the relevant window are assigned to the window_width and window_height variables.
    • With the SDL_EVENT_WINDOW_EXPOSED option, the main window can be drawn directly when it is visible and needs to be redrawn.
    • When one of the windows is moved with the SDL_EVENT_WINDOW_MOVED option, the main window coordinates of the relevant window are assigned to the window_x and window_y variables.
    • With the SDL_EVENT_WINDOW_MOUSE_ENTER and SDL_EVENT_WINDOW_MOUSE_LEAVE options, the mouse_in variable value is updated by checking whether the mouse is inside the windows.
    • With the SDL_EVENT_WINDOW_CLOSE_REQUESTED option, when one of the windows is closed, the SDL_HideWindow() function is used to update the relevant window is hidden.
    • With the SDL_EVENT_KEY_DOWN option,
      • When the F key is pressed, the active window is switched between full screen and normal view.
      • When the 1 key is pressed, the 1st window and when the 2 key is pressed, the 2nd window are shown in the foreground with the SDL_ShowWindow() and SDL_RaiseWindow() functions.
  6. In the update_screen() function, the coordinates, width, height of the main window and whether the mouse is inside the main window are written to the main window title.
  7. If the window_show and window_show2 variable values ​​are false, the program ends.
  8. In the draw_screen() function,
    • The background texture value is loaded to the screen with the SDL_RenderTexture() function.
    • Drawings and loadings made with the SDL_RenderPresent() function are displayed on the screen.

The content of the main.c file will be as follows:


#include <stdio.h>
#include <SDL3/SDL.h>
#include <SDL3_image/SDL_image.h>

// Global variables
int is_running = false;                           // Variable that controls the execution of the main loop of the program
SDL_Window *window = NULL, *window2 = NULL;       // Main window variables
SDL_Texture *texture = NULL, *texture2 = NULL;    // Texture variables
SDL_Renderer *renderer = NULL, *renderer2 = NULL; // Renderer variables

int window_id, window_id2;                        // Windows ID
int window_width = 640, window_width2 = 640;      // Window width
int window_height = 480, window_height2 = 480;    // Window height
int window_x, window_x2;                          // Window x coordinate
int window_y, window_y2;                          // Window y coordinate
bool mouse_in, mouse_in2;                         // Mouse position
bool full_screen, full_screen2;                   // Full screen control
bool window_show, window_show2;                   // Show window control

// Function prototypes
int init_window(void);
void init_vars(void);
void load_img(void);
void process_event(void);
void update_screen(void);
void draw_screen(void);
void destroy_window(void);

int main(int argc, char* argv[])
{
    // Create window and renderer
    is_running = init_window();

    // Initialize variables
    init_vars();

    // Load image
    load_img();

    // Main loop
    while (is_running) {
       process_event(); // Processing SDL events (Here keyboard inputs)
       update_screen(); // Updating variables
       draw_screen();   // Drawing objects on the window (Rendering)

	   // Application closed all windows
       if(window_show==false && window_show2==false) {
		  is_running = false;
       }
    }

    // Destroy renderer and SDL window
    destroy_window();

    return 0;
}

// Create window and renderer
int init_window(void)
{
    // Initialize the SDL library.
    if(SDL_Init(SDL_INIT_VIDEO) == false) {
       SDL_Log("SDL init error: %s\n", SDL_GetError());
       return false;
    }

    // Create a window and a 2D rendering context for the window.
    if(!SDL_CreateWindowAndRenderer("SDL3 window - 1", window_width, window_height, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
       return false;
    }

    window_id = SDL_GetWindowID(window);
    window_show = true;

    if(!SDL_CreateWindowAndRenderer("SDL3 window - 2", window_width2, window_height2, SDL_WINDOW_RESIZABLE, &window2, &renderer2)) {
       return false;
    }

    window_id2 = SDL_GetWindowID(window2);
    window_show2 = true;

    return true;
}

// Initialization function that runs only once at the beginning of the program
void init_vars(void)
{
    window_id = -1;
    window_id2 = -1;
    window_x = 0;
    window_x2 = 0;
    window_y = 0;
    window_y2 = 0;
    mouse_in = false;
    mouse_in2 = false;
    full_screen = false;
    full_screen2 = false;

    SDL_GetWindowPosition(window, &window_x, &window_y);
    SDL_GetWindowPosition(window2, &window_x2, &window_y2);

    SDL_SetWindowPosition(window2, window_x2+100, window_y2+100);
}

// Load image
void load_img(void)
{
    // Load image to texture
	texture = IMG_LoadTexture(renderer, "window_bg.png");

	if(texture == NULL) {
       SDL_Log("IMG_LoadTexture error: %s\n", SDL_GetError());
	}

    // Load image to texture
	texture2 = IMG_LoadTexture(renderer2, "window_bg2.png");

	if(texture2 == NULL) {
       SDL_Log("IMG_LoadTexture error: %s\n", SDL_GetError());
	}
}

// Function to control SDL events and process keyboard inputs
void process_event(void)
{
    SDL_Event event;

    // Creating a loop to process user inputs
    while (SDL_PollEvent(&event)) {
        switch (event.type) {
		   // Window appeared
		   case SDL_EVENT_WINDOW_SHOWN:
                if(event.window.windowID == window_id) {
                   window_show = true;
                }
                else if(event.window.windowID == window_id2) {
                   window_show2 = true;
                }
                break;
		   // Window disappeared
		   case SDL_EVENT_WINDOW_HIDDEN:
                if(event.window.windowID == window_id) {
                   window_show = false;
                }
                else if(event.window.windowID == window_id2) {
                   window_show2 = false;
                }
                break;

           // Get new dimensions and repaint on window size change
           case SDL_EVENT_WINDOW_RESIZED:
                if(event.window.windowID == window_id) {
                   window_width = event.window.data1;
                   window_height = event.window.data2;
                   SDL_RenderPresent(renderer);
                }
                else if(event.window.windowID == window_id2) {
                   window_width2 = event.window.data1;
                   window_height2 = event.window.data2;
                   SDL_RenderPresent(renderer2);
                }
                break;
		   // Repaint on exposure
		   case SDL_EVENT_WINDOW_EXPOSED:
                if(event.window.windowID == window_id) {
                   SDL_RenderPresent(renderer);
                }
                else if(event.window.windowID == window_id2) {
                   SDL_RenderPresent(renderer2);
                }
                break;
           case SDL_EVENT_WINDOW_MOVED:
                if(event.window.windowID == window_id) {
                   window_x = event.window.data1;
                   window_y = event.window.data2;
                }
                else if(event.window.windowID == window_id2) {
                   window_x2 = event.window.data1;
                   window_y2 = event.window.data2;
                }
                break;
           case SDL_EVENT_WINDOW_MOUSE_ENTER:
                if(event.window.windowID == window_id) {
                   mouse_in = true;
                }
                else if(event.window.windowID == window_id2) {
                   mouse_in2 = true;
                }
                 break;
           case SDL_EVENT_WINDOW_MOUSE_LEAVE:
                if(event.window.windowID == window_id) {
                   mouse_in = false;
                }
                else if(event.window.windowID == window_id2) {
                   mouse_in2 = false;
                }
                break;

		   // Hide on close
		   case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
                if(event.window.windowID == window_id) {
                   SDL_HideWindow(window);
                }
                else if(event.window.windowID == window_id2) {
                   SDL_HideWindow(window2);
                }
                break;

           case SDL_EVENT_KEY_DOWN: // Key pressed
		        switch (event.key.key) {
                   case SDLK_F:
                        if(event.window.windowID == window_id) {
                           if(full_screen) {
                              SDL_SetWindowFullscreen(window, false);
                              full_screen = false;
                           }
                           else {
                              SDL_SetWindowFullscreen(window, true);
                              full_screen = true;
                           }
                        }
                        else if(event.window.windowID == window_id2) {
                           if(full_screen2) {
                              SDL_SetWindowFullscreen(window2, false);
                              full_screen2 = false;
                           }
                           else {
                              SDL_SetWindowFullscreen(window2, true);
                              full_screen2 = true;
                           }
                        }
                        break;

		           case SDLK_1:
		                if(!window_show) {
		                   SDL_ShowWindow(window);
	                    }
                 	    SDL_RaiseWindow(window);
		                break;
		           case SDLK_2:
		                if(!window_show2) {
		                   SDL_ShowWindow(window2);
	                    }
                 	    SDL_RaiseWindow(window2);
		                break;

                   case SDLK_ESCAPE: is_running = false; break;
                }
                break;
        }
    }
}

void update_screen(void)
{
    char cdizi[100];

    sprintf(cdizi, "Window x: %d y: %d width: %d height: %d mouse: %s",
                    window_x, window_y, window_width, window_height, mouse_in ? "in" : "out");
    SDL_SetWindowTitle(window, cdizi);

    sprintf(cdizi, "Window2 x: %d y: %d width: %d height: %d mouse: %s",
                    window_x2, window_y2, window_width2, window_height2, mouse_in2 ? "in" : "out");
    SDL_SetWindowTitle(window2, cdizi);
}

// Render function used to draw game objects in the main window
void draw_screen(void)
{
    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); // Set the color used for drawing operations.
    SDL_RenderClear(renderer); // Clear the current rendering target with the drawing color.
    SDL_FRect rect_dst = { 0, 0, window_width, window_height };
	SDL_RenderTexture(renderer, texture, NULL, &rect_dst);
    SDL_RenderPresent(renderer); // Update on screen all operations performed since the previous call

    SDL_SetRenderDrawColor(renderer2, 0, 0, 0, 255); // Set the color used for drawing operations.
    SDL_RenderClear(renderer2); // Clear the current rendering target with the drawing color.
    SDL_FRect rect_dst2 = { 0, 0, window_width2, window_height2 };
	SDL_RenderTexture(renderer2, texture2, NULL, &rect_dst2);
    SDL_RenderPresent(renderer2); // Update on screen all operations performed since the previous call
}

// Destroy Renderer and SDL window, exit from SDL3
void destroy_window(void)
{
    SDL_DestroyTexture(texture);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);

    SDL_DestroyTexture(texture2);
    SDL_DestroyRenderer(renderer2);
    SDL_DestroyWindow(window2);

    SDL_Quit();
}