Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Accessible Hyper-Twister Builder Spike

A focused macOS spike for testing an accessible coaster-builder architecture inspired by OpenRCT2. The app builds one representative Hyper-Twister style coaster, renders it with SDL, and exposes a Swift/AppKit accessibility overlay for keyboard control, VoiceOver navigation, and spoken feedback.

This is not a full OpenRCT2 build and does not bundle RollerCoaster Tycoon assets.

Demo Video

A short web-friendly demo video is included at:

media/hyper-twister-validated-fullscreen-demo-web.mp4

It shows the validated closed-coaster recipe being built and the test train running. The MP4 is compressed for browser playback. Raw screen recordings and build outputs are intentionally not committed.

What It Demonstrates

  • C++ owns the coaster builder state, placement rules, completion guidance, metrics, sounds, and SDL rendering.
  • SDL is used only as the display and audio driver. Gameplay input events from SDL are disabled.
  • Swift/AppKit owns keyboard input and accessibility through an NSPanel.
  • Swift sends builder commands directly to C++ through a C bridge.
  • C++ sends semantic state back to Swift as JSON.
  • Swift updates native accessibility elements so VoiceOver can inspect builder state.
  • Command speech uses AVSpeechSynthesizer for low-latency spoken feedback.
  • Optional completion guidance is spoken on demand instead of after every piece.

Architecture

Keyboard / VoiceOver user
        |
        v
Swift NSPanel overlay
        |
        | BuilderSubmitCommand(command)
        v
C++ builder core
        |
        | semantic JSON state
        v
Swift accessibility fields + speech

C++ builder core
        |
        +--> SDL renderer: visual coaster scene
        +--> SDL audio: generated game cues

The important architectural choice is that Swift and SDL do not talk to each other. C++ is the hub. Swift controls accessible input/output, while SDL presents pixels and sound.

Resources Used

  • OpenRCT2 was used as an architectural and design reference for the coaster type and track-piece vocabulary.
  • No OpenRCT2 source files are embedded in this spike.
  • No RollerCoaster Tycoon or OpenRCT2 sprite sheets, object files, or sound assets are bundled.
  • Visuals are generated directly in C++/SDL: isometric terrain, paths, water, trees, station art, supports, rails, preview track, loops, and train cars.
  • Sounds are generated directly in C++/SDL: selection, placement, blocked placement, undo, rotation, toggles, reset, completed circuit, and train clacks.
  • Accessibility uses macOS AppKit, NSAccessibility, and AVSpeechSynthesizer.

Requirements

  • macOS 13 or newer
  • Xcode command line tools
  • Swift toolchain
  • SDL2 installed through Homebrew
brew install sdl2

Build

From this repository root:

make

Build the app bundle:

make app

Open the app:

make open-app

Run the non-interactive smoke demo:

make demo

Expected smoke-demo signal:

HYPER_TWISTER_SUMMARY ... sdl_input_events=0 ...

sdl_input_events=0 confirms gameplay input is not being handled by SDL.

Recipe Validation

Validate the known closed-coaster recipe without opening the UI:

make validate

Equivalent direct command:

build/hyper-twister-builder --validate-recipe "T SPACE N N SPACE N SPACE N L SPACE P SPACE SPACE P P L SPACE N N N N SPACE N SPACE T"

The expected result is:

VALIDATE_RECIPE_RESULT closed=true status="Complete circuit" ...
VALIDATE_RECIPE_PASSED

Validated recipe:

T                         pause test train
Space                     place station
N N Space                 left banked turn
N Space                   right banked turn
N L Space                 chain lift hill
P Space                   right banked turn
Space                     right banked turn
P P L Space               straight track, lift off
N N N N Space             steep drop
N Space                   vertical loop back into station
T                         start test run

Manual Controls

Keyboard commands while the Swift overlay is focused:

  • N: next piece
  • P: previous piece
  • Space or Return: place selected piece
  • U: undo last piece
  • R: rotate right
  • B: cycle bank
  • S: cycle slope
  • L: toggle chain lift
  • T: toggle test train
  • M: toggle game sounds
  • X: reset layout
  • C: speak circuit completion summary
  • H: speak heading and height mismatch
  • G: speak one suggested next step
  • Shift+G: speak detailed route guidance
  • V: toggle verbose guidance after every builder command
  • Esc: quit

Fullscreen Demo Mode

For clean video capture:

build/hyper-twister-builder --fullscreen

Then run the validated recipe above at human pace.

Manual VoiceOver Pass

  1. Turn on VoiceOver.
  2. Open the app with make open-app.
  3. Navigate the Swift overlay fields and controls.
  4. Confirm VoiceOver reads piece, direction, bank, slope, lift, sound, segment count, cost, ratings, cursor, completion, and last message.
  5. Place a few pieces and confirm speech feedback is immediate.
  6. Press C, H, G, and Shift+G to request optional completion guidance.
  7. Press M and confirm game sounds toggle while speech feedback continues.
  8. Switch to another app and confirm the spike does not steal global focus back.

Repository Contents

Makefile
README.md
media/hyper-twister-validated-fullscreen-demo-web.mp4
Resources/Info.plist
Sources/BuilderCore.cpp
Sources/BuilderOverlay.swift

Build products are ignored under build/.

Status

This is a spike, not production code. It is intended to demonstrate the accessibility architecture and make the interaction model demoable for discussion.

About

Accessible Hyper-Twister coaster builder spike with Swift accessibility overlay and SDL renderer

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages