This commit is contained in:
Horoli 2026-02-15 15:47:39 +09:00
parent adb6c2d20b
commit 0420e23939
4 changed files with 152 additions and 5 deletions

View File

@ -7,9 +7,14 @@ class SettingsProvider with ChangeNotifier {
bool _enableEnemyAnimations = true; // Default: Enabled
double _attackAnimScale = 5.0; // Default: 5.0
double _shakeOffset = 30.0; // Default: 30.0
double _shakeCount =
3.0; // Default: 3.0 (using double for slider convenience, cast to int where needed)
bool get enableEnemyAnimations => _enableEnemyAnimations;
double get attackAnimScale => _attackAnimScale;
double get shakeOffset => _shakeOffset;
double get shakeCount => _shakeCount;
SettingsProvider() {
_loadSettings();
@ -19,6 +24,8 @@ class SettingsProvider with ChangeNotifier {
final prefs = await SharedPreferences.getInstance();
_enableEnemyAnimations = prefs.getBool(_keyEnemyAnim) ?? true;
_attackAnimScale = prefs.getDouble(_keyAttackAnimScale) ?? 5.0;
_shakeOffset = prefs.getDouble('settings_shake_offset') ?? 30.0;
_shakeCount = prefs.getDouble('settings_shake_count') ?? 3.0;
notifyListeners();
}
@ -35,4 +42,18 @@ class SettingsProvider with ChangeNotifier {
final prefs = await SharedPreferences.getInstance();
await prefs.setDouble(_keyAttackAnimScale, value);
}
Future<void> setShakeOffset(double value) async {
_shakeOffset = value;
notifyListeners();
final prefs = await SharedPreferences.getInstance();
await prefs.setDouble('settings_shake_offset', value);
}
Future<void> setShakeCount(double value) async {
_shakeCount = value;
notifyListeners();
final prefs = await SharedPreferences.getInstance();
await prefs.setDouble('settings_shake_count', value);
}
}

View File

@ -84,6 +84,93 @@ class SettingsScreen extends StatelessWidget {
);
},
),
Consumer<SettingsProvider>(
builder: (context, settings, child) {
return SizedBox(
width: 300,
child: Column(
children: [
const SizedBox(height: 20),
const Text(
'Shake Offset',
style: TextStyle(color: ThemeConfig.textColorWhite),
),
Row(
children: [
const Text(
'0',
style: TextStyle(color: ThemeConfig.textColorGrey),
),
Expanded(
child: Slider(
value: settings.shakeOffset,
min: 0.0,
max: 100.0,
divisions: 100,
label: settings.shakeOffset.toStringAsFixed(1),
activeColor: ThemeConfig.btnActionActive,
inactiveColor: ThemeConfig.textColorGrey,
onChanged: (value) {
settings.setShakeOffset(value);
},
),
),
const Text(
'100',
style: TextStyle(color: ThemeConfig.textColorGrey),
),
],
),
Text(
'Current: ${settings.shakeOffset.toStringAsFixed(1)}',
style: const TextStyle(
color: ThemeConfig.textColorWhite,
fontSize: 12,
),
),
const SizedBox(height: 20),
const Text(
'Shake Count',
style: TextStyle(color: ThemeConfig.textColorWhite),
),
Row(
children: [
const Text(
'1',
style: TextStyle(color: ThemeConfig.textColorGrey),
),
Expanded(
child: Slider(
value: settings.shakeCount,
min: 1.0,
max: 10.0,
divisions: 9,
label: settings.shakeCount.toStringAsFixed(0),
activeColor: ThemeConfig.btnActionActive,
inactiveColor: ThemeConfig.textColorGrey,
onChanged: (value) {
settings.setShakeCount(value);
},
),
),
const Text(
'10',
style: TextStyle(color: ThemeConfig.textColorGrey),
),
],
),
Text(
'Current: ${settings.shakeCount.toStringAsFixed(0)}',
style: const TextStyle(
color: ThemeConfig.textColorWhite,
fontSize: 12,
),
),
],
),
);
},
),
// const SizedBox(height: 20),
// const Text(

View File

@ -1,5 +1,7 @@
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../../providers/settings_provider.dart';
class ShakeWidget extends StatefulWidget {
final Widget child;
@ -10,7 +12,7 @@ class ShakeWidget extends StatefulWidget {
const ShakeWidget({
super.key,
required this.child,
this.shakeOffset = 10.0,
this.shakeOffset = 30.0,
this.shakeCount = 3,
this.duration = const Duration(milliseconds: 400),
});
@ -46,14 +48,24 @@ class ShakeWidgetState extends State<ShakeWidget>
@override
Widget build(BuildContext context) {
// Read settings from provider (listen: false because we only read in build,
// actually we want to listen to updates if settings change while looking at it?
// But usually ShakeWidget is in BattleScreen.
// However, the previous implementation used `widget.shakeCount` and `widget.shakeOffset`.
// We should prefer provider values if available, or allow overrides?
// The prompt says "shakeWidget에서 shakeCount, shakeOffset을 settings에서 설정할 수 있게 globalOption으로 설정해야해."
// So we use Provider values.
final settings = context.watch<SettingsProvider>();
final shakeCount = settings.shakeCount;
final shakeOffset = settings.shakeOffset;
return AnimatedBuilder(
animation: _controller,
builder: (context, child) {
final double sineValue = sin(
widget.shakeCount * 2 * pi * _controller.value,
);
final double sineValue = sin(shakeCount * 2 * pi * _controller.value);
return Transform.translate(
offset: Offset(sineValue * widget.shakeOffset, 0),
offset: Offset(sineValue * shakeOffset, 0),
child: child,
);
},

View File

@ -0,0 +1,27 @@
# Task: Global Shake Settings
**Goal**: Make `shakeCount` and `shakeOffset` in `ShakeWidget` configurable via global settings, similar to `attackAnimationScale`.
## Context
Currently, `ShakeWidget` uses hardcoded defaults or constructor parameters for `shakeOffset` and `shakeCount`. The user wants to adjust these values globally from the Settings screen to fine-tune the visual feedback.
## Requirements
1. **Settings Provider Updates**:
- Add `shakeOffset` (double, default 30.0).
- Add `shakeCount` (int, default 3).
- Implement persistence using `SharedPreferences`.
2. **Settings UI**:
- Add sliders to the Settings screen to control these values.
- `Shake Offset`: Range approx 0-100?
- `Shake Count`: Range approx 1-10?
3. **ShakeWidget Updates**:
- Consume `SettingsProvider` to get the global values.
- Apply these values to the shake animation logic.
## Plan
1. Modify `lib/providers/settings_provider.dart` to add the new settings.
2. Modify `lib/screens/settings_screen.dart` to add the sliders.
3. Modify `lib/widgets/battle/shake_widget.dart` to use the provider.