This commit is contained in:
horoli 2026-01-28 23:16:37 +09:00
parent 8297ce980f
commit 7abb01ed5b
2 changed files with 64 additions and 38 deletions

View File

@ -128,6 +128,10 @@ class CharacterStatusCard extends StatelessWidget {
assetPath: overrideImage ?? character.image!, assetPath: overrideImage ?? character.image!,
scale: 5.0, // Zoomed in (300x300 in 200x200 box) scale: 5.0, // Zoomed in (300x300 in 200x200 box)
frameCount: 6, frameCount: 6,
flip: !isPlayer,
fallbackAssetPath: !isPlayer
? 'assets/images/enemies/Orc.png'
: null,
), ),
) )
: Icon( : Icon(

View File

@ -9,6 +9,8 @@ class SpriteAnimationWidget extends StatefulWidget {
final double tileHeight; final double tileHeight;
final int frameCount; final int frameCount;
final double scale; final double scale;
final bool flip;
final String? fallbackAssetPath;
const SpriteAnimationWidget({ const SpriteAnimationWidget({
super.key, super.key,
@ -18,6 +20,8 @@ class SpriteAnimationWidget extends StatefulWidget {
this.frameCount = this.frameCount =
6, // Default guess, will adjust logic to use actual image width if possible 6, // Default guess, will adjust logic to use actual image width if possible
this.scale = 1.0, this.scale = 1.0,
this.flip = false,
this.fallbackAssetPath,
}); });
@override @override
@ -43,33 +47,47 @@ class _SpriteAnimationWidgetState extends State<SpriteAnimationWidget>
Future<void> _loadImage() async { Future<void> _loadImage() async {
try { try {
final ByteData data = await rootBundle.load(widget.assetPath); await _loadAsset(widget.assetPath);
final List<int> bytes = data.buffer.asUint8List();
final Completer<ui.Image> completer = Completer();
ui.decodeImageFromList(Uint8List.fromList(bytes), (ui.Image img) {
completer.complete(img);
});
final image = await completer.future;
if (mounted) {
setState(() {
_image = image;
_isLoading = false;
// Use provided frameCount, but clamp to available frames in image
int maxFrames = (image.width / widget.tileWidth).floor();
_calculatedFrameCount = widget.frameCount > maxFrames
? maxFrames
: widget.frameCount;
// Adjust duration based on frame count
_controller.duration = Duration(
milliseconds: _calculatedFrameCount * 100,
);
_controller.repeat();
});
}
} catch (e) { } catch (e) {
debugPrint('Failed to load sprite image: $e'); debugPrint('Failed to load sprite image: $e');
if (widget.fallbackAssetPath != null) {
debugPrint(
'Attempting to load fallback image: ${widget.fallbackAssetPath}',
);
try {
await _loadAsset(widget.fallbackAssetPath!);
} catch (e2) {
debugPrint('Failed to load fallback image: $e2');
}
}
}
}
Future<void> _loadAsset(String path) async {
final ByteData data = await rootBundle.load(path);
final List<int> bytes = data.buffer.asUint8List();
final Completer<ui.Image> completer = Completer();
ui.decodeImageFromList(Uint8List.fromList(bytes), (ui.Image img) {
completer.complete(img);
});
final image = await completer.future;
if (mounted) {
setState(() {
_image = image;
_isLoading = false;
// Use provided frameCount, but clamp to available frames in image
int maxFrames = (image.width / widget.tileWidth).floor();
_calculatedFrameCount = widget.frameCount > maxFrames
? maxFrames
: widget.frameCount;
// Adjust duration based on frame count
_controller.duration = Duration(
milliseconds: _calculatedFrameCount * 100,
);
_controller.repeat();
});
} }
} }
@ -92,19 +110,23 @@ class _SpriteAnimationWidgetState extends State<SpriteAnimationWidget>
return AnimatedBuilder( return AnimatedBuilder(
animation: _controller, animation: _controller,
builder: (context, child) { builder: (context, child) {
return CustomPaint( return Transform.scale(
size: Size( scaleX: widget.flip ? -1.0 : 1.0,
widget.tileWidth * widget.scale, alignment: Alignment.center,
widget.tileHeight * widget.scale, child: CustomPaint(
), size: Size(
painter: SpriteSheetPainter( widget.tileWidth * widget.scale,
image: _image!, widget.tileHeight * widget.scale,
currentFrame: ),
(_controller.value * _calculatedFrameCount).floor() % painter: SpriteSheetPainter(
_calculatedFrameCount, image: _image!,
tileWidth: widget.tileWidth, currentFrame:
tileHeight: widget.tileHeight, (_controller.value * _calculatedFrameCount).floor() %
scale: widget.scale, _calculatedFrameCount,
tileWidth: widget.tileWidth,
tileHeight: widget.tileHeight,
scale: widget.scale,
),
), ),
); );
}, },