https://github.com/ericlewis/swift-playdate
Swift package for building Playdate games & apps.
https://github.com/ericlewis/swift-playdate
playdate swift
Last synced: 10 months ago
JSON representation
Swift package for building Playdate games & apps.
- Host: GitHub
- URL: https://github.com/ericlewis/swift-playdate
- Owner: ericlewis
- Created: 2022-03-23T02:59:15.000Z (almost 4 years ago)
- Default Branch: main
- Last Pushed: 2022-10-11T10:21:50.000Z (over 3 years ago)
- Last Synced: 2025-03-28T02:23:26.153Z (10 months ago)
- Topics: playdate, swift
- Language: C
- Homepage:
- Size: 215 KB
- Stars: 43
- Watchers: 3
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Swift :heart: Playdate
Swift package & plugin for building games that run on [Playdate's](https://play.date) [simulator](https://sdk.play.date/1.9.3/#using-playdate-simulator).
### Some things to know:
- Requires XCode 13.3+
- Only tested on M1 Mac.
- Useful for exploring what swift development might be like, you cannot build for device (yet).
- This is highly experimental and likely to change - the swift wrapper is barely started.
- You will likely need to kill the simulator between runs, it doesn't seem to pick up on changes very well.
- The plugin isn't very stable / smart, but it can be made to be.
## Usage
`swift-playdate` can be used via [swift-package-manager](https://github.com/apple/swift-package-manager). It only requires a small bit of project structure.
- Must be a package based project with product type of dynamic.
- Must have a `Sources/Resources` folder with *at least* a valid `pdxinfo` file inside.
- note: other assets (images, sound, lua files) are to be added here too.
- Builds are handled via SPM:
- `swift package --disable-sandbox pdc`: creates a pdx file located at `.build/plugins/pdc/outputs/artifacts/{PACKAGE_DISPLAY_NAME}.pdx`
- `swift package --disable-sandbox pdc --run`: creates a pdx file & opens it in the simulator
- `--disable-sandbox` is required because we are using plugins outside their typical reach.
- Ideally swizzle the `EventCallback` in order to install an update handler.
## Example
```swift
import Playdate
// MARK: Game Loop
func updateCallback() -> Bool {
Graphics.clear(with: .white)
processInputs()
DisplayList.updateAndDrawSprites()
return true
}
func processInputs() {
let state = System.currentButtonState
player.move(
by: .init(
x: state.contains(.left) ? -10 : state.contains(.right) ? 10 : 0,
y: state.contains(.up) ? -10 : state.contains(.down) ? 10 : 0
)
)
}
// MARK: Setup
let image = Bitmap("images/player")
let player = Sprite()
func initialize() {
setupPlayer()
setupMenu()
}
func setupPlayer() {
player.setImage(image)
player.move(to: .init(x: image.size.width, y: image.size.height))
player.addToDisplayList()
}
func setupMenu() {
Menu.addCheckmarkItem("inverted", isOn: false) { isEnabled in
Display.isInverted = isEnabled
}
}
// MARK: Event Handler
@_dynamicReplacement(for: EventCallback(event:))
func eventCallback(event: SystemEvent) {
if event == .initialize {
initialize()
System.setUpdateCallback(updateCallback)
}
}
```
## Supported APIs
Below is a list of all the C apis & wether or not there is some sort of equivalent in `Playdate`.
### Display
|Status|Name|
|:-:|---|
|✅|getWidth|
|✅|getHeight|
|✅|setRefreshRate|
|✅|setInverted|
|✅|setScale|
|✅|setMosaic|
|✅|setFlipped|
|✅|setOffset|
### File
|Status|Name|
|:-:|---|
|🚧|geterr|
|🚧|stat|
|🚧|mkdir|
|🚧|unlink|
|🚧|rename|
|🚧|open|
|🚧|read|
|🚧|write|
|🚧|flush|
|🚧|tell|
|🚧|seek|
### Graphics
|Status|Name|
|:-:|---|
|✅|Clear|
|✅|setBackgroundColor|
|✅|setStencil|
|✅|setDrawMode|
|✅|setDrawOffset|
|✅|setClipRect|
|✅|setScreenClipRect|
|✅|clearClipRect|
|✅|setLineCapStyle|
|✅|setFont|
|✅|setTextTracking|
|✅|setTextLeading|
|✅|pushContext|
|✅|popContext|
#### Drawing
|Status|Name|
|:-:|---|
|✅|drawBitmap|
|✅|tileBitmap|
|✅|drawLine|
|🚧|fillTriangle|
|✅|drawRect|
|✅|fillRect|
|🚧|drawEllipse|
|🚧|fillEllipse|
|🚧|fillPolygon|
|✅|drawScaledBitmap|
|✅|drawText|
#### Bitmap
|Status|Name|
|:-:|---|
|✅|newBitmap|
|✅|freeBitmap|
|✅|loadBitmap|
|✅|copyBitmap|
|🚧|loadIntoBitmap|
|✅|getBitmapData|
|✅|clearBitmap|
|🚧|rotatedBitmap|
#### BitmapTable
|Status|Name|
|:-:|---|
|🚧|newBitmapTable|
|🚧|freeBitmapTable|
|🚧|loadBitmapTable|
|🚧|loadIntoBitmapTable|
|🚧|getBitmapTable|
#### Font
|Status|Name|
|:-:|---|
|🚧|loadFont|
|🚧|getFontPage|
|🚧|getPageGlyph|
|🚧|getGlyphKerning|
|🚧|getTextWidth|
#### Raw Framebuffer
|Status|Name|
|:-:|---|
|🚧|getFrame|
|🚧|getDisplayFrame|
|🚧|getDebugFrame|
|🚧|copyFrameBufferBitmap|
|🚧|markUpdatedRows|
|✅|display|
### JSON
Note: it may not be worth implementing these since we have JSONDecoder.
### Lua
|Status|Name|
|:-:|---|
|🚧|addFunction|
|🚧|registerClass|
|🚧|pushFunction|
|🚧|indexMetatable|
|🚧|start|
|🚧|stop|
|🚧|getArgCount|
|🚧|getArgCount|
|🚧|argIsNil|
|🚧|getArgBool|
|🚧|getArgInt|
|🚧|getArgFloat|
|🚧|getArgString|
|🚧|getArgBytes|
|🚧|getArgObject|
|🚧|getBitmap|
|🚧|getSprite|
|🚧|pushNil|
|🚧|pushBool|
|🚧|pushInt|
|🚧|pushFloat|
|🚧|pushString|
|🚧|pushBytes|
|🚧|pushBitmap|
|🚧|pushSprite|
|🚧|pushObject|
|🚧|retainObject|
|🚧|releaseObject|
|🚧|setObjectValue|
|🚧|getObjectValue|
|🚧|callFunction|
### Scoreboards
Note: these are not documented anywhere.
|Status|Name|
|:-:|---|
|🚧|addScore|
|🚧|getPersonalBest|
|🚧|freeScore|
|🚧|getScoreboards|
|🚧|freeBoardsList|
|🚧|getScores|
|🚧|freeScoresList|
### Sound
TODO
### Sprite
|Status|Name|
|:-:|---|
|✅|newSprite|
|✅|moveTo|
|✅|moveBy|
|✅|getPosition|
|✅|addSprite|
|✅|setImage|
|✅|freeSprite|
|🚧|copy|
|🚧|setBounds|
|🚧|getBounds|
|🚧|getImage|
|🚧|setSize|
|🚧|setZIndex|
|🚧|getZIndex|
|🚧|setTag|
|🚧|getTag|
|🚧|setDrawMode|
|🚧|setImageFlip|
|🚧|getImageFlip|
|🚧|setStencil|
|🚧|setStencilPattern|
|🚧|clearStencil|
|🚧|setClipRect|
|🚧|clearClipRect|
|🚧|setClipRectsInRange|
|🚧|clearClipRectsInRange|
|🚧|setUpdatesEnabled|
|🚧|updatesEnabled|
|🚧|setVisible|
|🚧|isVisible|
|🚧|setOpaque|
|🚧|setAlwaysRedraw|
|🚧|markDirty|
|🚧|addDirtyRect|
|🚧|setIgnoresDrawOffset|
|🚧|setUpdateFunction|
|🚧|setDrawFunction|
|🚧|setUserData|
|🚧|getUserData|
|🚧|removeSprite|
|🚧|removeSprites|
|🚧|removeAllSprites|
|🚧|getSpriteCount|
|🚧|drawSprites|
|✅|updateAndDrawSprites|
|🚧|resetCollisionWorld|
|🚧|setCollisionsEnabled|
|🚧|collisionsEnabled|
|🚧|setCollideRect|
|🚧|getCollideRect|
|🚧|clearCollideRect|
|🚧|setCollisionResponseFunction|
|🚧|checkCollisions|
|🚧|moveWithCollisions|
|🚧|querySpritesAtPoint|
|🚧|querySpritesInRect|
|🚧|querySpritesAlongLine|
|🚧|querySpriteInfoAlongLine|
|🚧|overlappingSprites|
|🚧|allOverlappingSprites|
### System
|Status|Name|
|:-:|---|
|✅|realloc|
|✅|error|
|✅|logToConsole|
|✅|error|
#### Menu
|Status|Name|
|:-:|---|
|✅|addMenuItem|
|✅|addCheckmarkMenuItem|
|✅|addOptionsMenuItem|
|✅|removeMenuItem|
|✅|removeAllMenuItems|
|❌|getMenuItemTitle|
|❌|getMenuItemValue|
|❌|setMenuItemValue|
|❌|getMenuItemUserData|
|❌|setMenuItemUserData|
|✅|setMenuImage|
#### Miscellaneous
|Status|Name|
|:-:|---|
|✅|getCurrentTimeMilliseconds|
|✅|getSecondsSinceEpoch|
|✅|resetElapsedTime|
|✅|getElapsedTime|
|✅|getFlipped|
|✅|getReduceFlashing|
|❌|formatString|
|✅|setUpdateCallback|
|✅|drawFPS|
|✅|getBatteryPercentage|
|✅|getBatteryVoltage|
|✅|getLanguage|
|✅|setPeripheralsEnabled|
|✅|getAccelerometer|
|✅|getButtonState|
|✅|getCrankAngle|
|✅|getCrankChange|
|✅|getCrankDocked|
|✅|setAutoLockDisabled|
|✅|setCrankSoundDisabled|