A match-3 game that generates its own music in real time, in C, on the audio thread, and ships as four visually and sonically distinct products from a single binary and a single set of JSON files.
The game is the surface. What is underneath is a configurable app framework with a real-time synthesis engine in it.
The game was built for people living with dementia, and their caregivers. My wife had Alzheimer's, and a match-three game was one of the last things she could still do on her own, until it started running out of lives and showing her a countdown.
That brief is why the architecture looks the way it does. No lives, no timers, no fail states, no ads, no purchases, no accounts. Removing failure removes the need for most of the systems a casual game usually ships, and it forces the interest to come from somewhere else.
Difficulty steps down. A single comfort control bundles board size, color count, the specials roster, tempo ceiling, hint timing and language tier. The design rule for every feature was that it still gives something at the lowest setting, or it turns off.
Sound has three states, chosen by the player: off, conventional game sounds, or music. The first two are what a casual game normally ships, a set of recorded effect samples triggered on events. The third replaces them entirely.
In music mode there are no music files. Every note, drum hit and echo is generated sample by sample while you play, and the effect samples step aside so the score is what you hear.
Both drive the same voice architecture: 24 melody voices, 4 harmony and pad voices, 4 chime voices, 4 drum voices, each with its own envelope, pan and filter state.
Drums are synthesized from primitives too, a pitch sweep and a noise burst and an envelope per voice, with three distinct kits defined as data rather than code.
Cross-feedback with per-repeat damping. The delay time is derived from the current musical tempo and glides toward it, so as the game's pace drifts the repeats bend in pitch like tape catching up.
The engine has a music-theory layer: a scale ladder, chord tones, phrase grids, quantization, and a real V–I cadence that resolves at the end of each cycle. Gameplay events are mapped onto it musically rather than as sound effects.
Every visual, verbal, musical and pacing decision is resolved through a single lookup point that reads JSON. There is no compiled-in brand.
A skin file defines up to 16 sections: typography, palette, board geometry, sky gradients, world treatment, art sets, HUD, objectives, music, pacing, and language.
The second identity's palette was built by studying a specific catalog of industrial and electronic records, analyzing the drum programming, detuning, delay behavior and arrangement dynamics that make those records work, then rebuilding them from synthesis primitives. Nothing is sampled. It is reference, not reproduction.
Wordless mode, larger pieces, fewer colors and calmer pacing are not a settings screen bolted on. They are the same skin and preset machinery the four products are built from.
Core Haptics patterns share the same geometric vocabulary as the audio. A blast's shape becomes a haptic envelope the same way it becomes a musical figure. A radial blast is a crack over a short rumble, because a single transient can never read as an explosion. A cross is three transients departing, each sharper than the last. A color-clear is a rising rumble driven by a parameter curve, ending in an arrival.
Two decisions worth noting because they are decisions not to build:
Haptics also fire before the audio branch, so they work with sound off.
The world layer is a cumulative day cycle with CG-rendered sky gradients, a sun that tracks progress across the header, a moon rendered per day with a real terminator (a lit-limb arc and a swept half-ellipse, mirrored for waning phases), and seasonal tinting. All of it derives from constants, so no calendar literal is hard-coded anywhere.
There is no test framework. A real-time audio engine and a physics-adjacent board do not submit to unit tests easily. Instead:
| Language and frameworks | Objective-C, SpriteKit, AVAudioEngine, Core Haptics, Core Graphics |
| Platforms | iOS and macOS from one project, one shared source set |
| Shared source | ~15,300 lines. Audio engine 4,727, scene 5,547, settings 2,070, skin layer 893, haptics 464 |
| Audio | AVAudioSourceNode render callback, C11 atomics, lock-free note queue, 36 concurrent voices |
| Synthesis | Karplus–Strong physical model, PolyBLEP saw through a state-variable filter, synthesized drum kits, tempo-synced stereo delay |
| Products | 4 skins from one binary, up to 16 config sections each, 44 language overrides per skin, nested movement overrides |
| Distinctive | Generative score driven by board position, blast geometry shared between audio and haptics, accessibility implemented as the configuration system |