Getting Started with SDL2 Graphics
This brief guide provides code to show simple graphics functionality without SplashKit such as how to open a window, keep a window open, draw a rectangle and display a bitmap. These are then combined to create a simple "eye dropper" program to compare with and without SplashKit.
Written by: Simon Rhook and Olivia McKeon
Last updated: December 2024
Getting Started without SplashKit
Section titled “Getting Started without SplashKit”Installing SDL2 and SDL2_image
Section titled “Installing SDL2 and SDL2_image”If you have not already installed SplashKit, you will need to install SDL2 and SDL2_image to be able to compile the code shown in this guide.
You can use the following command, which is usually run during the SplashKit installation, which will ensure you have installed the required libraries/dependencies.
pacman -S --needed --disable-download-timeout mingw-w64-x86_64-clang mingw-w64-x86_64-gcc mingw-w64-x86_64-gdb mingw-w64-x86_64-cmake mingw-w64-x86_64-SDL2 mingw-w64-x86_64-SDL2_gfx mingw-w64-x86_64-SDL2_mixer mingw-w64-x86_64-SDL2_image mingw-w64-x86_64-SDL2_ttf mingw-w64-x86_64-SDL2_net mingw-w64-x86_64-civetwebbrew install pkgconfig sdl2 sdl2_ttf sdl2_image sdl2_net sdl2_mixer sdl2_gfx libpng cmakesudo apt-get install cmake libpng-dev libcurl4-openssl-dev libsdl2-dev libsdl2-mixer-dev libsdl2-gfx-dev libsdl2-image-dev libsdl2-net-dev libsdl2-ttf-dev libmikmod-dev libncurses5-dev libbz2-dev libflac-dev libvorbis-dev libwebp-dev libfreetype6-dev build-essential clangCompiling Your Code
Section titled “Compiling Your Code”With C++ programs, you will need to adjust the compiling command to link to any libraries being used. Below you will see the different commands to compile with and without SplashKit.
Now, assuming the code filename is program.cpp.
As usual, you will compile the SplashKit C++ code using the following command:
g++ program.cpp -o test -l SplashKitYou can use this command to compile the code below:
g++ program.cpp -o test -lSDL2_image -lmingw32 -mwindows -lSDL2main -lSDL2Note: If you have issues, you can find out the compiling flags needed using these commands:
pkg-config --libs sdl2 sdl2_imagepkg-config --cflags sdl2g++ program.cpp -o test -L/opt/homebrew/Cellar/sdl2_image/2.8.8/lib -lSDL2_image -L/opt/homebrew/lib -lSDL2 -I/opt/homebrew/include -I/opt/homebrew/include/SDL2 -D_THREAD_SAFENote: If you have issues, you can find out the compiling flags needed using these commands:
pkg-config --libs sdl2 sdl2_imagepkg-config --cflags sdl2g++ program.cpp -o test -lSDL2_image -lSDL2 -I/usr/include/SDL2 -D_REENTRANTNote: If you have issues, you can find out the compiling flags needed using these commands:
pkg-config --libs sdl2 SDL2_imagepkg-config --cflags sdl2SDL2 Versions of SplashKit Functions
Section titled “SDL2 Versions of SplashKit Functions”The following sections show how to create the same functionality given in SplashKit, but without using SplashKit. These code examples are using SDL2 which is actually one of SplashKit’s dependencies, and are quite similar to what is happening behind the scenes when using SplashKit functions.
Open Window
Section titled “Open Window”The following code shows how to open a Window with and without SplashKit:
#include "splashkit.h"
int main(int argv, char **args){    // Create Window    window win = open_window("SK Window: OpenWindow", 800, 600);
    // Hold window 4 seconds    delay(4000);
    // Cleanup and free memory    close_all_windows();
    return 0;}#include <iostream>#ifdef __APPLE__#include <SDL.h>#else#include <SDL2/SDL.h>#endif
int main(int argv, char **args){    // Opening a Window without SplashKit
    // Declare Variables    SDL_Window *window = nullptr;
    // Check for successful initialisation    if (SDL_Init(SDL_INIT_VIDEO) < 0)    {        std::cout << "SDL could not be initialized: " << SDL_GetError();        exit(1);    }
    // Create Window    window = SDL_CreateWindow(        "No SK Window: OpenWindow",        SDL_WINDOWPOS_CENTERED,        SDL_WINDOWPOS_CENTERED,        800,        600,        SDL_WINDOW_OPENGL);
    // Error handling for window    if (window == NULL)    {        SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Could not create window: %s\n", SDL_GetError());        exit(1);    }
    // Hold window open for 4 seconds    Uint32 start_time = SDL_GetTicks(); // Start timer    SDL_Event event;
    while (SDL_GetTicks() - start_time < 4000) // Run for 4 seconds    {        if (SDL_PollEvent(&event) && event.type == SDL_QUIT) break;    }
    // Cleanup and free memory    SDL_DestroyWindow(window);
    return 0;}Quit Requested
Section titled “Quit Requested”The following code shows how to open a Window and hold the window open until the user quits, with and without SplashKit:
#include "splashkit.h"
int main(int argv, char **args){    open_window("SK Window: QuitRequested", 600, 600);
    // Hang window until quit    while (!quit_requested())    {        process_events();    }
    // Cleanup and free memory    close_all_windows();
    return 0;}#include <iostream>#ifdef __APPLE__#include <SDL.h>#else#include <SDL2/SDL.h>#endif
SDL_Window *sdl_open_window(const char *window_title, const int width, const int height){    // This function demonstrates how we can open window without SplashKit.
    // Declare Variables    SDL_Window *window = nullptr;
    // Check for successful initialisation    if (SDL_Init(SDL_INIT_VIDEO) < 0)    {        std::cout << "SDL could not be initialized: " << SDL_GetError();        exit(1);    }
    // Create Window    window = SDL_CreateWindow(        window_title,        SDL_WINDOWPOS_CENTERED,        SDL_WINDOWPOS_CENTERED,        width,        height,        SDL_WINDOW_OPENGL);
    // Error handling for window    if (window == NULL)    {        SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Could not create window: %s\n", SDL_GetError());        exit(1);    }
    return window;}
int main(int argv, char **args){    SDL_Window *window = sdl_open_window("No SK Window: QuitRequested", 800, 600);
    // Hang window until quit    SDL_Event event;    while (event.type != SDL_QUIT)    {        SDL_PollEvent(&event);    }
    // Cleanup and free memory    SDL_DestroyWindow(window);
    return 0;}Draw Rectangle
Section titled “Draw Rectangle”The following code shows how to draw a rectangle to the screen (Window), with and without SplashKit:
#include "splashkit.h"
int main(int argv, char **args){    // Create window    open_window("SK Window: DrawRectangle", 600, 600);
    // Define a rectangle    rectangle rect = rectangle_from(100.0, 100.0, 400.0, 300.0);
    // Clear screen with a black color    clear_screen(COLOR_BLACK);
    // Draw & fill blue rectangle    fill_rectangle(COLOR_BLUE, rect);
    // Display drawing    refresh_screen();
    // Hold window until quit requested    while (!quit_requested())    {        process_events();    }
    // Cleanup and free memory    close_all_windows();
    return 0;}#include <iostream>#ifdef __APPLE__#include <SDL.h>#else#include <SDL2/SDL.h>#endif
SDL_Window *sdl_open_window(const char *window_title, const int width, const int height){    // Declare Variables    SDL_Window *window = nullptr;
    // Check for successful initialisation    if (SDL_Init(SDL_INIT_VIDEO) < 0)    {        std::cout << "SDL could not be initialized: " << SDL_GetError();        exit(1);    }
    // Create Window    window = SDL_CreateWindow(        window_title,        SDL_WINDOWPOS_CENTERED,        SDL_WINDOWPOS_CENTERED,        width,        height,        SDL_WINDOW_OPENGL);
    // Error handling for window    if (window == NULL)    {        SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Could not create window: %s\n", SDL_GetError());        exit(1);    }
    return window;}
int main(int argv, char **args){    SDL_Window *window = sdl_open_window("No SK Window: DrawRectangle", 800, 600);
    // Create renderer    SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);    if (renderer == NULL)    {        SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Could not create rederer: %s\n", SDL_GetError());        exit(1);    }
    // Define a rectangle    SDL_Rect rect = {100, 100, 400, 300};
    // Clear screen with a black color    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);    SDL_RenderClear(renderer);
    // Set rectangle color to blue    SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
    // Draw & fill rectangle    SDL_RenderDrawRect(renderer, &rect);    SDL_RenderFillRect(renderer, &rect);
    // Display drawing    SDL_RenderPresent(renderer);
    SDL_Event event;    while (event.type != SDL_QUIT)    {        // check for quit requested        SDL_PollEvent(&event);    }
    // Cleanup and free memory    SDL_DestroyRenderer(renderer);    SDL_DestroyWindow(window);    SDL_Quit();
    return 0;}Draw Bitmap
Section titled “Draw Bitmap”The following code shows how to display a bitmap image on the screen (Window), with and without SplashKit:
#include "splashkit.h"
int main(int argv, char **args){    // Create window    open_window("SK Window: DrawBitmap", 800, 600);
    // Load image    bitmap image = load_bitmap("photo", "photo.jpg");
    // Hold window until quit requested    while (!quit_requested())    {        process_events();
        // Clear screen with black        clear_screen(COLOR_BLACK);
        // Draw image to screen        draw_bitmap("photo", 75, 125);
        // Display drawing        refresh_screen();    }
    // Cleanup and free memory    close_all_windows();    free_all_bitmaps();
    return 0;}#include <iostream>#ifdef __APPLE__#include <SDL.h>#include <SDL_image.h>#else#include <SDL2/SDL.h>#include <SDL2/SDL_image.h>#endif
SDL_Window *sdl_open_window(const char *window_title, const int width, const int height){    // Declare Variables    SDL_Window *window = nullptr;
    // Check for successful initialisation    if (SDL_Init(SDL_INIT_VIDEO) < 0)    {        std::cout << "SDL could not be initialized: " << SDL_GetError();        exit(1);    }
    // Create Window    window = SDL_CreateWindow(        window_title,        SDL_WINDOWPOS_CENTERED,        SDL_WINDOWPOS_CENTERED,        width,        height,        SDL_WINDOW_OPENGL);
    // Error handling for window    if (window == NULL)    {        SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Could not create window: %s\n", SDL_GetError());        exit(1);    }
    return window;}
SDL_Renderer *sdl_create_renderer(SDL_Window *window){    SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);    if (renderer == NULL)    {        SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Could not create rederer: %s\n", SDL_GetError());        exit(1);    }    return renderer;}
int main(int argv, char **args){    SDL_Window *window = sdl_open_window("No SK Window: DrawBitmap", 800, 600);    SDL_Renderer *renderer = sdl_create_renderer(window);
    // Load image    // Create a surface for imported image    SDL_Surface *image = IMG_Load("Resources/images/photo.jpg");    if (image == NULL)    {        std::cout << "Failed to load photo.jpg" << SDL_GetError();        exit(1);    }
    // Convert surface to texture    SDL_Texture *image_texture = SDL_CreateTextureFromSurface(renderer, image);    if (image_texture == NULL)    {        std::cout << "Failed to create texture" << SDL_GetError();        exit(1);    }
    // Free memory    SDL_FreeSurface(image);
    // Get image size to avoid stretching    int background_width = 0, background_height = 0;    SDL_QueryTexture(image_texture, NULL, NULL, &background_width, &background_height);
    // Hang window until quit    SDL_Event event;    while (event.type != SDL_QUIT)    {        SDL_PollEvent(&event);
        // Clear screen with black        SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);        SDL_RenderClear(renderer);
        // Draw image to screen        SDL_Rect image_rect = { 75, 125, background_width, background_height };        SDL_RenderCopy(renderer, image_texture, NULL, &image_rect);
        // Display drawing        SDL_RenderPresent(renderer);    }
    // Cleanup and free memory    SDL_DestroyWindow(window);    SDL_DestroyRenderer(renderer);
    return 0;}Combining Functionality
Section titled “Combining Functionality”You can then combine the elements above into a small program such as the eyedropper (colour picker) program shown below.
Eyedropper Program
Section titled “Eyedropper Program”This program combines the above into a small program that will change the screen (Window) colour based on the colour of the image at the point where you click on it:
#include "splashkit.h"
int main(int argv, char **args){    // Print instructions in terminal    write_line("\nClick anywhere on the image to change the background colour\n");
    // Declare Variables    color eye_select = COLOR_BLACK;
    // Open Window    open_window("SK Window: Eyedropper", 800, 600);
    // Load bitmaps    load_bitmap("image", "photo.jpg");    load_bitmap("eyedrop", "eyedrop.png");
    while (!quit_requested())    {        process_events();
        // Clear screen with mouse color        clear_screen(eye_select);
        // Draw image        draw_bitmap("image", 75, 125);
        // Draw eyedropper as curser        draw_bitmap("eyedrop", mouse_x() - 3, mouse_y() - bitmap_height("eyedrop") + 3);        hide_mouse();
        // Set color at cursor when click        if (mouse_clicked(LEFT_BUTTON))            eye_select = get_pixel(mouse_x(), mouse_y());
        // Display drawing        refresh_screen();    }
    // Cleanup and free memory    close_all_windows();    free_all_sound_effects();    free_all_music();
    return 0;}#include <iostream>#ifdef __APPLE__#include <SDL.h>#include <SDL_image.h>#else#include <SDL2/SDL.h>#include <SDL2/SDL_image.h>#endif
SDL_Window *sdl_open_window(const char *window_title, const int width, const int height){    // Declare Variables    SDL_Window *window = nullptr;
    // Check for successful initialisation    if (SDL_Init(SDL_INIT_VIDEO) < 0)    {        std::cout << "SDL could not be initialized: " << SDL_GetError();        exit(1);    }    if (!(IMG_Init(IMG_INIT_PNG | IMG_INIT_JPG) & (IMG_INIT_PNG | IMG_INIT_JPG)))    {        std::cout << "Failed to initialize SDL_image: " << IMG_GetError();        exit(1);    }
    // Create Window    window = SDL_CreateWindow(        window_title,        SDL_WINDOWPOS_CENTERED,        SDL_WINDOWPOS_CENTERED,        width,        height,        SDL_WINDOW_OPENGL);
    // Error handling for window    if (window == NULL)    {        SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Could not create window: %s\n", SDL_GetError());        exit(1);    }
    return window;}
int main(int argv, char **args){    // Print instructions in terminal    std::cout << "\nClick anywhere on the image to change the background colour\n\n";
    // Declare Variables    int mouse_x, mouse_y;    unsigned int clr = 0;    SDL_Color mouse_color = {0, 0, 0, 255};
    // Open Window    SDL_Window *window = sdl_open_window("No SK Window: SDL2 Eyedropper", 800, 600);
    // Create renderer    SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);    if (renderer == NULL)    {        SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Could not create rederer: %s\n", SDL_GetError());        exit(1);    }
    // Create textures for eye drop and background image    SDL_Surface *background = IMG_Load("Resources/images/photo.jpg");    if (background == NULL)    {        std::cout << "Failed to load background.jpg" << SDL_GetError();        exit(1);    }
    SDL_Texture *background_texture = SDL_CreateTextureFromSurface(renderer, background);    if (background_texture == NULL)    {        std::cout << "Failed to create texture" << SDL_GetError();        exit(1);    }    SDL_FreeSurface(background);    SDL_Surface *eyedrop = IMG_Load("Resources/images/eyedrop.png");    if (eyedrop == NULL)    {        std::cout << "Failed to load eyedrop.png" << SDL_GetError();        exit(1);    }
    SDL_Texture *eyedrop_texture = SDL_CreateTextureFromSurface(renderer, eyedrop);    if (eyedrop_texture == NULL)    {        std::cout << "Failed to create texture" << SDL_GetError();        exit(1);    }    SDL_FreeSurface(eyedrop);
    // Get the native dimensions of the textures    int background_width = 0, background_height = 0, eyedrop_width = 0, eyedrop_height = 0;    SDL_QueryTexture(background_texture, NULL, NULL, &background_width, &background_height);    SDL_QueryTexture(eyedrop_texture, NULL, NULL, &eyedrop_width, &eyedrop_height);
    SDL_Event event;    while (event.type != SDL_QUIT)    {        // Check for quit requested        SDL_PollEvent(&event);
        // Clear screen with mouse color        SDL_SetRenderDrawColor(renderer, mouse_color.r, mouse_color.g, mouse_color.b, mouse_color.a);        SDL_RenderClear(renderer);
        // Draw background        SDL_Rect background_rect = {75, 125, background_width, background_height};        SDL_RenderCopy(renderer, background_texture, NULL, &background_rect);
        // Get the mouse position        SDL_GetMouseState(&mouse_x, &mouse_y);        SDL_Rect rect = {mouse_x, mouse_y, 1, 1};
        // Draw eyedropper as curser        SDL_Rect eyedrop_rect = {mouse_x - 3, mouse_y - eyedrop_height + 3, eyedrop_width, eyedrop_height};        SDL_RenderCopy(renderer, eyedrop_texture, NULL, &eyedrop_rect);        SDL_ShowCursor(SDL_DISABLE);
        // Set color at cursor when click        if (event.type == SDL_MOUSEBUTTONDOWN)        {            SDL_RenderReadPixels(renderer, &rect, SDL_PIXELFORMAT_RGBA8888, &clr, 1);            SDL_GetRGBA(clr, SDL_AllocFormat(SDL_PIXELFORMAT_RGBA8888), &mouse_color.r, &mouse_color.g, &mouse_color.b, &mouse_color.a);        }
        // Display drawing        SDL_RenderPresent(renderer);    }    // Cleanup and free memory    SDL_DestroyTexture(background_texture);    SDL_DestroyTexture(eyedrop_texture);    SDL_DestroyRenderer(renderer);    SDL_DestroyWindow(window);    SDL_Quit();
    return 0;}