Skip to content

๐Ÿงญ Compass Game Mode (Developer Docs)

The CompassFragment implements the Compass Game Mode in zMantra.
This mode challenges players to physically rotate their device toward a target compass direction (e.g., North, South-East, West).
It integrates Androidโ€™s accelerometer and magnetometer sensors, custom accessibility announcements, and real-time feedback.


๐Ÿ“‚ Location

com.zendalona.zmantra.presentation.features.game.compass.CompassFragment


๐Ÿ”‘ Core Responsibilities

  1. Sensor Management
  2. Uses SensorManager to register the Accelerometer and Magnetometer.
  3. Calculates device orientation with SensorManager.getRotationMatrix().
  4. Converts orientation to azimuth (0โ€“360ยฐ).

  5. Game Question Flow

  6. Loads compass questions (GameQuestion objects).
  7. Each question specifies a target direction (e.g., "North").
  8. Players must rotate the device and hold it in the target direction for 3 seconds.

  9. Accessibility & Feedback

  10. Announces each new question with TalkBack / TTS.
  11. Periodically announces the current facing direction (every 10 seconds).
  12. Provides spoken and visual feedback on correct orientation.

  13. Game Result

  14. Calculates grade based on time taken vs questionโ€™s time limit.
  15. Shows result dialog, then proceeds to the next question.

โš™๏ธ Key Fields

Variable Type Purpose
sensorManager SensorManager Access to device sensors.
magnetometer, accelerometer Sensor? Required sensors for orientation.
rotationMatrix, orientation FloatArray Store orientation math results.
currentAzimuth Float Current compass azimuth in degrees.
targetDirection Float Target direction in degrees (from question).
questions MutableList<GameQuestion> Loaded compass questions.
holdHandler Handler Used to check if user holds correct direction for 3s.
directionAnnounceHandler Handler Announces direction every 10s for accessibility.

๐Ÿ”„ Lifecycle

  1. onAttach() โ†’ Initialize SensorManager, get sensors.
  2. onCreateView() โ†’ Inflate layout, load compass directions from strings.xml.
  3. onViewCreated() โ†’ Announce "Turn to ..." instruction.
  4. onQuestionsLoaded() โ†’ Populate questions & call generateNewQuestion().
  5. generateNewQuestion() โ†’
  6. Set new targetDirection.
  7. Announce question.
  8. Start periodic announcements.
  9. onSensorChanged() โ†’
  10. Collect accelerometer & magnetometer values.
  11. Compute azimuth.
  12. Call updateCompassUI().
  13. updateCompassUI() โ†’ Update rotation + check if holding correct direction.
  14. checkIfHoldingCorrectDirection() โ†’
  15. If user holds within ยฑ22.5ยฐ of target for 3s โ†’ trigger success.

๐Ÿ“ Orientation Logic

```kotlin SensorManager.getRotationMatrix(rotationMatrix, null, lastAccelerometer, lastMagnetometer) SensorManager.getOrientation(rotationMatrix, orientation)

val azimuth = Math.toDegrees(orientation[0].toDouble()).toFloat() val azimuthFixed = (azimuth + 360) % 360 ````

  • azimuth โ†’ Raw compass heading.
  • azimuthFixed โ†’ Normalized value (0โ€“360ยฐ).

๐ŸŽง Accessibility

  • Announcements:

  • At question start โ†’ "Turn to North"

  • Every 10s โ†’ "Currently facing East"
  • TalkBack users can still navigate UI, but spoken feedback is automatic.
  • This ensures blind learners can orient their device correctly.

๐Ÿงช Testing Notes

  • Test in environments without strong magnetic interference.
  • Validate with both sighted mode (UI compass rotates) and TalkBack mode (spoken feedback only).
  • Edge cases:

  • Missing sensors โ†’ show "No compass questions found" and end game.

  • Holding at borderline angle (22.5ยฐ threshold).