Using SDL2 in Rust
16 Sep 2023
Introduction
Simple DirectMedia Layer or just simple SDL is a cross-platform library used for accessing video, audio, input devices like keyboard, mouse or joysticks, in addition to also providing some networking abstractions. Despite its age of already 25 years, it is still used extensively for games and other multimedia software as an abstraction layer, either using it to directly draw graphics and play sounds or as a lower-level library on which games engines are built.
While written mainly in C, a lot of language bindings where created and one of them is the Rust binding rust-sdl2, which we will introduce here. We will show how to open a window, draw a small thing and use the events system from SDL2 to handle keyboard inputs.
Linux setup
To get started with SDL2 in Rust, you first need the sdl2 library and headers installed on your system (the Rust crate has a bundled feature, where it compiles it from source, but we are not gonna talk about this here). Install the library using the appropriate package manager for your distribution.
Ubuntu:
sudo apt-get install libsdl2-dev
Fedora:
sudo dnf install SDL2-devel
Arch:
sudo pacman -S sdl2
Windows setup
We assume you are using MSVC as your C++ compiler environment. if you are using MINGW, please see the crate documentation on how to continue.
-
Download the MSVC version of SDL2 from http://www.libsdl.org/ (usually named something like SDL2-devel-2.x.x-VC.zip).
-
Unzip SDL2-devel-2.x.x-VC.zip.
-
Copy all .lib files from
SDL2-2.x.x\lib\x64\
to%userprofile%\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\x86_64-pc-windows-msvc\lib\
-
Copy
SDL2-2.x.x\lib\x64\SDL2.dll
into your project directory or into any directory which is in your PATH. When you want to distribute the compiled application, make sure the shipSDL2.dll
right next to it, or it may not run, if the user doesn’t have theSDL2.dll
lying around.
Creating a Rust project
If you haven’t installed it, yet, install Rust following the “Install Rust” guide.
Create a new Rust project by typing
cargo new sdl2-example
Then change into the newly created directory and type
cargo add sdl2 -F unsafe_textures
to add th SDL2 rust bindings.
We are going to use the unsafe_textures
feature, even though we are not going to use any textures. Mainly because, if you do use textures, you will notice that without that option you are getting a lost of Rust lifetime issues. However, this comes with he downside, that you have to manage the texture objects yourself and make sure to call destroy, if you do not need them any longer. For more information about this feature see here.
You can also add other features which correspond to the different optional SDL2 libraries like gfx, mixer or tff.
When this was successful, you are ready to start developing with SDL2!
Opening a window
Let’s open our main.rs
file and start by creating a window inside the main function (note, we adapt the return value of the main function slightly):
use sdl2::{event::Event, keyboard::Keycode};
pub fn main() -> Result<(), String> {
let sdl_context = sdl2::init()?;
let video_subsystem = sdl_context.video()?;
let window = video_subsystem
.window("rust-sdl2 example", 800, 600)
.opengl()
.build()
.map_err(|e| e.to_string())?;
let mut event_pump = sdl_context.event_pump()?;
'main: loop {
for event in event_pump.poll_iter() {
match event {
Event::Quit { .. }
| Event::KeyDown {
keycode: Some(Keycode::Escape),
..
} => {
break 'main
},
_ => {}
}
}
}
Ok(())
}
Now let’s try to run the program
cargo run
If everything compiles and runs successfully, you will see an empty window. This is fine, we are not drawing anything, yet. But you should be able to close the program with the ESC key.
Here you can already see, that SDL2 is not a full game engine, you really have to do a lot of things yourself, like maintaining an event loop and mapping the events that SDL2 captures to something meaningful, like closing the program.
Drawing a rectangle
We are going to use build-in drawing functionalities from SDL2. They are suitable for drawing simple primitives and we will use one of them to draw a rectangle.
use sdl2::{event::Event, keyboard::Keycode, pixels::Color, rect::Rect};
pub fn main() -> Result<(), String> {
let sdl_context = sdl2::init()?;
let video_subsystem = sdl_context.video()?;
let window = video_subsystem
.window("rust-sdl2 example", 800, 600)
.opengl()
.build()
.map_err(|e| e.to_string())?;
let mut event_pump = sdl_context.event_pump()?;
let mut canvas = window.into_canvas().build().map_err(|e| e.to_string())?;
'main: loop {
for event in event_pump.poll_iter() {
match event {
Event::Quit { .. }
| Event::KeyDown {
keycode: Some(Keycode::Escape),
..
} => break 'main,
_ => {}
}
}
// Set the background
canvas.set_draw_color(Color::RGB(255, 200, 0));
canvas.clear();
// Draw a red rectangle
canvas.set_draw_color(Color::RGB(255, 0, 0));
canvas.fill_rect(Rect::new(100, 100, 600, 400))?;
// Show it on the screen
canvas.present();
}
Ok(())
}
And that’s it!
Summary
As you can see, using SDL2 in Rust is as straightforward as in C and I hope this small introduction could serve as a starting point for your SDL2 and Rust adventures.
And here is a screenshot of our running program:
⇐ Back