DEV Community

Cover image for Gyroscope tilt steering (mobile)
Weird Codes
Weird Codes

Posted on • Originally published at weirdcodes.itch.io

Gyroscope tilt steering (mobile)

Devlog — Gyroscope tilt steering (mobile)

Summary

Added device-tilt (gyroscope) steering for mobile so players can control the chariot (ratha) using the DeviceOrientation API. The feature includes iOS 13+ permission flow, baseline calibration, a configurable deadzone to avoid accidental steering, a HUD button for enable/re-calibrate, and i18n strings + UI alerts.

What changed (high level)

  • New GyroscopeControls class that reads DeviceOrientation gamma and injects arrow keys into the shared keys object used by the engine.
  • iOS 13+ permission-aware flow via DeviceOrientationEvent.requestPermission() (called inside a user gesture).
  • Calibration: the first orientation event after enabling is recorded as baseline; re-clicking the HUD button re-zeroes baseline.
  • Deadzone ±10° (configurable) to avoid accidental steering.
  • Key-ownership semantics so the gyro only clears keys it set (prevents clobbering keyboard/touch input).
  • HUD UX: a #gyro-btn icon is added (visible only on touch+sensor devices). Button toggles to a recalibrate state and shows alerts when permission is granted/denied or calibration occurs.
  • i18n: added English + Hindi strings for gyro UI and alerts.
  • Styling: added .gyro-active CSS for the active button state.
  • Integration in main.js: imported/instantiated GyroscopeControls, logic to show UI, requestPermission flow on button click, and language-aware title updates.

Files changed (summary)

  • index.html
    • Added HUD button: <button id="gyro-btn" ... style="display:none;">🌀</button>
  • src/i18n.js
    • Added i18n keys: gyro.title, gyro.recalibrate, alert.gyroEnabled.*, alert.gyroDenied.*, alert.gyroCalibrate.* (Hindi + English)
  • src/main.js
    • Imported GyroscopeControls
    • Instantiated gyro controller
    • Show/hide gyro button when touch + orientation supported
    • Click handler for #gyro-btn: requestPermission(), calibrate() on re-click, and engine alerts
    • Updated applyStartScreenLanguage() to update gyro button title per language
  • src/touch.js
    • Appended new GyroscopeControls class (full implementation)
    • Implements isSupported(), requestPermission(), calibrate(), stop(), isActive(), internal event handling, deadzone and baseline handling, and key-ownership flags
  • style.css
    • Added #gyro-btn.gyro-active styling

Commit stats: +226 / -3 (total 229 changes)

How it works (user flow)

  • On a touch device with orientation support the HUD gyro button becomes visible.
  • First tap:
    • iOS 13+: shows permission dialog via requestPermission() (must be inside a user gesture).
    • Android / devices without explicit permission: starts immediately.
    • The first orientation event after start is taken as the baseline (neutral) orientation.
    • Game alerts that tilt steering is active.
  • While active:
    • Tilting left past -10° from baseline sets arrowleft (steer left).
    • Tilting right past +10° from baseline sets arrowright (steer right).
    • Within ±10° both gyro-set keys are released (neutral).
    • Keyboard or touch input keeps ownership over their keys; gyro only clears keys it set.
  • Re-clicking the gyro button re-calibrates the baseline to the current orientation (alert shown).
  • If permission is denied, an alert instructs the player to enable sensors in device settings.

Developer notes / implementation details

  • Key ownership: GyroscopeControls tracks which keys it set (_setLeft, _setRight) and only clears those keys to avoid clobbering keyboard/touch inputs.
  • Calibration: this._needsCal is set on start and when calibrate() is called. The first event when _needsCal is true records this._baseline = event.gamma.
  • Deadzone: default 10° (this.deadzone = 10) — adjustable on the class instance.
  • iOS permission: checks for DeviceOrientationEvent.requestPermission and calls it inside the button click handler (user gesture requirement).
  • Alerts: uses engine._alertKey() with new i18n keys (alert.gyroEnabled, alert.gyroDenied, alert.gyroCalibrate).
  • stop() removes the event listener and clears gyro-owned keys; no explicit "disable" UI currently wired.
  • Visual feedback: .gyro-active class applied to button when enabled.

QA / Testing checklist

  • Permission flows:
    • iOS: click button → permission dialog → allow → steering works and alert shown.
    • iOS deny → permission-denied alert, no crash.
    • Android: click button → starts and calibrates baseline automatically.
  • Calibration:
    • Verify steering only occurs beyond ±10° from baseline.
    • Re-click button while tilted → neutral updated, alert shown.
  • Input coexistence:
    • Hold keyboard arrow key → gyro should not override it.
    • Use touch steering while gyro active → gyro should only change keys it set.
  • Edge cases:
    • Devices without orientation support — button remains hidden.
    • Dismissing permission dialog handled gracefully.
    • Rapid enable/disable should not leave stale keys (verify stop() behavior if used).

Potential follow-ups / suggested improvements

  • Add a HUD toggle to fully disable gyro steering (UI to call stop()).
  • Add sensitivity slider (deadzone and sensitivity) in settings and persist user's choice.
  • Persist calibration and enabled state if desired by UX.
  • Add a short in-game tutorial explaining tilt controls and permission steps.
  • Add analytics to see adoption (respecting privacy/consent).

Changelog-ready line

  • feat(mobile): add tilt steering via DeviceOrientation API with iOS permission support, calibration, deadzone, HUD button, and i18n (closes #28)

Top comments (0)