Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Playdate Scaffolder

Playdate logo

A scaffolder to start the development of Playdate apps and games written in Swift, built on the playdate-kit bindings, for both the Playdate Simulator and real Playdate hardware.

Starting a new project

The quickest way — nothing to clone, the init script fetches the template by itself:

curl -fsSL https://raw.githubusercontent.com/rock-n-code/playdate/main/init.sh | sh -s -- MyGame

Or from a checkout of the template repository:

git clone https://github.com/rock-n-code/playdate.git
playdate/init.sh MyGame                                   # creates the game ./MyGame next to the checkout
playdate/init.sh MyGame ~/Projects/MyGame                 # creates a game with explicit destination
playdate/init.sh MyApp --type app --author "John Doe"  # creates the app ./MyApp with specific options

Arguments and options

The initialization script accepts the following arguments and options:

./init.sh <AppName> [destination-dir] [options]
Argument Meaning Default
AppName The game's name; it becomes the Swift module name, so letters and digits only, starting with a letter required
destination-dir Where the project is created ../<AppName> beside the checkout, or ./<AppName> when run via curl
--type <app|game> What kind of project this is; names the root class App or Game accordingly game
--display-name <name> Launcher name in pdxinfo AppName
--bundle-id <id> Reverse-DNS identifier in pdxinfo com.example.<appname>
--author <name> Author in pdxinfo git config user.name
--no-git Skip git init and the initial commit new projects start as a git repository

The generated project has the placeholder name substituted everywhere it matters: the package and target names, the sources folder, the pdxinfo metadata, and the build tooling.

⛔️ A few names are refused because they collide with modules the project depends on: PlaydateKit, CPlaydate, and Swift.

What the script does

  1. Copies the template's git-tracked files (so build artifacts and editor droppings never end up in a new project); when run standalone, it first fetches the template into a temporary clone. The script itself is not copied.
  2. Renames the Template placeholder to your project's name across the sources, manifest, and build tooling — and, with --type app, renames the Game class and file to App.
  3. Fills in pdxinfo with the display name, bundle identifier, and author.
  4. Replaces this README with a fresh one titled after the app/game.
  5. Initializes a git repository with an initial commit (unless --no-git).

If anything fails or the run is interrupted, the half-created destination is removed — you never end up with a broken project.

After generating

cd MyGame
make build    # first build: resolves playdate-kit, packages MyGame.pdx
open -a "$HOME/Developer/PlaydateSDK/bin/Playdate Simulator.app" MyGame.pdx

To work in Xcode, open the project folder (or its Package.swift) — editing, code completion, and host builds all work there, while .pdx packaging and device builds go through make in the terminal.

Prerequisites

This scaffolder is macOS-only: the build tooling depends on Xcode's toolchain discovery (xcrun, plutil) and BSD utilities. The Playdate SDK itself supports other platforms, but this script does not unfortunately.

For Simulator builds:

  • Playdate SDK 3.1.1 or later, installed at ~/Developer/PlaydateSDK or pointed to by PLAYDATE_SDK_PATH
  • Swift 6.3 tools or later (recent Xcode is fine)
  • The playdate pkg-config module, generated once per machine by running make setup in a playdate-kit checkout

Additionally, for device builds:

  • A swift.org development snapshot toolchain, since Xcode's toolchain lacks the Embedded Swift stdlib for armv7em-none-none-eabi. The easiest route is to install this snapshot toolchain with Swiftly: swiftly install main-snapshot
  • The Arm GNU toolchain (arm-none-eabi-gcc) on your PATH

Project structure

Package.swift        SwiftPM manifest; the product must stay named "pdex"
Sources/
  Template/
    EventHandler.swift   @_cdecl("eventHandler") C entry point
    Game.swift           minimal game loop — build from here
                         (named App.swift in projects created with --type app)
Source/
  pdxinfo          bundle metadata (name, bundleID, version)
init.sh            creates a renamed project from this template
Makefile           provide tasks to assist in the development lifecycle of an app or game

Building

Simulator

make build
open -a "$HOME/Developer/PlaydateSDK/bin/Playdate Simulator.app" Template.pdx

The build target compiles the game as pdex.dylib with SwiftPM, drops it into Source/ next to pdxinfo, and packages Template.pdx with the SDK's pdc. It only needs Xcode's Swift and the Playdate SDK — none of the device prerequisites above.

Device (and Simulator)

make all        # device binary + simulator dylib in one pdx
make device     # device binary only
make simulator  # simulator dylib only
make run        # simulator flavor, then open in the Playdate Simulator
make clean      # remove build folders, the pdx, and copied binaries

Bare make (or make help) prints this list of targets without building anything.

The Makefile cross-compiles the game and the playdate-kit wrapper with Embedded Swift for the device's ARM Cortex-M7, reusing the swift.mk build logic from the SwiftPM checkout of playdate-kit (so it always matches the pinned dependency version). Sideload the resulting Template.pdx via the Playdate Simulator (Device ▸ Upload Game to Device) or the SDK's pdutil.

If make picks the wrong Swift toolchain, select one explicitly, e.g.:

TOOLCHAINS=$(plutil -extract CFBundleIdentifier raw -o - \
  ~/Library/Developer/Toolchains/swift-latest.xctoolchain/Info.plist) make

Development

How a project runs

The Playdate firmware (and the Simulator) loads the game and calls the C entry point exported in EventHandler.swift with lifecycle events. On initialize, the handler stores the Playdate API pointer — this must happen before any other PlaydateKit call — and hands control to Game.shared.start() (or App in app-type projects), which registers the update callback. From then on, update() runs once per frame: read input, advance state, draw. The playdate-kit README documents the API surface — System, Display, Graphics, Sprite, Sound, File, and other available types.

Assets

Everything in Source/ is packaged into the pdx by the SDK's pdc compiler, next to the compiled game code. Put images, audio, and fonts there and load them by path with the Graphics/Sound APIs. pdc converts known formats on the way in (for example .png to .pdi); consult the Playdate SDK docs for the supported formats.

Updating playdate-kit

Run make outdated to see whether newer versions are available within the manifest's ranges, and make update to move to them. For a new major version, bump the range in Package.swift first. The device build reuses swift.mk from the resolved checkout, so its build logic follows the pinned version automatically — no other files to touch.

Troubleshooting

  • Playdate SDK not found or no pdc at "…/bin" (from make) — install the Playdate SDK or point PLAYDATE_SDK_PATH at it.
  • swift build cannot find CPlaydate / pd_api.h — the playdate pkg-config module is missing; run make setup in a playdate-kit checkout once per machine.
  • Swift toolchain not found; set ENV value TOOLCHAINS — device builds need a swift.org snapshot toolchain: swiftly install main-snapshot. If the wrong toolchain gets picked, see the TOOLCHAINS override under Building.
  • arm-none-eabi C headers not found — install the Arm GNU toolchain and make sure arm-none-eabi-gcc is on PATH.
  • First make in a fresh project prints Resolving Swift package dependencies… — that's normal; the checkout of playdate-kit is created on demand.
  • The Simulator shows a blank screen — make sure the update callback returns true, otherwise the display is not redrawn.

⚠️ The source of the app/game code must stay within the Embedded Swift subset — no Foundation, no reflection, no untyped throws — or device builds will fail even though the simulator build succeeds.

About

A scaffolder to kickstart the development of your Playdate apps and games.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages