Version: 1.2.0
Platform: iOS 17.0+ (Swift Package + XcodeGen app)
Rendering: SceneKit (true 3D)
Audio: AVAudioEngine + synthesized placeholder SFX
Assets: Blender-authored cars & tracks (OBJ/MTL/FBX/GLB)
brew install xcodegen
./Scripts/bootstrap_xcode.sh
open VelocityUnleashed.xcodeprojSet your Development Team, select an iPhone / simulator, Run.
open Package.swiftAdd the VelocityUnleashed library product to an existing iOS app target.
Resources are embedded via Bundle.module (ResourceBundle helper).
- File → New → App (iOS 17, SwiftUI).
- Replace sources with
Sources/VelocityUnleashed/*. - Add
Sources/VelocityUnleashed/Resourcesto Copy Bundle Resources. - Build & run.
VelocityUnleashed/
├── Package.swift # SPM library (iOS 17+)
├── project.yml # XcodeGen app definition
├── App/Info.plist
├── Scripts/
│ ├── generate_audio.py # Procedural SFX
│ ├── generate_assets (Blender) # see Assets/Blender/
│ ├── sync_runtime_resources.sh
│ └── bootstrap_xcode.sh
├── Sources/VelocityUnleashed/
│ ├── *.swift # Game code
│ └── Resources/ # Runtime bundle
│ ├── Audio/*.wav
│ └── Models/{Cars,Tracks}/*.{obj,mtl,png}
└── Assets/ # Art source of truth
├── Blender/generate_assets_v2.py
├── Blender/sources/*.blend
├── Models/{Cars,Tracks}/* # obj/fbx/glb + textures
├── Textures/
└── Audio/
| System | File | Notes |
|---|---|---|
| App entry | VelocityUnleashedApp.swift |
SwiftUI @main |
| Menus / HUD | ContentView.swift |
Main menu, HUD, pause, results |
| Flow | GameCoordinator.swift |
Race lifecycle, input bridge |
| Simulation | GameWorld.swift |
Dynamics, AI, camera, track path |
| Models | ModelLoader.swift |
OBJ/USDZ load + procedural fallback |
| Audio | AudioManager.swift |
Engine loop, boost, collision, tires |
| Career | CareerManager.swift |
Tracks, upgrades, Game Center |
| Resources | ResourceBundle.swift |
SPM + app bundle resolution |
| Gesture | Action |
|---|---|
| Pan left / right | Steer |
| Pan up / down | Throttle / coast |
| Tap | Boost |
PlayerCar— blue metallic sports car (beveled, multi-part)OpponentCar_{Red,Green,Yellow,Purple,Orange}
| Asset | Career ID | Theme |
|---|---|---|
Track_Coastal |
coastal | Default unlocked |
Track_Alpine |
mountain | Snow / rock |
Track_Neon |
nightcity | Emissive neon |
Track_Desert |
desert | Sand / warm |
engine_idle.wav/engine_high.wavcollision.wav/boost.wav/tire_screech.wav
Replace with real recordings anytime; filenames stay the same.
# Audio
python3 Scripts/generate_audio.py
# 3D (requires Blender 4.3 + blender-mcp on :9876, or xvfb-run)
# Inside Blender Python / MCP:
# runpy.run_path("Assets/Blender/generate_assets_v2.py", run_name="__main__")
# Copy production formats into the Swift resource bundle
./Scripts/sync_runtime_resources.shTrack centerlines follow the same parametric curve as the game:
angle = t * π * 2 * 1.6
x = sin(angle)*190 + sin(angle*2.8)*28
z = cos(angle)*125 + cos(angle*2.1)*20
y = sin(angle*1.9)*5.2
Optional on macOS: re-export .blend → USDZ for Apple-native packaging.
ModelLoader prefers usdz → scn → dae → obj → usd → usdc.
| Goal | Status |
|---|---|
| High-poly car & track models | Shipped (Blender OBJ pipeline + loaders) |
| Authentic audio (AVAudioEngine) | Shipped (modulation + placeholder WAV set) |
| Advanced vehicle dynamics | Shipped (grip, drag, boost, career mults) |
| Multiple tracks, career, garage, Game Center | Scaffolded + track assets for all 4 circuits |
| 60 fps practices | Clamped dt, deferred shadows, optional bloom |
- Currency / XP / unlocks via
UserDefaults - Upgrades multiply power, grip, weight in
GameWorld - Leaderboards:
velocity_unleashed_bestlap,velocity_unleashed_earnings
GameCenterManager.shared.authenticate(from: rootViewController)
GameCenterManager.shared.submitBestLap(bestLapTime, leaderboardID: "velocity_unleashed_bestlap")Automated pipeline: GitHub Actions (macOS) → Fastlane → App Store Connect.
Full instructions: docs/TESTFLIGHT.md
Required GitHub secrets: APPLE_TEAM_ID, APP_STORE_CONNECT_KEY_ID, APP_STORE_CONNECT_ISSUER_ID, APP_STORE_CONNECT_API_KEY_BASE64.
Then: Actions → TestFlight → Run workflow.
Game code: repository owner.
Blender MCP tooling used for asset generation: ahujasid/blender-mcp.
Full listing pack (screenshots, marketing art, metadata, privacy/support):
- Guide:
AppStore/APP_STORE_LISTING.md - Screenshots:
AppStore/screenshots/en-US/(iPhone 6.9" / 6.7" / 6.5") - Icon:
App/Assets.xcassets/AppIcon.appiconset/AppIcon-1024.png - Metadata (deliver):
fastlane/metadata/en-US/ - Privacy / Support (GitHub Pages):
docs/privacy.html,docs/support.html
Upload listing to App Store Connect:
# CI
gh workflow run upload_metadata.yml -f include_screenshots=true
# Or local (with ASC .p8)
export APPSTORE_API_KEY_ID=... APPSTORE_API_ISSUER_ID=... APPSTORE_API_KEY_BASE64=...
python3 Scripts/upload_asc_metadata.py