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 > Mouse operations

Mouse operations

In this section, we will examine the program that allows the texture color to be changed with color modulation when the mouse is hovered over a texture created from a .png image file and loaded into the main window, the texture color to be changed with color modulation, the texture to be moved with the mouse, whether the mouse is inside the texture and the position of the left button.

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

  1. At the beginning of the program, the global variable shown below is first defined:
    • float x, y: Mouse coordinate variables
    • bool mouse_in: Mouse texture control variable
    • bool lb_down: Mouse left button state variable
    • SDL_Rect rect_texture: Texture rectangle frame variable
  2. The init_vars() function initializes global variables.
  3. In the load_img() function, an image is loaded into the texture variable with the IMG_LoadTexture() function.
  4. In the process_event() function, when the mouse movement and click are performed,
    • The coordinates of the mouse are taken with the SDL_GetMouseState() function and assigned to the x and y variables.
    • The event.motion.x and event.motion.y values ​​are assigned to the mouse_pos variable.
    • The SDL_PointInRect() function checks whether the mouse is inside the texture frame.
    • If it is inside the texture frame,
      • The mouse_in variable is set to true.
      • With the SDL_SetCursor() function mouse pointer is set to hand.
      • Action is performed according to the mouse event:
        • If the event is SDL_EVENT_MOUSE_MOTION and the left mouse button is pressed (lb_down is true), if the difference between the x value of the mouse and the x value when the left mouse button is pressed is greater than or equal to 0 and less than or equal to the difference between the main window width and the texture width, if the difference between the y value of the mouse and the y value when the left mouse button is pressed is greater than or equal to 0 and less than or equal to the difference between the main window height and the texture height, the x and y values ​​of the texture frame take the difference between the x and y values ​​when the mouse and the left mouse button are pressed.
        • If the event is SDL_EVENT_MOUSE_BUTTON_DOWN and the left mouse button is not pressed, the lb_down variable takes the value true. The x and y values ​​of the coor_drag_start variable are the difference between the x and y values ​​of the mouse and texture frame variables.
        • If the event is SDL_EVENT_MOUSE_BUTTON_UP and the left mouse button is pressed, the lb_down variable is false.
    • Otherwise,
      • The mouse_in variable is false.
      • The mouse pointer is set to the system default pointer with the SDL_SetCursor() function.
  5. In the draw_screen() function,
    • The SDL_SetTextureColorMod() function sets the texture color mode according to the mouse_in variable value.
    • The SDL_RenderTexture() function sets the texture to the main copy to window.
    • Mouse coordinates, whether the mouse is in the texture or not and left click status are shown in the main window bar.

main.c file content will be as follows:


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

// Window width and height
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480

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

float x, y;                    // Mouse coordinates
bool mouse_in;                 // Mouse in texture control variable
bool lb_down;                  // Mouse left button state variable
SDL_Rect rect_texture;         // Texture rectangle variable

// Function prototypes
int init_window(void);         // Create window and renderer
void init_vars(void);          // Initialize variables
void load_img(void);           // Load image to texture
void process_event(void);      // Process events
void update_screen();          // Update values
void draw_screen(void);        // Draw screen
void destroy_window(void);     // Destroy window

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

    // Initialize variables
    init_vars();

    // Load .png file to texture
    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)
    }

    // 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", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
       return false;
    }

    return true;
}

// Initialization function that runs only once at the beginning of the program
void init_vars(void)
{
    mouse_in = false;
    lb_down = false;
    rect_texture.x = (WINDOW_WIDTH-300)/2;
    rect_texture.y = (WINDOW_HEIGHT-240)/2;
    rect_texture.w = 300;
    rect_texture.h = 240;
}

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

	if(texture == 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;
    SDL_Point coor_drag_start;

    // Creating a loop to process user inputs
    while (SDL_PollEvent(&event)) {
       switch (event.type) {
          // Fare işlemi
          case SDL_EVENT_MOUSE_MOTION:
          case SDL_EVENT_MOUSE_BUTTON_DOWN:
          case SDL_EVENT_MOUSE_BUTTON_UP:
          {
               SDL_GetMouseState(&x, &y);
               SDL_Point mouse_pos = { event.motion.x, event.motion.y };

               // Checking whether the mouse is inside the texture.
               if(SDL_PointInRect(&mouse_pos, &rect_texture)) {
                  mouse_in = true;
                  SDL_SetCursor(SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_POINTER));

                  switch(event.type) {
                     case SDL_EVENT_MOUSE_MOTION:
                          if(lb_down) {
                             if((mouse_pos.x-coor_drag_start.x)>=0 && (mouse_pos.x-coor_drag_start.x)<=(WINDOW_WIDTH-300) &&
                                (mouse_pos.y-coor_drag_start.y)>=0 && (mouse_pos.y-coor_drag_start.y)<=(WINDOW_HEIGHT-240)) {
                                rect_texture.x = mouse_pos.x - coor_drag_start.x;
                                rect_texture.y = mouse_pos.y - coor_drag_start.y;
                             }
                          }
                          break;
                     case SDL_EVENT_MOUSE_BUTTON_DOWN:
                          if(!lb_down && event.button.button==SDL_BUTTON_LEFT) {
                             lb_down = true;
                             coor_drag_start.x = mouse_pos.x - rect_texture.x;
                             coor_drag_start.y = mouse_pos.y - rect_texture.y;
                          }
                          break;
                     case SDL_EVENT_MOUSE_BUTTON_UP:
                          if(lb_down && event.button.button==SDL_BUTTON_LEFT) {
                             lb_down = false;
                          }
                          break;
                  }
               }
               else {
                  mouse_in = false;
                  SDL_SetCursor(SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_DEFAULT));
               }
          }
          break;

          case SDL_EVENT_QUIT: // Logout action by the user (x button at the top right of the window)
               is_running = false; // Terminates the execution of the program main loop.
               break;

          case SDL_EVENT_KEY_DOWN: // Key pressed.
               if(event.key.key==SDLK_ESCAPE) {
                 is_running = false;
               }
               break;
       }
    }
}

// Updates objects in the main window
void update_screen(void)
{

}

// 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 frect_dst = { (float) rect_texture.x, (float) rect_texture.y, 300, 240 };
    if(mouse_in) {
       SDL_SetTextureColorMod(texture, 240, 170, 0);
    }
    else {
       SDL_SetTextureColorMod(texture, 255, 255, 255);
    }

	SDL_RenderTexture(renderer, texture, NULL, &frect_dst);

    // Loading all objects drawn one by one to the back buffer to the front buffer at once and loading them onto the screen
    // This process prevents each drawn object from being displayed on the screen one by one.
    SDL_RenderPresent(renderer); // Update on screen all operations performed since the previous call

    char cdizi[100];
    sprintf(cdizi, "SDL3 window - Mouse: x: %.2f y: %.2f %s Left button: %s", 
	                x, y, mouse_in ? "in" : "out", lb_down ? "Down" : "Up");
    SDL_SetWindowTitle(window, cdizi);
}

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