Developer Documentation โ Shake Game Feature
This document provides technical details for developers working on the Shake Game feature of z.Mantra. It explains the structure, logic, and extensibility of the ShakeFragment and related components.
๐ Location
com.zendalona.zmantra.presentation.features.game.shake
๐ Core Class: ShakeFragment
The ShakeFragment implements a game where the player answers questions by shaking the device.
It extends:
BaseGameFragmentโ provides shared game logic (TTS, answer submission, game flow).SensorEventListenerโ listens to accelerometer data for detecting shakes.
๐๏ธ Lifecycle & Flow
-
Initialization
-
SensorManagerand accelerometer sensor are registered inonResume. -
GIF animation (
rotate your phone) is loaded if defined. -
Loading Questions
-
onQuestionsLoaded()receives a list ofGameQuestionobjects. -
Each question specifies:
expression: Instruction (e.g., "Shake 3 times").answer: Correct shake count.timeLimit: Allowed time to complete (default = 10s if undefined).
-
Starting a Question
-
startQuestion():- Resets counters (
count,wrongAttempts,answerChecked). - Updates UI (
ringMeTv,ringCount). - Announces question using TTS + accessibility.
- Resets counters (
-
Shake Detection
-
onSensorChanged()calculates acceleration from accelerometer values:kotlin val acceleration = sqrt((x*x + y*y + z*z).toDouble()).toFloat() if (acceleration > 12f) onShakeDetected()* Threshold = 12f (tuned to filter small device movements). -
Shake Handling
-
onShakeDetected():- Increments count.
- Announces count via TTS + Accessibility.
- If count exceeds expected โ triggers
checkAnswer(forceWrong = true). - If count == expected โ delayed
checkAnswer()after 1.5s.
-
Answer Checking
-
checkAnswer()comparescountwithquestion.answer. - If correct โ calls
proceedToNextQuestion(). - If wrong โ resets and retries (after 1s).
-
Time is measured using
firstShakeTime. -
Game Completion
-
When all questions are done,
endGame()is triggered fromBaseGameFragment.
๐ Important Variables
| Variable | Purpose |
|---|---|
count |
Current shake count. |
wrongAttempts |
Tracks how many times the user failed before retrying. |
answerChecked |
Prevents duplicate validation calls. |
firstShakeTime |
Timestamp of first shake for time measurement. |
isShakingAllowed |
Prevents multiple detections within 500ms. |
shakeHandler |
Controls shake debounce. |
gameHandler |
Controls answer validation timing. |
๐ฏ Accessibility Support
- Each question instruction (
ringMeTv) hascontentDescriptionset and announced viaannounce(). - Each shake count (
ringCount) is announced live. - Focus automatically moves to the instruction on the first question.
โ๏ธ Extensibility
1. Change Shake Sensitivity
Adjust threshold in onSensorChanged():
if (acceleration > 10f) { ... } // More sensitive
2. Custom Shake Animation
Replace GIF in getGifResource():
override fun getGifResource(): Int = R.drawable.my_custom_shake_gif
3. Add Difficulty Levels
Modify shake threshold/time limit dynamically based on question difficulty.
4. Data Model (GameQuestion)
Ensure GameQuestion has:
expression: String
answer: Int
timeLimit: Double?
๐งช Testing Notes
-
Manual Testing
-
Verify shake counts are detected properly on different devices.
- Check that accessibility announcements trigger correctly.
-
Test edge cases: 0 shakes, excessive shakes, timeouts.
-
Automated Testing
-
Use
SensorManagermocks for shake detection. - Validate game flow with sample
GameQuestioninputs.
๐ Example Question Flow
- App loads
GameQuestion("Shake 3 times", 3, 10). - Instruction announced: "Shake 3 times".
-
Player shakes:
-
Shake 1 โ Count = 1
- Shake 2 โ Count = 2
- Shake 3 โ Count = 3 โ Validation after 1.5s.
- Correct โ Next question.