In this section, we will examine a program that starts and stops a timer via a menu, and displays the elapsed time in hours, minutes, seconds, and milliseconds in the window title.
When the program runs, in addition to the basic operations, the following operations occur:
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
bool timer_on; // Timer activation variable
unsigned int time_start; // Timer start time variable
unsigned int time_current; // Current time variable
// Function prototypes
int init_window(void); // Create window and renderer
void init_vars(void); // Initialize values
void load_media(void); // Load media
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 image
load_media();
// 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)
{
timer_on = false;
time_start = 0;
time_current = 0;
}
// Load image
void load_media(void)
{
// Load image to texture
texture = IMG_LoadTexture(renderer, "menu_timer.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;
// Creating a loop to process user inputs
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_EVENT_MOUSE_BUTTON_DOWN:
case SDL_EVENT_MOUSE_MOTION:
{
SDL_Point mouse_pos = { event.motion.x, event.motion.y };
SDL_Rect rect_menu = { 20, 20, 120, 30 };
bool mouse_in = 0;
bool lb_state = event.type==SDL_EVENT_MOUSE_BUTTON_DOWN && event.button.button==SDL_BUTTON_LEFT;
// Checking whether the mouse is inside the button
if(SDL_PointInRect(&mouse_pos, &rect_menu)) {
mouse_in = true;
if(lb_state) {
timer_on = true;
time_start = SDL_GetTicks();
}
}
rect_menu.y = 60;
if(SDL_PointInRect(&mouse_pos, &rect_menu)) {
mouse_in = true;
if(lb_state) timer_on = false;
}
if(mouse_in) SDL_SetCursor(SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_POINTER));
else 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.
// Copy menu texture to main window
SDL_FRect frect_dst = { 20, 20, 120, 70 };
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];
char time_format[20];
time_current = SDL_GetTicks();
if(timer_on) {
int milliseconds = time_current-time_start;
int seconds = milliseconds / 1000;
milliseconds %= 1000;
int minutes = seconds / 60;
seconds %= 60;
int hours = minutes / 60;
minutes %= 60;
sprintf(time_format, "%.2d:%.2d:%.2d:%.4d", hours, minutes, seconds, milliseconds);
}
else {
strcpy(time_format, "00:00:00:0000");
}
sprintf(cdizi, "SDL3 window - Timer: %s", time_format);
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();
}