This is the complete working solution for Activity 13: Motion Fun. All TODOs have been implemented with best practices.
This solution includes:
- โ
Shake detection using accelerometer data
- โ
Background color changes based on device tilt
- โ
Real-time sensor data display (accelerometer + gyroscope)
- โ
Smooth performance with optimized update intervals
- โ
Proper cleanup on component unmount
bash
cd activity-13-motion-fun-solution
npm install --legacy-peer-deps
Important: This app requires a physical device with motion sensors. Web preview will not work.
Threshold-based Detection:
javascript
const threshold = 1.5;
const isShaking =
Math.abs(data.x) > threshold ||
Math.abs(data.y) > threshold ||
Math.abs(data.z) > threshold;
if (isShaking) {
setShakeCount(prev => prev + 1);
}
How it works:
- Accelerometer measures acceleration in all three axes (x, y, z)
- Sharp movements (shakes) cause acceleration spikes
- Threshold of 1.5 g-force filters normal movement
- Any axis exceeding threshold triggers shake detection
Why 1.5?
- Too low (< 1.0): False positives from normal handling
- Too high (> 2.5): Requires very vigorous shaking
- One.5 provides good balance for natural shake gestures
Gyroscope Mapping:
javascript
let newColor = '#1f2937';
if (data.x > 0.3) {
newColor = '#ef4444';
} else if (data.x < -0.3) {
newColor = '#3b82f6';
} else if (data.y > 0.3) {
newColor = '#eab308';
} else if (data.y < -0.3) {
newColor = '#22c55e';
}
setBackgroundColor(newColor);
How it works:
- Gyroscope measures rotation rate (rad/s) around each axis
- X-axis: Roll (left/right tilt)
- Y-axis: Pitch (forward/backward tilt)
- Z-axis: Yaw (rotation around vertical)
- Threshold of 0.3 rad/s prevents jitter
Color Mapping Logic:
- Red (Right): Device tilted to the right
- Blue (Left): Device tilted to the left
- Yellow (Forward): Top of device toward user
- Green (Backward): Top of device away from user
- Gray (Neutral): Device held flat or below threshold
javascript
Accelerometer.setUpdateInterval(100);
Gyroscope.setUpdateInterval(100);
Why 100ms?
- Fast enough for responsive UI (10 updates/second)
- Slow enough to conserve battery
- Prevents overwhelming React state updates
javascript
return () => {
accelerometerSubscription && accelerometerSubscription.remove();
gyroscopeSubscription && gyroscopeSubscription.remove();
};
Purpose:
- Prevents memory leaks
- Stops sensor updates when component unmounts
- Essential for battery life
javascript
setShakeCount(prev => prev + 1);
Best Practice:
- Using
prev => prev + 1 ensures correct increments
- Avoids issues with rapid state updates
- Works correctly even with multiple shakes/second
- Gentle shake: Should not trigger (< 1.5 threshold)
- Vigorous shake: Counter increments rapidly
- Continuous shake: Each shake registers separately
- Hold flat: Gray background
- Tilt right slowly: Changes to red at 0.3 rad/s
- Tilt left: Changes to blue
- Tilt forward/back: Yellow/green respectively
- Return to flat: Returns to gray
- Multiple rapid shakes: Counter should increment correctly
- Tilt while shaking: Both features work independently
- Background app: Sensors pause automatically
- Device rotation: Values adjust to new orientation
Sensor Understanding:
- Accelerometer vs Gyroscope differences
- 3-axis coordinate system
- Threshold-based event detection
React Native Skills:
- Subscribing to sensor updates
- Managing real-time data streams
- Proper cleanup in useEffect
- Dynamic styling with state
Motion Detection Algorithms:
- Shake detection patterns
- Tilt mapping strategies
- Noise filtering techniques
- Add debouncing to prevent rapid shake counts
- Display "Shaking!" indicator
- Add reset button
- Implement smooth color transitions with Animated API
- Add haptic feedback on shake
- Track shake intensity (force)
- Create shake gesture recognition (patterns)
- Build tilt-controlled game
- Implement motion-based navigation
- Units: g-force (1g = 9.81 m/sยฒ)
- Range: Typically +/-2g to +/-16g
- Use cases: Shake, free fall, tap detection
- Units: rad/s (radians per second)
- Range: Typically +/-250ยฐ/s to +/-2000ยฐ/s
- Use cases: Rotation, tilt, orientation
Combining both sensors provides:
- More accurate motion tracking
- Better gesture recognition
- Reduced individual sensor errors
Issue: Counter increments even when still
Solution: Increase threshold from 1.5 to 2.0
Issue: Colors flicker rapidly
Solution: Increase gyroscope threshold from 0.3 to 0.5
Issue: Battery drains quickly
Solution: Increase update interval to 200-500ms
Issue: Sensors not available
Solution: Must use physical device, not simulator
Expo Documentation:
Motion Sensors:
๐ Solution Complete!
This implementation demonstrates:
- Professional sensor handling
- Clean React patterns
- Real-world motion detection
- Battery-efficient design
Next Steps:
- Study the implementation
- Test on multiple devices
- Try the extension challenges
- Integrate into your projects!
Activity 13 Solution | M1: Mobile Foundations | Expo SDK 53 | React Native 0.79.5