---
name: wintermuted/playdate-sdk-core
source: https://app.decimal.ai/s/wintermuted-playdate-sdk-core@1/SKILL.md
source_sha256: 86f1e8c9d50f
---

# Playdate SDK Core — Lua Development Patterns

## Runtime Environment

Playdate games run Lua 5.4 on-device via the Playdate SDK runtime. The same Lua 5.4 interpreter runs on desktop for unit tests, but the `playdate.*` API is absent on desktop.

Key consequence: **never call `playdate.*` APIs in models or systems**. Those modules must be importable and testable on desktop Lua without a simulator.

## Global Module Pattern

The Playdate SDK uses `import` (not `require`). Imported modules declare a global table:

```lua
-- src/models/Actor.lua
Actor = {}
Actor.__index = Actor

function Actor.new(def)
  local a = setmetatable({}, Actor)
  a.name = def.name
  a.maxHP = def.maxHP
  a.hp = def.maxHP
  return a
end

function Actor:isDead()
  return self.hp <= 0
end
```

Callers reference the global directly after `import`:

```lua
import "models/Actor"   -- declares global Actor
local hero = Actor.new(PARTY_DATA.player)
```

## Import Paths

- `import` resolves relative to the project `src/` root (the path passed to `pdc`)
- Use forward slashes; no `.lua` extension needed
- Example: `import "core/StateMachine"` loads `src/core/StateMachine.lua`
- CoreLibs are imported as: `import "CoreLibs/sprites"`, `import "CoreLibs/graphics"`

## pdxinfo

`pdxinfo` is a key=value metadata file at the project root (not inside `src/`):

```
name=My Game
author=Your Name
description=Short description
bundleID=com.yourname.mygame
version=1.0
buildNumber=1
imagePath=images/launcher
```

Required fields: `name`, `bundleID`, `version`. Increment `buildNumber` on each release.

## Lua 5.4 Notes

- Integer division: `//` (e.g. `7 // 2 == 3`)
- `table.move`, `string.pack/unpack`, `utf8` library are available
- No `io.popen` or `os.execute` on-device
- `math.random` / `math.randomseed` available; seed from `playdate.getSecondsSinceEpoch()` on-device
- `print()` writes to the Playdate console (visible in the simulator's console panel)
- Metatables and `__index` work identically to standard Lua 5.4

## Common Pitfalls

- Do not use `require` — the Playdate runtime uses `import`
- Do not use `local` for module tables you intend to import — they must be global
- `import` is idempotent; importing the same file twice is safe
- Desktop Lua does not have `playdate.*` — guard any on-device-only code with a nil check: `if playdate then ... end`