├── support └── .gitkeep ├── source ├── images │ └── .gitkeep ├── sounds │ └── .gitkeep ├── system-assets │ ├── card.png │ └── launchImage.png ├── pdxinfo ├── crank.lua ├── lifecycle.lua ├── main.lua ├── simulator.lua └── button.lua ├── .gitignore ├── .vscode ├── settings.json └── tasks.json ├── .luacheckrc ├── .nova └── Tasks │ └── Playdate Simulator.json ├── makefile ├── .github └── workflows │ └── main.yml ├── LICENSE.md └── README.md /support/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /source/images/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /source/sounds/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.pdx/ -------------------------------------------------------------------------------- /source/system-assets/card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bedinotti/playlate/HEAD/source/system-assets/card.png -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Lua.diagnostics.globals": [ 3 | "import", 4 | "playdate" 5 | ] 6 | } -------------------------------------------------------------------------------- /source/system-assets/launchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bedinotti/playlate/HEAD/source/system-assets/launchImage.png -------------------------------------------------------------------------------- /.luacheckrc: -------------------------------------------------------------------------------- 1 | std = "lua54" 2 | globals = { 3 | "playdate", 4 | "game" 5 | } 6 | read_globals = { 7 | "import" 8 | } 9 | -------------------------------------------------------------------------------- /source/pdxinfo: -------------------------------------------------------------------------------- 1 | name=Template 2 | author=You, Inc. 3 | description=A basic game template. 4 | bundleID=com.yourcompany.TemplateGame 5 | version=1.0 6 | buildNumber=100 7 | imagePath=system-assets 8 | -------------------------------------------------------------------------------- /.nova/Tasks/Playdate Simulator.json: -------------------------------------------------------------------------------- 1 | { 2 | "extensionTemplate" : "simulator", 3 | "extension" : { 4 | "name" : "Playdate", 5 | "identifier" : "com.panic.Playdate" 6 | }, 7 | "identifier" : "EA7875DC-3ABA-42BB-976B-9F348052F6C7" 8 | } -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | .PHONY: clean 2 | .PHONY: build 3 | .PHONY: run 4 | .PHONY: copy 5 | 6 | SDK = $(shell egrep '^\s*SDKRoot' ~/.Playdate/config | head -n 1 | cut -c9-) 7 | SDKBIN=$(SDK)/bin 8 | GAME=$(notdir $(CURDIR)) 9 | SIM=Playdate Simulator 10 | 11 | 12 | build: clean compile run 13 | 14 | run: open 15 | 16 | clean: 17 | rm -rf '$(GAME).pdx' 18 | 19 | compile: Source/main.lua 20 | "$(SDKBIN)/pdc" 'Source' '$(GAME).pdx' 21 | 22 | open: 23 | open -a '$(SDKBIN)/$(SIM).app/Contents/MacOS/$(SIM)' '$(GAME).pdx' 24 | -------------------------------------------------------------------------------- /source/crank.lua: -------------------------------------------------------------------------------- 1 | -- All the callbacks for the crank. 2 | -- See https://sdk.play.date/1.9.3/Inside%20Playdate.html#_crank_callbacks for more information 3 | 4 | local prefix = "[Crank] " 5 | 6 | --- Called when the crank moves. 7 | --- @param change number How much the crank moved, in degrees. Negative values are anti-clockwise. 8 | --- @param acceleratedChange number How much the crank moved, scaled by how fast it was moved. 9 | function playdate.cranked(change, acceleratedChange) 10 | local log = string.format( 11 | "Crank rotated %.4f degrees clockwise (%.4f degrees accelerated).", 12 | change, 13 | acceleratedChange 14 | ) 15 | print(prefix .. log) 16 | end 17 | 18 | --- Called when the crank is docked. 19 | function playdate.crankDocked() 20 | print(prefix .. "Crank docked.") 21 | end 22 | 23 | --- Called when the crank is undocked. 24 | function playdate.crankUndocked() 25 | print(prefix .. "Crank undocked.") 26 | end 27 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: Luacheck 4 | 5 | # Controls when the workflow will run 6 | on: 7 | # Triggers the workflow on push or pull request events but only for the main branch 8 | push: 9 | branches: [ main ] 10 | pull_request: 11 | branches: [ main ] 12 | 13 | # Allows you to run this workflow manually from the Actions tab 14 | workflow_dispatch: 15 | 16 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 17 | jobs: 18 | # This workflow contains a single job called "build" 19 | build: 20 | # The type of runner that the job will run on 21 | runs-on: ubuntu-latest 22 | 23 | # Steps represent a sequence of tasks that will be executed as part of the job 24 | steps: 25 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 26 | - uses: actions/checkout@v2 27 | 28 | - uses: nebularg/actions-luacheck@v1 29 | with: 30 | files: source/ 31 | args: -qo 011 32 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | Copyright © 2022 Chris Downie 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /source/lifecycle.lua: -------------------------------------------------------------------------------- 1 | -- All callbacks for the app and game lifecycle. 2 | -- See https://sdk.play.date/1.9.3/Inside%20Playdate.html#game-lifecycle for more information 3 | 4 | local prefix = "[Lifecycle] " 5 | 6 | -- 7 | -- System lifecycle callbacks 8 | -- 9 | 10 | --- Called before the system pauses the game. 11 | --- This is a good time to update the [menu image](https://sdk.play.date/1.9.3/Inside%20Playdate.html#f-setMenuImage). 12 | function playdate.gameWillPause() 13 | print(prefix .. "Game will pause...") 14 | end 15 | 16 | --- Called before the system resumes the game. 17 | function playdate.gameWillResume() 18 | print(prefix .. "Game will resume...") 19 | end 20 | 21 | --- Called when the player chooses to exit the game via the System Menu or Menu button. 22 | function playdate.gameWillTerminate() 23 | print(prefix .. "Game will terminate...") 24 | end 25 | 26 | -- 27 | -- Device callbacks 28 | -- 29 | 30 | --- Called when the device is unlocked, if your game is running. 31 | function playdate.deviceDidUnlock() 32 | print(prefix .. "Device did unlock.") 33 | end 34 | 35 | --- Called when the device is locked, if your game is running. 36 | function playdate.deviceWillLock() 37 | print(prefix .. "Device will lock...") 38 | end 39 | 40 | --- Called before the device goes to low-power sleep mode because of a low battery. 41 | function playdate.deviceWillSleep() 42 | print(prefix .. "Device will sleep...") 43 | end 44 | -------------------------------------------------------------------------------- /source/main.lua: -------------------------------------------------------------------------------- 1 | -- Common CoreLibs imports. 2 | import "CoreLibs/object" 3 | import "CoreLibs/graphics" 4 | import "CoreLibs/sprites" 5 | import "CoreLibs/timer" 6 | 7 | -- Project imports 8 | import "button" 9 | import "crank" 10 | import "lifecycle" 11 | import "simulator" 12 | 13 | -- Use common shorthands for playdate code 14 | local gfx = playdate.graphics 15 | 16 | --- By convention, most games need to perform some initial setup when they're 17 | --- initially launched. Perform that setup here. 18 | --- 19 | --- Note: This will be called exactly once. If you're looking to do something 20 | --- whenever the game is resumed from the background, see playdate.gameWillResume 21 | --- in lifecycle.lua 22 | local function gameDidLaunch() 23 | print(playdate.metadata.name .. " launched!") 24 | 25 | gfx.setBackgroundColor(gfx.kColorBlack) 26 | end 27 | gameDidLaunch() 28 | 29 | --- This update method is called once per frame. 30 | function playdate.update() 31 | -- Example code. Draw a full-screen rectangle and the frames per second 32 | gfx.fillRect(0, 0, 400, 240) 33 | playdate.drawFPS(0,0) 34 | 35 | -- Update and draw all sprites. Calling this method in playdate.update 36 | -- is generally what you want, if you're using sprites. 37 | -- See https://sdk.play.date/1.9.3/#f-graphics.sprite.update for more info 38 | gfx.sprite.update() 39 | 40 | -- Update all timers once per frame. This is required if you're using 41 | -- timers in your game. 42 | -- See https://sdk.play.date/1.9.3/#f-timer.updateTimers for more info 43 | playdate.timer.updateTimers() 44 | end 45 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Build and Run", 8 | "type": "shell", 9 | "command": "make build", 10 | "problemMatcher": { 11 | "owner": "lua", 12 | "fileLocation": ["relative", "${workspaceFolder}"], 13 | "pattern": { 14 | // Example: error: Source/main.lua:14: '>' expected near 'st' 15 | "regexp": "^(warning|error): (.*):(\\d+):\\s+(.*)$", 16 | "severity": 1, 17 | "file": 2, 18 | "line": 3, 19 | "message": 4 20 | } 21 | }, 22 | "group": { 23 | "kind": "build", 24 | "isDefault": true 25 | } 26 | }, 27 | { 28 | "label": "Run", 29 | "type": "shell", 30 | "command": "make run", 31 | "problemMatcher": [] 32 | }, 33 | { 34 | "label": "Compile", 35 | "type": "shell", 36 | "command": "make compile", 37 | "problemMatcher": { 38 | "owner": "lua", 39 | "fileLocation": ["relative", "${workspaceFolder}"], 40 | "pattern": { 41 | "regexp": "^(warning|error): (.*):(\\d+):\\s+(.*)$", 42 | "severity": 1, 43 | "file": 2, 44 | "line": 3, 45 | "message": 4 46 | } 47 | }, 48 | }, 49 | { 50 | "label": "Clean", 51 | "type": "shell", 52 | "command": "make clean", 53 | "problemMatcher": [] 54 | }, 55 | ] 56 | } -------------------------------------------------------------------------------- /source/simulator.lua: -------------------------------------------------------------------------------- 1 | -- This file contains methods that are only called when running in the Simulator. 2 | -- See https://sdk.play.date/1.9.3/#_simulator_debug_callbacks for more information 3 | 4 | local prefix = "[Simulator] " 5 | 6 | --- Lets you act on keyboard key presses when running in the Simulator ONLY. 7 | --- These can be useful for adding debugging functions that can be enabled 8 | --- via your keyboard. 9 | --- 10 | --- @param key string The character pressed on the keyboard, if unused by the Simulator. 11 | function playdate.keyPressed(key) 12 | print(prefix .. string.format("Pressed %s key", key)) 13 | end 14 | 15 | --- Lets you act on keyboard key releases when running in the Simulator ONLY. 16 | --- These can be useful for adding debugging functions that can be enabled 17 | --- via your keyboard. 18 | --- 19 | --- @param key string The character released on the keyboard, if unused by the Simulator. 20 | function playdate.keyReleased(key) 21 | print(prefix .. string.format("Released %s key", key)) 22 | end 23 | 24 | --- Called immediately after `playdate.update()`, any drawing performed during 25 | --- this callback is overlaid on the display in 50% transparent red (or another 26 | --- color selected with `playdate.setDebugDrawColor()`). 27 | --- 28 | --- White pixels are drawn in the debugDrawColor. Black pixels are transparent. 29 | function playdate.debugDraw() 30 | playdate.graphics.pushContext() 31 | -- Change the color of all our debug drawing. Default is red 32 | -- Use this line to change the debug color (this one is hot pink @ 30%) 33 | -- playdate.setDebugDrawColor(0.9, 0.3, 0.96, 0.3) 34 | 35 | -- Then perform anything you'd like overlayed on the screen 36 | -- playdate.graphics.drawRect(20, 20, 150, 100) 37 | 38 | -- To show text, you need to change the draw mode. Default text is drawn as 39 | -- black, which is treated as transparent in `debugDraw` 40 | -- playdate.graphics.setImageDrawMode(playdate.graphics.kDrawModeFillWhite) 41 | -- playdate.graphics.drawText("hello", 0, 10) 42 | playdate.graphics.popContext() 43 | end 44 | -------------------------------------------------------------------------------- /source/button.lua: -------------------------------------------------------------------------------- 1 | -- All the callbacks for button presses. 2 | -- See https://sdk.play.date/1.9.3/Inside%20Playdate.html#buttonCallbacks for more information 3 | 4 | local prefix = "[Button] " 5 | 6 | -- 7 | -- A Button 8 | -- 9 | 10 | --- Called immediately when the user presses the "A" button. 11 | function playdate.AButtonDown() 12 | print(prefix .. "A button pressed down.") 13 | end 14 | 15 | --- Called after the "A" button is held for one second. 16 | function playdate.AButtonHeld() 17 | print(prefix .. "A button held down for one second.") 18 | end 19 | 20 | --- Called immediately after the user releases the "A" button 21 | function playdate.AButtonUp() 22 | print(prefix .. "A button released.") 23 | end 24 | 25 | -- 26 | -- B Button 27 | -- 28 | 29 | --- Called immediately when the user presses the "B" button. 30 | function playdate.BButtonDown() 31 | print(prefix .. "B button pressed down.") 32 | end 33 | 34 | --- Called after the "B" button is held for one second. 35 | function playdate.BButtonHeld() 36 | print(prefix .. "B button held down for one second.") 37 | end 38 | 39 | --- Called immediately after the user releases the "B" button 40 | function playdate.BButtonUp() 41 | print(prefix .. "B button released.") 42 | end 43 | 44 | -- 45 | -- D-pad buttons 46 | -- 47 | 48 | --- Called immediately after the player presses the down direction on the d-pad. 49 | function playdate.downButtonDown() 50 | print(prefix .. "Down button pressed.") 51 | end 52 | 53 | --- Called immediately after the player releases the down direction on the d-pad. 54 | function playdate.downButtonUp() 55 | print(prefix .. "Down button released.") 56 | end 57 | 58 | --- Called immediately after the player presses the left direction on the d-pad. 59 | function playdate.leftButtonDown() 60 | print(prefix .. "Left button pressed.") 61 | end 62 | 63 | --- Called immediately after the player releases the left direction on the d-pad. 64 | function playdate.leftButtonUp() 65 | print(prefix .. "Left button released.") 66 | end 67 | 68 | --- Called immediately after the player presses the right direction on the d-pad. 69 | function playdate.rightButtonDown() 70 | print(prefix .. "Right button pressed.") 71 | end 72 | 73 | --- Called immediately after the player releases the right direction on the d-pad. 74 | function playdate.rightButtonUp() 75 | print(prefix .. "Right button released.") 76 | end 77 | 78 | --- Called immediately after the player presses the up direction on the d-pad. 79 | function playdate.upButtonDown() 80 | print(prefix .. "Up button pressed.") 81 | end 82 | 83 | --- Called immediately after the player releases the up direction on the d-pad. 84 | function playdate.upButtonUp() 85 | print(prefix .. "Up button released.") 86 | end 87 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Playlate 2 | [Playdate](https://play.date) + template = Playlate 3 | 4 | Use this template to explore the [Playdate SDK](https://play.date/dev/) and get 5 | to building your game faster. 6 | 7 | 8 | ## How to Use 9 | 10 | Use this project to get started, then add your code and/or remove the bits you don't need. You can either use this template: 11 | 12 | - directly on GitHub, or 13 | - by downloading the zip file for this repo. 14 | 15 | ### On GitHub 16 | This repo is a GitHub Template. Click "Use this template" in the top right to 17 | create your own repository based off of the code here. See [Creating a Repository from a Template](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template) 18 | for more information. 19 | 20 | ### From ZIP File 21 | You can also download a zip of this repository and start there. Head on over to 22 | [the Releases] area of this repo and download the latest version. Or, if you're 23 | feeling brave, download the latest by clicking `Code > Download ZIP`. 24 | 25 | 26 | ## Features 27 | 28 | This builds off of the "Game Template" project provided in 29 | [the Playdate SDK](https://play.date/dev/) and adds a few nifty features. 30 | 31 | ### Standardized Structure 32 | This template uses the [recommended folder structure](https://sdk.play.date/1.9.3/Inside%20Playdate.html#_structuring_your_project) 33 | for Playdate games. Empty folders are preserved with an empty `.gitkeep` file 34 | that can be deleted if you'd like. 35 | 36 | ### Default Callbacks 37 | The Playdate SDK calls a few callbacks based on user interaction, the state of 38 | the device, and other game lifecycle events. Each of these have been implemented 39 | with a default implementation that prints out that each method has been called. 40 | 41 | ### Nova Features 42 | For folks who use [Nova](https://nova.app), you've got a few extra goodies: 43 | - A Playdate Simulator Task, to easily build & run your game. 44 | - A `.luacheckrc` file for linting your lua code with the [Luacheck Extension](nova://extension/?id=pro.albright.luacheck&name=Luacheck). 45 | 46 | ### VSCode Features 47 | Prefer to use [Visual Studio Code](https://code.visualstudio.com)? You get some 48 | goodies too: 49 | - Added Compile, Run, Build and Clean tasks, with a default Build task. 50 | - Updated settings to work with the [lua-language-server extension](https://marketplace.visualstudio.com/items?itemName=sumneko.lua). 51 | 52 | ### GitHub `luacheck` Action 53 | This also ships with a GitHub Action that runs [the `luacheck` code linter](https://github.com/lunarmodules/luacheck) 54 | on your code before merging to the `main` branch. 55 | 56 | ## License 57 | 58 | This is licensed under the MIT License. See [LICENSE.md](LICENSE.md) for more 59 | details. Generally: anything you build with this is yours. 60 | 61 | This template only works with the Playdate SDK. Make sure you follow the terms 62 | of the [Playdate SDK License](https://play.date/dev/sdk-license) when building 63 | your games. 64 | --------------------------------------------------------------------------------