mmoehabb/zigsdl
A simple framework for developing graphic apps with SDL in zig.
A relatively easy-to-pick, simple, and straightforward package that developers can use in order to write graphic applications in Zig. Just as the name indicates it's build on SDL3.
You can use ZigSDL in your zig project by fetching it as follows:
zig fetch --save git+https://github.com/mmoehabb/zigsdl.git
And then add it as an import in your exe root module:
const exe = b.addExecutable(.{
.name = "your-project",
.root_module = exe_mod,
});
const zigsdl_dep = b.dependency("zigsdl", .{
.target = target,
.optimize = optimize,
});
const zigsdl_mod = zigsdl_dep.module("zigsdl");
exe.root_module.addImport("zigsdl", zigsdl_mod);
Make sure to install SDL3 first.
First ensure to install SDL3 on your machine, and Zig of course. Choose any example file in the examples directory, and then run it with the following command:
Note: compatible only with zig versions ^0.15.0
zig build example:<example-filename>
For instance:
zig build example:moving-box
I bet if you gave the code a look, you'd already know how to extend it and make a functional game with ZigSDL. Here's the moving-box zig file:
const zigsdl = @import("zigsdl");
const std = @import("std");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
defer {
const deinit_status = gpa.deinit();
if (deinit_status == .leak) std.debug.panic("Memory leak detected!", .{});
}
// Create a drawable object
var rect = zigsdl.drawables.Rect.new(
.{ .w = 20, .h = 20, .d = 1 },
.{ .g = 255 },
);
var rect_drawable = rect.toDrawable();
var obj = zigsdl.modules.Object.init(allocator, .{
.name = "GreenBox",
.position = .{ .x = 20, .y = 20, .z = 1 },
.rotation = .{ .x = 0, .y = 0, .z = 0 },
.drawable = &rect_drawable,
});
defer obj.deinit();
// Add movement script to the object
var movement = zigsdl.scripts.Movement{ .velocity = 5, .smooth = true };
try obj.addScript(@constCast(&movement.toScript()));
// Create a scene and add the obj into it
var scene = zigsdl.modules.Scene.init(allocator);
defer scene.deinit();
try scene.addObject(&obj);
// Create a screen, attach the scene to it, and open it
var screen = zigsdl.modules.Screen.init(allocator, .{
.title = "Simple Game",
.width = 320,
.height = 320,
.rate = 1000 / 60,
});
defer screen.deinit();
screen.setScene(&scene);
try screen.open();
}
You may add as many objects as you want in the scene, you can easily add different functionalities and behaviour to your objects by adding scripts into them; you may use ZigSDL pre-defined drawables and/or scripts or write your own ones as follows:
The Rect Drawable:
const zigsdl = @import("zigsdl");
pub const Rect = struct {
dim: zigsdl.types.common.Dimensions,
color: zigsdl.types.common.Color = .{},
_draw_strategy: zigsdl.modules.DrawStrategy = zigsdl.modules.DrawStrategy{
.draw = draw,
.destroy = destroy,
},
pub fn new(dim: zigsdl.types.common.Dimensions, color: zigsdl.types.common.Color) Rect {
return Rect{
.dim = dim,
.color = color,
};
}
pub fn toDrawable(self: *Rect) zigsdl.modules.Drawable {
return zigsdl.modules.Drawable{
.dim = self.dim,
.color = self.color,
.drawStrategy = &self._draw_strategy,
};
}
fn draw(
_: *zigsdl.modules.Drawable,
_: *const zigsdl.modules.DrawStrategy,
renderer: *zigsdl.sdl.SDL_Renderer,
p: zigsdl.types.common.Position,
_: zigsdl.types.common.Rotation,
dim: zigsdl.types.common.Dimensions,
) !void {
if (!sdl.c.SDL_RenderFillRect(renderer, &sdl.c.SDL_FRect{
.x = p.x,
.y = p.y,
.w = dim.w,
.h = dim.h,
})) return error.RenderFailed;
}
fn destroy(
_: *zigsdl.modules.Drawable,
_: *const zigsdl.modules.DrawStrategy,
) void {}
};
The Movement script:
const zigsdl = @import("zigsdl");
pub const Movement = struct {
velocity: f32 = 5,
smooth: bool = true,
_script_strategy: zigsdl.modules.ScriptStrategy = zigsdl.modules.ScriptStrategy{
.start = start,
.update = update,
.end = end,
},
_last_pressed: zigsdl.types.event.Key = .Unknown,
pub fn toScript(self: *Movement) zigsdl.modules.Script {
return modules.Script{ .strategy = &self._script_strategy };
}
fn start(_: *zigsdl.modules.Script, _: *zigsdl.modules.Object) void {}
fn update(s: *zigsdl.modules.Script, o: *zigsdl.modules.Object) void {
const obj = o;
const self = @as(*Movement, @constCast(@fieldParentPtr("_script_strategy", s.strategy)));
var em = o.*._scene.?.screen.?.em;
if (self.smooth) {
if (em.isKeyDown(.W)) obj.position.y -= self.velocity;
if (em.isKeyDown(.S)) obj.position.y += self.velocity;
if (em.isKeyDown(.D)) obj.position.x += self.velocity;
if (em.isKeyDown(.A)) obj.position.x -= self.velocity;
return;
}
// ...
}
fn end(_: *zigsdl.modules.Script, _: *zigsdl.modules.Object) void {}
};
Moreover, you may access SDL indirectly from ZigSDL, and use SDL facilities in your scripts:
const sdl = @import("zigsdl").sdl;
sdl.SDL_RenderFillRect(...);
This guide provides brief instructions for installing SDL3 on various operating systems to support projects like zigsdl.
Generated by Grok
Using vcpkg:
vcpkg install sdl3
vcpkg install sdl3_ttf
vcpkg install sdl3_image
Manual Installation:
include and lib directories to your compiler's include and library paths.SDL3.dll is in your executable's directory or system PATH.Using Homebrew:
brew install sdl3
brew install sdl3_ttf
brew install sdl3_image
Manual Installation:
SDL3.framework to /Library/Frameworks or your project directory.Using apt:
sudo apt-get update
sudo apt-get install libsdl3-dev
sudo apt-get install libsdl3_ttf-dev
sudo apt-get install libsdl3_image-dev
Manual Installation:
wget https://github.com/libsdl-org/SDL/releases/download/release-3.2.26/SDL3-3.2.26.tar.gz
tar -xf SDL3-3.2.26.tar.gz
mkdir ./SDL3-3.2.26/build
cd ./SDL3-3.2.26/build
cmake ..
cmake --build . --parallel $(nproc)
sudo cmake --install .
wget https://github.com/libsdl-org/SDL_ttf/releases/download/release-3.2.2/SDL3_ttf-3.2.2.tar.gz
tar -xf SDL3_ttf-3.2.2.tar.gz
mkdir ./SDL3_ttf-3.2.2/build
cd ./SDL3_ttf-3.2.2/build
cmake ..
cmake --build . --parallel $(nproc)
sudo cmake --install .
wget https://github.com/libsdl-org/SDL_image/releases/download/release-3.2.4/SDL3_image-3.2.4.tar.gz
tar -xf SDL3_image-3.2.4.tar.gz
mkdir ./SDL3_image-3.2.4/build
cd ./SDL3_image-3.2.4/build
cmake ..
cmake --build . --parallel $(nproc)
sudo cmake --install .
Using dnf:
sudo dnf install SDL3-devel
sudo dnf install SDL3_ttf-devel
sudo dnf install SDL3_image-devel
Using paru:
paru -S sdl3
paru -S sdl3_ttf
paru -S sdl3_image
pkg-config --libs --cflags sdl3 to check if SDL3 is correctly installed and accessible.-lSDL3.For detailed instructions or troubleshooting, visit the SDL3 documentation.
Add loop, pause and volume settings in the AudioPlayer.
Make scenes behave like cameras; they can zoom in and out, and move in the four directions.
Implement a drawable for each common geometric shape.
Implement interactive UI drawables: Button, TextInput, Select, and Checkbox.
Implement SVG Drawable.
Implement Rigidbody script; it should, at minimum, specify the mass of the object, detect collisions, and apply gravity.
Implement Collision script; any two objects with this script, and one of them is a rigid-body, they shall not overlap.
Implement AudioSource and AudioListener scripts. The general idea is that whenever an AudioSource commence to play an audio, it searches for an AudioListener in the same scene. Once it find one, it plays the audio with the volumes of its channels twisted according to the distance between the two objects (one carries the source, and another carries the listener).
Write Animation and Animator scripts.
Write SVG Example.
Develop a Pong game.
Develop a Sokoban game.