Add master renders for the canal, gatling, scrapper and surveillance enemies and repack their optimized assets alongside a re-optimized surge card.
DeckBuilder
A minimal portrait 2D deck builder boilerplate for Godot 4.6, configured for iOS release (and web-canvas prototyping — both use the GL Compatibility renderer).
What's in the box
A playable one-enemy combat loop:
- Draw 5 cards each turn, 3 energy.
- Strike (attack), Defend (skill/block), Bash (heavy attack).
- Tap/click a card to play it; "End Turn" lets the enemy hit you.
- Auto-reshuffle the discard pile, win/lose detection.
Project layout
project.godot Portrait config + GameState autoload + GL Compatibility renderer
icon.svg
scenes/
main.tscn Combat screen layout (HUD, hand, end-turn button)
card.tscn Reusable card widget (cost / name / description)
scripts/
game_state.gd Autoload singleton — ALL game logic, signal-driven (no UI in here)
card_data.gd CardData resource — the data shape of a card
card_database.gd Builds the starting deck in code
card.gd Card widget behaviour (emits `played` on tap)
main.gd Wires HUD + dynamic hand to GameState signals
The architecture keeps logic and presentation separate: game_state.gd is
pure state + signals, the UI only reads state and listens for hand_changed /
stats_changed / combat_ended. That makes the rules easy to unit-test and the
UI easy to replace.
Run it
godot project.godot # opens the editor
godot # runs the main scene directly
The desktop window opens at 540×960 (a half-scale portrait preview); the design resolution is 1080×1920.
Configuration already set for mobile
In project.godot:
display/window/handheld/orientation=1— portrait locked.window/stretch/mode="canvas_items",aspect="expand"— scales the 1080×1920 design across iPhone aspect ratios.renderer/rendering_method="gl_compatibility"— runs on iOS, Android, and the Web canvas export, so the same project prototypes in a browser and ships to the App Store.
Web (canvas) build — test on iOS over Tailscale
godot --headless --export-release "Web" build/web/index.html # build the canvas export
bun serve.mjs # serve build/web on 0.0.0.0:8088
The Web preset has thread support disabled (no SharedArrayBuffer / COEP
headers needed). But Godot's web runtime still requires a secure context, so
it must be served over HTTPS (plain HTTP fails with "Secure Context ...
use HTTPS"). serve.mjs serves HTTPS on :8443 using a self-signed cert.
One-time: trust the dev cert on iOS
The cert lives in certs/ (generate it once — see below). On your iPhone:
- Open
http://100.64.0.2:8088/certin Safari → “Allow” the profile download. - Settings → General → VPN & Device Management → install the DeckBuilder Dev profile.
- Settings → General → About → Certificate Trust Settings → toggle it on.
Then open the game at https://100.64.0.2:8443/ (or
https://desktop.ts.local:8443/ if MagicDNS resolves on the phone). Tap once to
start (iOS needs a gesture for audio).
Play offline (add to Home Screen)
The web build is an installable PWA, so it runs even when this Mac/PC (the
server) is off. Open the HTTPS URL once while the server is up, let it finish
loading, then Share → Add to Home Screen. Launch it from the home-screen
icon and it starts offline from cache (portrait, standalone, no Safari chrome).
One loaded visit is enough to cache it; rebuilding (bb web) re-caches on the
next online launch. See AGENTS.md → Offline (installable PWA) for how it works.
Generate the cert (once)
mkdir -p certs
openssl req -x509 -newkey rsa:2048 -nodes \
-keyout certs/key.pem -out certs/cert.pem -days 824 \
-subj "/CN=DeckBuilder Dev" \
-addext "subjectAltName=IP:100.64.0.2,DNS:desktop.ts.local,DNS:desktop" \
-addext "extendedKeyUsage=serverAuth" \
-addext "basicConstraints=critical,CA:TRUE"
Replace the IP/DNS with your own Tailscale address. Re-run the export + restart
serve.mjs after code changes to refresh the build.
Exporting to iOS
- Web prototype loop (no Mac needed):
Project → Export → Add → Web, then run the.htmllocally to iterate fast. - On-device test (free Apple ID, sideload):
Project → Export → Add → iOS, set a unique Bundle Identifier (e.g.com.you.deckbuilder), export the Xcode project, open it in Xcode on a Mac, pick your personal team, and Run. - App Store release: paid Apple Developer account ($99/yr), then archive + upload via Xcode / TestFlight for review.
iOS export templates must be installed:
Editor → Manage Export Templates.
Extending it
- New cards: add them in
card_database.gd, or create.tresfiles from theCardDataresource and load them from aresources/cards/folder. - New effects: extend the
match card.card_typeblock ingame_state.gd::play_card(add a newCardData.Type). - More enemies / map / relics: add new autoload state or scenes; keep logic in plain scripts and let scenes subscribe to signals.