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
-
SensorManager
and accelerometer sensor are registered inonResume
. -
GIF animation (
rotate your phone
) is loaded if defined. -
Loading Questions
-
onQuestionsLoaded()
receives a list ofGameQuestion
objects. -
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()
comparescount
withquestion.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
) hascontentDescription
set 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
SensorManager
mocks for shake detection. - Validate game flow with sample
GameQuestion
inputs.
๐ 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.