Docs

Twine

Install and make Twine yours, the arcade game in SwiftUI + Metal. Version 1.0.0.

A one-touch arcade run cut from washi paper: lift the blue kite, and the red one copies you a beat later in the sky below. This guide takes you from download to a running game under your own name. It covers version 1.0.0. See the screens on its game page.

Requirements

  • Xcode 26 and an iOS 17.0 or later deployment target
  • Tuist 4 (brew install tuist)
  • An Apple Developer team for devices, Game Center, iCloud and the widget. The simulator runs without one.

Install

Download

Included with SwiftPieces Games. Not signed in? The button takes you to sign in or create an account, then starts the download when you're back. Unzip the archive; it contains one folder, Twine/.

Make it yours

cd Twine
scripts/setup.sh --name YourGame --bundle-id com.you.yourgame

The script renames the target, scheme and bundle ids, rewrites the StoreKit product ids and runs tuist generate. To keep the name Twine for now, run tuist generate instead.

Run it

Open YourGame.xcworkspace, choose an iPhone simulator and run the YourGame scheme. The scheme uses Configuration/Products.storekit, so the shop works before App Store Connect is set up.

What's in the project

  • Content: Endless, with a tuned curve
  • Game Center: 3 leaderboards, 19 achievements
  • Shop: Continue tokens (spools), Mission pass, Cosmetic pack
  • Built on: GameCore, Feel, GameServices, Shaders, GameUI
  • Presets: shore, paddies, lanterns
  • Swift: 8,600 lines in 81 files

Rebrand options

OptionWhat it sets
--nameTarget, scheme and product name
--bundle-idBundle id. Modules, the widget, the App Group (group.<bundle-id>) and tests derive theirs from it
--display-nameThe name under the icon
--teamYour team id. Required for devices, Game Center, iCloud and the widget's App Group
--product-prefixApp Store Connect product ids. Defaults to the bundle id

The values live in Tuist/ProjectDescriptionHelpers/AppConfig.swift. Game Center ids are listed in Configuration/GameCenter.json (three leaderboards, nineteen achievements); create them under your app in App Store Connect. Products are in Configuration/Products.storekit, which the scheme uses for local purchases.

Structure

App/                  @main, the root stage (Metal world + phase layer), the tab hub, deep links
Features/Play         In-flight HUD, pause and re-tie panels
Features/Results      The results sequence, hanko seals, the reminders ask
Features/Home         Home over the attract loop, the daily gift sheet
Features/Shed         Kite shapes and papers over the Kite Shed showcase
Features/Missions     Kite Club rank and the mission board
Features/Shop         Spools, the Mission Pass and the Lantern Festival pack
Features/Logbook      Best flight, lifetime totals, commendations, leaderboards
Features/Settings     Sound, haptics, motion, contrast, colour vision, assist, restore, credits
Modules/GameCore      Fixed-step clock, seeded RNG, daily seed, saves, event ring, synth (no game types)
Modules/GameDesign    GameTheme tokens, variants, washi shaders and the component kit
Modules/TwineKit      The simulation: two kites, flock course generator, wind, ghost, missions, profile, catalog
Modules/TwineRender   MTKView renderer: world, instanced entities, uber-post, quality tiers
Modules/Feel          Sound bank, audio engine, haptic patterns
Modules/GameServices  Game Center, StoreKit 2, iCloud sync, reminders
Modules/Session       GameSession (phases and low-frequency state) and the JuiceDirector
Widget/               The Daily Run widget. Shared/ holds what it shares with the app
Design/StyleSpec.md   The art direction: pillars, inks, type, motion, sound
Tests/                Swift Testing: simulation, course, balance, meta and sound

How it runs

  • The simulation (World.step) is plain Swift at a fixed 120 Hz with a seeded RNG; the renderer interpolates. SwiftUI only sees GameSession, which publishes the HUD when a visible value changes, never per frame.
  • The sim emits TwineEvents; the JuiceDirector turns each into its feedback stack (rings, paper scraps, shake, flash, koto plucks on a yo scale, haptic, hanko seal), scaled by how rare the event is.
  • The renderer is mounted once. Pausing flips the phase and dims the world; it never tears down.
  • The look is a theme: change GameTheme.twine (inks, type, radii, motion, sound) and both the SwiftUI screens and the Metal uniforms follow.

Tuning and the difficulty curve are documented in BALANCE.md.

Licenses

Shippori Mincho (bundled as a subset) is under the SIL Open Font License 1.1 (Licenses/). Everything else in the project is yours to ship with your game. See ASSET_MANIFEST.md.

Changelog

1.0.0

2026-10-30

  • The Sakura palette: blossom-pink, apricot and plum-night skies fading to warm cream, over lilac, rose and violet paper hills.
  • First release: two kites on one hand, cut from washi paper, with SwiftUI meta screens over a Metal world.
  • Hold to lift the indigo kite; the vermilion kite copies the move 0.65 s later in the lower sky. Flocks of paper birds guard the gaps in each sky.
  • A festival kid in an indigo happi coat and hachimaki flies the pair from the dune, both hands on a wooden reel.
  • Endless procedural course across three sheets (Shore, Paddies, Lanterns) with a tuned speed and difficulty curve, grazes, twins, wind and gusts.
  • Daily Run: one seeded course a day for everyone, with your best flown back as a ghost kite, a streak and a Home Screen widget.
  • Six cosmetic kite shapes and eight papers in the Kite Shed, missions with Kite Club ranks, a seven-day gift sheet and nineteen achievements.
  • StoreKit 2 stall: spool packs, the Mission Pass and the Lantern Festival pack, with restore and a local StoreKit configuration.
  • Game Center leaderboards and achievements, iCloud save sync, Game Mode, 120 Hz, thermal tiers, Reduce Motion, contrast, colour-vision and Assist options.
  • Every sound synthesised on the device, koto included; every surface drawn in shaders.