Refactor: Slim down BattleProvider and extract logic services. Restore original animations and positioning.

This commit is contained in:
2026-04-28 08:41:46 +09:00
parent 0e0748540e
commit 83ea191ca2
29 changed files with 2079 additions and 1951 deletions
+41 -13
View File
@@ -10,6 +10,8 @@ class SpriteAnimationWidget extends StatefulWidget {
final int frameCount;
final double scale;
final bool flip;
final bool loop;
final Duration? customDuration;
final String? fallbackAssetPath;
const SpriteAnimationWidget({
@@ -17,10 +19,11 @@ class SpriteAnimationWidget extends StatefulWidget {
required this.assetPath,
this.tileWidth = 100.0,
this.tileHeight = 100.0,
this.frameCount =
6, // Default guess, will adjust logic to use actual image width if possible
this.frameCount = 6,
this.scale = 1.0,
this.flip = false,
this.loop = true,
this.customDuration,
this.fallbackAssetPath,
});
@@ -40,11 +43,22 @@ class _SpriteAnimationWidgetState extends State<SpriteAnimationWidget>
super.initState();
_controller = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 600), // 100ms per frame approx
duration: widget.customDuration ?? const Duration(milliseconds: 600),
);
_loadImage();
}
@override
void didUpdateWidget(covariant SpriteAnimationWidget oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.assetPath != widget.assetPath) {
// Don't set _isLoading = true to avoid flickering.
// Keep showing the old image until the new one is loaded.
_controller.reset();
_loadImage();
}
}
Future<void> _loadImage() async {
try {
await _loadAsset(widget.assetPath);
@@ -82,11 +96,18 @@ class _SpriteAnimationWidgetState extends State<SpriteAnimationWidget>
? maxFrames
: widget.frameCount;
// Adjust duration based on frame count
_controller.duration = Duration(
milliseconds: _calculatedFrameCount * 100,
);
_controller.repeat();
// Adjust duration based on frame count if not custom
if (widget.customDuration == null) {
_controller.duration = Duration(
milliseconds: _calculatedFrameCount * 100,
);
}
if (widget.loop) {
_controller.repeat();
} else {
_controller.forward();
}
});
}
}
@@ -99,17 +120,26 @@ class _SpriteAnimationWidgetState extends State<SpriteAnimationWidget>
@override
Widget build(BuildContext context) {
if (_isLoading || _image == null) {
if (_image == null) {
return SizedBox(
width: widget.tileWidth * widget.scale,
height: widget.tileHeight * widget.scale,
child: const Center(child: CircularProgressIndicator()),
);
}
return AnimatedBuilder(
animation: _controller,
builder: (context, child) {
int frame;
if (!widget.loop) {
frame = (_controller.value * _calculatedFrameCount)
.floor()
.clamp(0, _calculatedFrameCount - 1);
} else {
frame = (_controller.value * _calculatedFrameCount).floor() %
_calculatedFrameCount;
}
return Transform.scale(
scaleX: widget.flip ? -1.0 : 1.0,
alignment: Alignment.center,
@@ -120,9 +150,7 @@ class _SpriteAnimationWidgetState extends State<SpriteAnimationWidget>
),
painter: SpriteSheetPainter(
image: _image!,
currentFrame:
(_controller.value * _calculatedFrameCount).floor() %
_calculatedFrameCount,
currentFrame: frame,
tileWidth: widget.tileWidth,
tileHeight: widget.tileHeight,
scale: widget.scale,