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
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-civetweb
brew install pkgconfig sdl2 sdl2_ttf sdl2_image sdl2_net sdl2_mixer sdl2_gfx libpng cmake
sudo 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 clang
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 SplashKit
You can use this command to compile the code below:
g++ program.cpp -o test -lSDL2_image -lmingw32 -mwindows -lSDL2main -lSDL2
Note: If you have issues, you can find out the compiling flags needed using these commands:
pkg-config --libs sdl2 sdl2_imagepkg-config --cflags sdl2
g++ program.cpp -o test -L/opt/homebrew/Cellar/sdl2_image/2.8.2_2/lib -lSDL2_image -L/opt/homebrew/lib -lSDL2 -I/opt/homebrew/include -I/opt/homebrew/include/SDL2 -D_THREAD_SAFE
Note: If you have issues, you can find out the compiling flags needed using these commands:
pkg-config --libs sdl2 sdl2_imagepkg-config --cflags sdl2
g++ program.cpp -o test -lSDL2_image -lSDL2 -I/usr/include/SDL2 -D_REENTRANT
Note: If you have issues, you can find out the compiling flags needed using these commands:
pkg-config --libs sdl2 SDL2_imagepkg-config --cflags sdl2
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
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 4 seconds SDL_Delay(4000);
// Cleanup and free memory SDL_DestroyWindow(window);
return 0;}
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
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
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
You can then combine the elements above into a small program such as the eyedropper (colour picker) program shown below.
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;}