Add DocC documentation and a runnable example game

- DocC catalog (Sources/PlayDate/PlayDate.docc) with a curated landing
  page and a Getting Started article; swift-docc-plugin wired up for
  `swift package generate-documentation`, and a GitHub Pages deployment
  workflow renders docs on every push to main.
- Examples/HelloPlaydate: a minimal game (bouncing box, crank needle,
  button handling, system menu item) whose build.sh compiles the game as
  a dylib and produces a runnable simulator .pdx via the SDK's pdc.
  Verified: the pdx builds and exports the eventHandler entry point.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-24 11:29:13 +02:00
co-authored by Claude Fable 5
parent 6485997edc
commit 8cf0715cdc
11 changed files with 417 additions and 72 deletions
@@ -0,0 +1,66 @@
# Getting Started
Bootstrap the bindings from your game's entry point and drive a frame loop.
## Overview
A Playdate game has a single C entry point, `eventHandler`, which the
firmware calls with a `PlaydateAPI*` and an event code. Export it with
`@_cdecl`, call ``Playdate/initialize(with:)`` on the first event, and
install an update callback:
```swift
import CPlaydate
import PlayDate
@_cdecl("eventHandler")
func eventHandler(
pointer: UnsafeMutableRawPointer,
event: PDSystemEvent,
argument: UInt32
) -> Int32 {
if case .initialize = SystemEvent(event: event, argument: argument) {
Playdate.initialize(with: pointer) // must happen before anything else
Game.shared.start()
}
return 0
}
final class Game {
nonisolated(unsafe) static let shared = Game()
func start() {
Display.setRefreshRate(50)
System.setUpdateCallback {
self.update()
return true // true = redraw the display this frame
}
}
func update() {
let (_, pushed, _) = System.buttonState
if pushed.contains(.a) {
System.log("A pressed")
}
Graphics.clear(color: .white)
Graphics.drawText("Hello, Playdate", x: 8, y: 8)
System.drawFPS()
}
}
```
## Conventions to know
- **Initialization.** Calling any wrapper before
``Playdate/initialize(with:)`` is a programmer error and will crash.
- **Errors.** Fallible operations use typed throws — ``PlaydateError``
generally, ``Network/NetError`` for network I/O.
- **Ownership.** A wrapper that creates a C object frees it on `deinit`;
keep the wrapper referenced for as long as you use it. Wrappers vending
OS-owned objects don't free them — keep the owner alive instead, as
documented on each API.
- **Threading.** The Playdate runtime is single-threaded; don't call the
API from other threads.