Skip to main content

Architecture

Gametriki splits SDK (pure motion) from app (BLE, games, UI). Games depend only on GameInput from VeltoKit.

Layer diagram

flowchart LR
BLE[BLE peripheral]
SDK[VeltoKit / MotionSDK]
GI[GameInput]
GM[Engine / Games]
PL[TrikiInputAdapter optional]

BLE --> SDK
SDK --> GI
GI --> GM
PL -.-> SDK

Frame pipeline (VeltoKit)

Each display tick (with connect() + pollInput()):

  1. BLEBLEManager delivers notify bytes → enqueueBLE(_:) (lazy pipeline on first connect()).
  2. IngressflushIngress() parses gyro blocks (BLEGyroParser) or paddle raw int16.
  3. ButtonButtonDetector watches 0x22 packets, rising edge on bytes[1].
  4. MotionEngine.updateFrame — runs mode-specific processor + gesture FSM.
  5. PublishMotionSDK copies MotionOutput + click/throw into GameInput.
let input = motion.pollInput(deltaTime: dt) // preferred after connect()
// or: motion.enqueueBLE(bytes); motion.updateFrame(deltaTime: dt)

Internal modules

ComponentResponsibility
MotionProcessorOffset, smoothing, paddle integration, pointer rotation
GestureDetectorBACK → FORWARD throw, throwPower
ButtonDetectorBLE click edge
MotionEngineMode switch, calibration APIs, output / debug
MotionSDKFacade: connect(), pollInput(), ingress, input
BLEManagerScan, connect, notify (VeltoKit target)
MotionParserSensor struct + impulses (used by pollInput)

Platform (sample app, optional)

PieceRole
TrikiInputAdapterForwards to MotionSDK; calibration UI

MotionInputProvider is a type alias for TrikiInputAdapter.

Triki UI navigation layer

For screen navigation, the sample app adds a thin UI layer on top of MotionInputProvider:

  • .trikiUIScreen(...) wires per-screen lifecycle and ticking
  • TrikiUINavigator maps posX to slots and triggers activation
  • TrikiFocusGate + TrikiHoldTracker stabilize and confirm focus

See Triki UI navigation for integration details and examples.

Sample games

GameMotionModePrimary fields
Pong.paddleposX
Dart.gesturethrowPower, shotTriggered
Bowling.gesturethrow → SceneKit force
Quiz.pointerposX, primaryAction

Threading

MotionSDK, MotionEngine, and TrikiInputAdapter are @MainActor. Call update / pollInput from the main thread (e.g. CADisplayLink or SwiftUI timer).

Debug

  • motion.debug — raw/smooth/rel, paddle steer, gyro block index
  • motion.output — normalized x, y, didShoot, paddleAtRest
  • DEV UI in the sample app exposes MotionConfig sliders

MotionSDK API · Triki UI navigation · BLE integration