Skip to content

๐Ÿ“ Angle Game Mode (Developer Docs)

The AngleFragment implements the Angle Game Mode in zMantra.
This mode challenges players to rotate their phone to achieve a target relative angle.
It integrates the Rotation Sensor Utility, accessibility announcements, and validation logic to provide an interactive experience for both sighted and TalkBack users.


๐Ÿ“‚ Location

com.zendalona.zmantra.presentation.features.game.angle.AngleFragment


๐Ÿ”‘ Core Responsibilities

  1. Sensor Management
  2. Uses a RotationSensorUtility to capture azimuth, pitch, roll from the device sensors.
  3. Tracks the base azimuth (starting orientation).
  4. Calculates the relative rotation of the device in degrees.

  5. Game Question Flow

  6. Each GameQuestion provides a target angle (answer).
  7. Player must rotate their phone until the relative angle matches the target (ยฑ5ยฐ tolerance).
  8. If held for 5 seconds, the question is marked as answered and a grade is assigned.

  9. Accessibility & Feedback

  10. Announces each new question text (e.g., "Rotate your phone by 45ยฐ").
  11. Every 3 seconds, if TalkBack is active, announces the current rotation angle.
  12. This ensures blind users receive continuous audio feedback.

  13. Game Result

  14. Uses getGrade() with fixed parameters (elapsedTime = 1.0, limit = 10.0).
  15. Shows a result dialog after each question.

โš™๏ธ Key Fields

Variable Type Purpose
_binding / binding FragmentGameAngleBinding View binding for layout.
rotationSensorUtility RotationSensorUtility Handles rotation sensor updates.
targetRotation Float Target angle (from question).
baseAzimuth Float Reference orientation (initial azimuth).
questionAnswered Boolean Prevents re-validation after answering.
currentIndex Int Index of the current question.
isFirstQuestion Boolean Ensures focus only for the first question.
angleUpdateHandler Handler Manages repeated announcements.
angleUpdateRunnable Runnable? Announces current angle every 3s.
holdRunnable Runnable? Checks if angle is held for 5s.
isHolding Boolean Tracks whether device is held at correct angle.

๐Ÿ”„ Lifecycle

  1. onCreateView()
  2. Inflate layout, initialize RotationSensorUtility.
  3. Set up RotationListener โ†’ calls handleRotationChange().

  4. onStart()

  5. Registers sensor listener.

  6. onStop() / onDestroyView()

  7. Unregisters sensor listener.
  8. Removes callbacks to prevent memory leaks.

  9. onQuestionsLoaded()

  10. Resets state.
  11. Shows first question (or no-questions message).

  12. showNextQuestion()

  13. Loads next GameQuestion.
  14. Updates targetRotation.
  15. Announces question text.
  16. Starts recurring accessibility announcements of current angle.

  17. handleRotationChange()

  18. Sets baseAzimuth if unset.
  19. Calculates relative angle from azimuth difference.
  20. Updates UI (rotationAngleText).
  21. Calls validateAngle().

  22. validateAngle()

  23. Checks if current angle โ‰ˆ targetRotation (ยฑ5ยฐ).
  24. If within range, start 5-second hold timer.
  25. If held successfully โ†’ mark answered, grade, show result.
  26. If moved away โ†’ reset hold state.

๐Ÿ“ Rotation Logic

```kotlin val relativeAzimuth = (azimuth - baseAzimuth + 360) % 360 binding.rotationAngleText.text = getString(R.string.relative_angle_template, relativeAzimuth.toInt()) ````

  • baseAzimuth: The initial device orientation when question starts.
  • relativeAzimuth: Normalized rotation difference (0โ€“360ยฐ).
  • UI displays angle, TalkBack announces updates.

๐ŸŽง Accessibility

  • At question start โ†’ "Rotate your phone by Xยฐ".
  • Every 3 seconds โ†’ "Current angle: Yยฐ".
  • Focus request on first question ensures TalkBack reads aloud automatically.
  • Uses AccessibilityUtils().isSystemExploreByTouchEnabled() to detect TalkBack.

๐Ÿงช Testing Notes

  • Angle tolerance: ยฑ5ยฐ around target.
  • Hold duration: 5 seconds (can be adjusted).
  • Edge cases:

  • No questions โ†’ "No questions available".

  • Device rotation sensors unavailable โ†’ test fallback.
  • Reset when leaving fragment (lifecycle cleanup).