SwiftSDL is an open-source Swift library that provides a complete interface for working with the C-based SDL (Simple DirectMedia Layer) library. This wrapper allows developers to leverage SDL's cross-platform multimedia and game development capabilities in Swift applications across macOS, iOS, and Linux.
"Simple DirectMedia Layer is a cross-platform development library designed to provide low level access to audio, keyboard, mouse, joystick, and graphics hardware via OpenGL/Direct3D/Metal/Vulkan. It is used by video playback software, emulators, and popular games including Valve's award winning catalog and many Humble Bundle games." - wiki.libsdl.org
- Swift 6.0.2, or later; and,
- SDL v3.1.6-preview, (required only for Linux).
// swift-tools-version: 6.0
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "MySDLGame",
platforms: [
.macOS(.v13)
],
dependencies: [
.package(url: "https://github.com/KevinVitale/SwiftSDL.git", from: "0.2.0-alpha.16"),),
],
targets: [
.executableTarget(
name: "SwiftSDLTest",
dependencies: [
"SwiftSDL"
],
resources: [
.process("../Resources/BMP"),
]
),
]
)
Like Swift itself, SwiftSDL makes SDL3 approachable for newcomers and powerful for experts.
A complete SwiftSDL game consists of the following 22-lines of code:
import SwiftSDL
@main
final class MyGame: Game {
private enum CodingKeys: String, CodingKey {
case options
}
@OptionGroup
var options: GameOptions
func onReady(window: any Window) throws(SDL_Error) {
/* create a renderer, or acquire a gpu device. */
/* load assets or resources. */
}
func onUpdate(window: any Window, _ delta: Uint64) throws(SDL_Error) {
/* handle game logic and render frames */
}
func onEvent(window: any Window, _ event: SDL_Event) throws(SDL_Error) {
/* respond to events */
}
func onShutdown(window: (any Window)?) throws(SDL_Error) {
/* release objects and unload resources */
}
}
The class, MyGame
, conforms to the Game
protocol. A window is created automatically using reasonable defaults, although, it's possible to override the window's creation manually.
Underneath the hood, the Game
protocol has implemented SDL3's new main callbacks.
GameOptions
are runtime arguments which alter the behavior or your application, such as your window's appearance.
Let's create an app using SwiftSDL from start-to-finish.
Using Swift's command-line utility, we'll create the project in an empty directory
# Create an empty directory for our project
mkdir MyGame
cd MyGame
# Create the executable package
swift package init --type executable
Update the Package.swift
file to include SwiftSDL as a dependency:
Note: you may need adjust
platforms
to use.macOS(.v13)
.
// swift-tools-version: 6.0
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "MyGame",
platforms: [
.macOS(.v13)
],
dependencies: [
.package(url: "https://github.com/KevinVitale/SwiftSDL.git", from: "0.2.0-alpha.17")
],
targets: [
// Targets can depend on other targets in this package and products from dependencies.
.executableTarget(
name: "MyGame",
dependencies: [
"SwiftSDL"
]
),
]
)
Rename main.swift
to MyGame.swift
:
mv Sources/main.swift Sources/MyGame.swift
Then replace MyGame.swift
with the following code:
import SwiftSDL
@main
final class MyGame: Game {
private enum CodingKeys: String, CodingKey {
case options, message
}
@OptionGroup
var options: GameOptions
@Argument
var message: String = "Hello, SwiftSDL!"
private var renderer: (any Renderer)! = nil
func onReady(window: any Window) throws(SDL_Error) {
renderer = try window.createRenderer()
}
func onUpdate(window: any Window, _ delta: Uint64) throws(SDL_Error) {
try renderer
.clear(color: .gray)
.debug(text: message, position: [12, 12], scale: [2, 2])
.fill(rects: [24, 48, 128, 128], color: .white)
.fill(rects: [36, 60, 104, 104], color: .green)
.present()
}
func onEvent(window: any Window, _ event: SDL_Event) throws(SDL_Error) {
}
func onShutdown(window: (any Window)?) throws(SDL_Error) {
renderer = nil
}
}
Then start the game:
swift run
Note: You should see a window with a gray background, a message saying "Hello, SwiftSDL!", and two squares: one large white one, and a smaller green one.
Your game has several options built-in. To see them all, use --help
:
swift run MyGame --help
USAGE: my-game [<options>] [<message>]
ARGUMENTS:
<message> (default: Hello, SwiftSDL!)
OPTIONS:
--hide-cursor Hide the system's cursor
--auto-scale-content Stretch the content to fill the window
--logical-size <logical-size>
Forces the rendered content to be a certain logical size (WxH)
--logical-presentation <logical-presentation>
Forces the rendered content to be a certain logical order; overrides '--auto-scale-content' (values: disabled,
stretch, letterbox, overscan, integer-scale; default: disabled)
--vsync-rate <vsync-rate>
Set vertical synchronization rate (values: adaptive, disabled, interger value; default: disabled)
--window-always-on-top Window is always kept on top
--window-fullscreen Window is set to fullscreen
--window-transparent Window is uses a transparent buffer
--window-maximized Create a maximized window; requires '--window-resizable'
--window-minimized Create a minimized window
--window-max-size <window-max-size>
Specify the maximum window's size (WxH)
--window-min-size <window-min-size>
Specify the minimum window's size (WxH)
--window-mouse-focus Force the window to have mouse focus
--window-no-frame Create a borderless window
--window-resizable Enable window resizability
--window-position <window-position>
Specify the window's position (XxY)
--window-size <window-size>
Specify the window's size (WxH)
--window-title <window-title>
Specify the window's title
-h, --help Show help information.
SwiftSDL includes several samples to help you get started.
These are reimplementations of a variety of SDL3's tests using SwiftSDL:
Build Command | Image Preview |
---|---|
swift run sdl test controller |
|
swift run sdl test camera |
|
swift run sdl test geometry |
|
swift run sdl test sprite |
Build Command | Image Preview |
---|---|
swift run sdl games flappy-bird |
Explore: Samples/SwiftSDL-Xcode
SwiftSDL doesn't work without SDL3. Refer to the following sections to ensure SwiftSDL compiles properly.
SwiftSDL works on macOS, iOS, and tvOS simply by adding it to your project's Package.swift
file. A precompiled XCFramework containing the SDL3 library is provided.
You do not need to build the XCFramework yourself. However, if you need to, the available Makefile
can be used:
# Clone KevinVitale/SwiftSDL
git clone https://github.com/KevinVitale/SwiftSDL
cd SwiftSDL
# Build XCFramework...grab some βοΈ
make build-sdl-xcframework
You must build and install SDL3 from source. Thankfully, it's easy and should take only a few minutes:
- Install whichever dependencies your need for your game; and,
- Build and install from source.
Support for Windows is currently unavailable.
SwiftSDL is open-sourced under the MIT license. See the LICENSE
file for details.