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 > Gif animation

Gif animation

In this section, we will examine a program that automatically loads the frames of an animation created from a .gif file into the window in order and creates an animation.

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

  1. At the beginning of the program, the following global variables are defined:
    • IMG_Animation* anim: Animation variable
    • Uint32 frame_time: Frame time
    • Uint32 last_time: Active time
    • int current_frame: Active frame
  2. In the load_img() function, With the IMG_LoadAnimation() function, a gif file is loaded and transferred to the variable named anim.
  3. In the init_vars() function,
    • A duration in milliseconds is calculated for a frame and assigned to the frame_time variable.
    • The active time is taken and assigned to the last_variable.
    • The current_frame variable is assigned the value 0.
    • The animation width and height, frame number and time are written to the main window title.
  4. In the update_screen() function,
    • The active time is taken with the SDL_GetTicks() function and assigned to the current_time variable.
    • If the difference between the current_time and last_time variable values ​​is greater than or equal to the frame_time variable value, the remaining value of dividing the current_frame variable value by 1 plus the anim->count value, is assigned to the current_frame variable. The current_time variable value is assigned to the last_time variable.
  5. In the draw_screen() function,
    • A texture is created from the active frame surface with the SDL_CreateTextureFromSurface() function and assigned to the texture_gif variable.
    • The texture_gif value is copied to the main window with the SDL_RenderTexture() function.

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_gif = NULL;   // Gif frame texture
SDL_Renderer *renderer = NULL;     // Renderer variable

IMG_Animation* anim;               // Animation
Uint32 frame_time;                 // Frame time in milliseconds
Uint32 last_time;                  // Current time  
int current_frame;                 // Current frame  

// 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();

    // Load .gif file
    load_img();

    // Initialize variables
    init_vars();

    // 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;
}

// Load image
void load_img(void)
{
	anim = IMG_LoadAnimation("fire.gif");
}

// Initialization function that runs only once at the beginning of the program
void init_vars(void)
{
    frame_time = 1000 / anim->count; // Frame time in milliseconds
    last_time = SDL_GetTicks();      // Current time
    current_frame = 0;               // Current frame

    char cdizi[100];
    sprintf(cdizi, "Animation - Width: %d Height: %d Number of frames: %d Frame time: %d",
                    anim->w, anim->h, anim->count, frame_time);
    SDL_SetWindowTitle(window, cdizi);
}

// 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) {
          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.
               switch(event.key.key) {
                  case SDLK_ESCAPE: is_running = false; break;
               }
               break;
       }
    }
}
// Updates objects in the main window
void update_screen(void)
{
    // Update current frame
    Uint32 current_time = SDL_GetTicks();
    if(current_time - last_time >= frame_time) {
       current_frame = (current_frame + 1) % anim->count;
       last_time = current_time;
    }
}

// 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.

    // Render current frame
    SDL_FRect frect_src = {0, 0, anim->frames[current_frame]->w, anim->frames[current_frame]->h};
    SDL_FRect frect_dst = { (WINDOW_WIDTH - frect_src.w) / 2, (WINDOW_HEIGHT - frect_src.h) / 2, frect_src.w, frect_src.h};

    // Create texture from gif frame surface
    texture_gif = SDL_CreateTextureFromSurface(renderer, anim->frames[current_frame]);

    SDL_RenderTexture(renderer, texture_gif, &frect_src, &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
}

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