From 8297ce980f85704da7ac99498d923976ab96ad13 Mon Sep 17 00:00:00 2001 From: horoli Date: Mon, 26 Jan 2026 00:53:04 +0900 Subject: [PATCH] aa --- assets/data/enemies.json | 143 ++++++++++++---- assets/data/players.json | 4 +- assets/images/character/Soldier-Attack01.png | Bin 0 -> 1934 bytes assets/images/character/Soldier.png | Bin 0 -> 13244 bytes assets/images/enemies/Orc.png | Bin 0 -> 1410 bytes lib/screens/main_menu_screen.dart | 14 ++ lib/widgets/battle/character_status_card.dart | 33 ++-- lib/widgets/test/sprite_animation_widget.dart | 155 ++++++++++++++++++ 8 files changed, 297 insertions(+), 52 deletions(-) create mode 100644 assets/images/character/Soldier-Attack01.png create mode 100644 assets/images/character/Soldier.png create mode 100644 assets/images/enemies/Orc.png create mode 100644 lib/widgets/test/sprite_animation_widget.dart diff --git a/assets/data/enemies.json b/assets/data/enemies.json index 7027191..2238839 100644 --- a/assets/data/enemies.json +++ b/assets/data/enemies.json @@ -5,8 +5,10 @@ "baseHp": 30, "baseAtk": 6, "baseDefense": 0, - "image": "assets/images/enemies/scrawny_gladiator.png", - "equipment": ["pot_lid"], + "image": "assets/images/enemies/Orc.png", + "equipment": [ + "pot_lid" + ], "tier": 1 }, { @@ -25,7 +27,9 @@ "baseAtk": 4, "baseDefense": 1, "image": "assets/images/enemies/clumsy_gladiator.png", - "equipment": ["simple_rags"], + "equipment": [ + "simple_rags" + ], "tier": 1 }, { @@ -34,7 +38,9 @@ "baseAtk": 7, "baseDefense": 1, "image": "assets/images/enemies/desperate_gladiator.png", - "equipment": ["gladius"], + "equipment": [ + "gladius" + ], "tier": 1 }, { @@ -43,7 +49,9 @@ "baseAtk": 6, "baseDefense": 3, "image": "assets/images/enemies/untrained_gladiator.png", - "equipment": ["wooden_buckler"], + "equipment": [ + "wooden_buckler" + ], "tier": 1 }, { @@ -61,7 +69,9 @@ "baseAtk": 5, "baseDefense": 5, "image": "assets/images/enemies/chained_gladiator.png", - "equipment": ["flail"], + "equipment": [ + "flail" + ], "tier": 1 }, { @@ -70,7 +80,9 @@ "baseAtk": 8, "baseDefense": 3, "image": "assets/images/enemies/retiarius.png", - "equipment": ["trident"], + "equipment": [ + "trident" + ], "tier": 1 }, { @@ -79,7 +91,9 @@ "baseAtk": 15, "baseDefense": 4, "image": "assets/images/enemies/one_eyed_gladiator.png", - "equipment": ["scimitar"], + "equipment": [ + "scimitar" + ], "tier": 2 }, { @@ -88,7 +102,9 @@ "baseAtk": 18, "baseDefense": 5, "image": "assets/images/enemies/brutal_gladiator.png", - "equipment": ["war_axe"], + "equipment": [ + "war_axe" + ], "tier": 2 }, { @@ -97,7 +113,10 @@ "baseAtk": 15, "baseDefense": 10, "image": "assets/images/enemies/veteran_gladiator.png", - "equipment": ["gladius", "leather_vest"], + "equipment": [ + "gladius", + "leather_vest" + ], "tier": 2 }, { @@ -107,7 +126,9 @@ "baseDefense": 7, "baseDodge": 15, "image": "assets/images/enemies/swift_gladiator.png", - "equipment": ["scimitar"], + "equipment": [ + "scimitar" + ], "tier": 2 }, { @@ -117,7 +138,10 @@ "baseDefense": 8, "luck": 10, "image": "assets/images/enemies/cunning_gladiator.png", - "equipment": ["flail", "tarnished_ring"], + "equipment": [ + "flail", + "tarnished_ring" + ], "tier": 2 }, { @@ -126,7 +150,11 @@ "baseAtk": 15, "baseDefense": 12, "image": "assets/images/enemies/hoplomachus.png", - "equipment": ["trident", "kite_shield", "chainmail"], + "equipment": [ + "trident", + "kite_shield", + "chainmail" + ], "tier": 2 }, { @@ -136,7 +164,9 @@ "baseDefense": 5, "baseDodge": -5, "image": "assets/images/enemies/drunken_gladiator.png", - "equipment": ["war_axe"], + "equipment": [ + "war_axe" + ], "tier": 2 }, { @@ -145,7 +175,10 @@ "baseAtk": 10, "baseDefense": 12, "image": "assets/images/enemies/the_wall.png", - "equipment": ["tower_shield", "chainmail"], + "equipment": [ + "tower_shield", + "chainmail" + ], "tier": 2 }, { @@ -154,7 +187,10 @@ "baseAtk": 25, "baseDefense": 12, "image": "assets/images/enemies/champion_gannicus.png", - "equipment": ["steel_greatsword", "steel_plate"], + "equipment": [ + "steel_greatsword", + "steel_plate" + ], "tier": 3 }, { @@ -163,7 +199,9 @@ "baseAtk": 30, "baseDefense": 10, "image": "assets/images/enemies/the_giant.png", - "equipment": ["war_hammer"], + "equipment": [ + "war_hammer" + ], "tier": 3 }, { @@ -172,7 +210,9 @@ "baseAtk": 25, "baseDefense": 14, "image": "assets/images/enemies/bloody_flamma.png", - "equipment": ["barbed_net"], + "equipment": [ + "barbed_net" + ], "tier": 3 }, { @@ -181,7 +221,10 @@ "baseAtk": 24, "baseDefense": 20, "image": "assets/images/enemies/legendary_oenomaus.png", - "equipment": ["scimitar", "steel_shield"], + "equipment": [ + "scimitar", + "steel_shield" + ], "tier": 3 }, { @@ -191,7 +234,9 @@ "baseDefense": 12, "baseDodge": 30, "image": "assets/images/enemies/the_unseen.png", - "equipment": ["hooked_spear"], + "equipment": [ + "hooked_spear" + ], "tier": 3 }, { @@ -200,7 +245,9 @@ "baseAtk": 35, "baseDefense": 15, "image": "assets/images/enemies/executioner.png", - "equipment": ["executioners_axe"], + "equipment": [ + "executioners_axe" + ], "tier": 3 }, { @@ -209,7 +256,9 @@ "baseAtk": 35, "baseDefense": 16, "image": "assets/images/enemies/vengeful_spartacus.png", - "equipment": ["gladius"], + "equipment": [ + "gladius" + ], "tier": 3 }, { @@ -218,7 +267,11 @@ "baseAtk": 28, "baseDefense": 25, "image": "assets/images/enemies/praetorian_guard.png", - "equipment": ["steel_greatsword", "steel_plate", "tower_shield"], + "equipment": [ + "steel_greatsword", + "steel_plate", + "tower_shield" + ], "tier": 3 } ], @@ -229,7 +282,10 @@ "baseAtk": 14, "baseDefense": 5, "image": "assets/images/enemies/crixus_the_gaul.png", - "equipment": ["long_sword", "kite_shield"], + "equipment": [ + "long_sword", + "kite_shield" + ], "tier": 1 }, { @@ -238,7 +294,9 @@ "baseAtk": 28, "baseDefense": 8, "image": "assets/images/enemies/theokoles.png", - "equipment": ["war_axe"], + "equipment": [ + "war_axe" + ], "tier": 1 }, { @@ -247,7 +305,9 @@ "baseAtk": 22, "baseDefense": 10, "image": "assets/images/enemies/isidorus_the_butcher.png", - "equipment": ["trident"], + "equipment": [ + "trident" + ], "tier": 1 }, { @@ -257,7 +317,11 @@ "baseDefense": 10, "luck": 15, "image": "assets/images/enemies/vitallion_the_lion.png", - "equipment": ["war_hammer", "chainmail", "engraved_amulet"], + "equipment": [ + "war_hammer", + "chainmail", + "engraved_amulet" + ], "tier": 2 }, { @@ -267,7 +331,9 @@ "baseDefense": 15, "baseDodge": 15, "image": "assets/images/enemies/arcas_the_serpent.png", - "equipment": ["hooked_spear"], + "equipment": [ + "hooked_spear" + ], "tier": 2 }, { @@ -276,7 +342,10 @@ "baseAtk": 30, "baseDefense": 20, "image": "assets/images/enemies/verus_the_undefeated.png", - "equipment": ["steel_greatsword", "steel_shield"], + "equipment": [ + "steel_greatsword", + "steel_shield" + ], "tier": 2 }, { @@ -285,7 +354,11 @@ "baseAtk": 38, "baseDefense": 30, "image": "assets/images/enemies/magistratus_maxentius.png", - "equipment": ["executioners_axe", "steel_plate", "champions_badge"], + "equipment": [ + "executioners_axe", + "steel_plate", + "champions_badge" + ], "tier": 3 }, { @@ -295,7 +368,9 @@ "baseDefense": 15, "baseDodge": 20, "image": "assets/images/enemies/aurelia_crimson_blade.png", - "equipment": ["scimitar"], + "equipment": [ + "scimitar" + ], "tier": 3 }, { @@ -304,8 +379,10 @@ "baseAtk": 40, "baseDefense": 18, "image": "assets/images/enemies/chimera.png", - "equipment": ["sunderer_axe"], + "equipment": [ + "sunderer_axe" + ], "tier": 3 } ] -} +} \ No newline at end of file diff --git a/assets/data/players.json b/assets/data/players.json index 28c0d0e..2167f13 100644 --- a/assets/data/players.json +++ b/assets/data/players.json @@ -7,7 +7,7 @@ "baseAtk": 5, "baseDefense": 5, "baseDodge": 2, - "image": "assets/images/character/warrior.png" + "image": "assets/images/character/Soldier.png" }, { "id": "rogue", @@ -19,4 +19,4 @@ "baseDodge": 15, "image": "assets/images/character/rogue.png" } -] +] \ No newline at end of file diff --git a/assets/images/character/Soldier-Attack01.png b/assets/images/character/Soldier-Attack01.png new file mode 100644 index 0000000000000000000000000000000000000000..a39e0584ae775ade04f21840a311235c750009fe GIT binary patch literal 1934 zcmb`IYcv~L7RS?EB%Kz~>rGV=(yEGhM7@$w!VKzOT3We9B4S!sAA^Rd zS0hwWTEsIn;!)EgA!v~nm1H`C29=5?R6Hj6JYVlw>zsYoI_vz_-uvwRKMyXW5I_EK z{09I4@FUXQ)eivJi&gC-4{E5^;0vfzDzgXghj0NfM)V{A0MH%jdLbaW0}U3(oGs(UfxP!muZ=@9UVP!8!O7~ z?jBKRF;eBqpEp2S!%u&uY=QuQvsqVtTSdX7p8Ck_V+6qY?EC|s+~W`ri&x>Ks}sOi z^VYjkJ4EWiy8rN4Yl+Q(P50hA-YCg|&pk_Sseo%RK0W6{5~ZrWwq zWcA#hSK-(0>({B+Llj@g(A5v7|57m6E5pKld2}g)cJ<7w-0C3erbm=JRQ97xrQ$Ck13v&HOr{<}Vai?qc7GH4u<_8oNY4|G6wiN3<>6N0+s# zay^e47RN(Kj~Yljc!J^`wRBs1hK zD10QPfj-;>FI}8TRAfxeBrJ6ELca?$Llt2b1OrH+u+Jn60{3s7YawGOK~?H7*9I37 zd|%2P^XO$?I+ldui7d@cFYs(si`bW@U$?m5Iw|JaTGO=J_PaWtSgS`@I26N4Nx8td z?J%m?Zoy*iQ`o4uJzBI(LMH=j3t`lu54Ky977=IF1~Sj#>1Lm@i9b_fv+b|nLY)lK zvm#^_4(A}QYmBSvxArI}ZMP){8pdL*Is7$ghI|D_lFZHAR9?3yetwc*yI)ndn3hR9 ztK6xos;FW;r{67=MnO zXKnega>cXaU5?0B(}6O^l}HlhRkqlvMj5DTTJP6p#i2^ng^55GpB?{?lSpfJ>mxxB zZ{}&GcEDTJIVoCRiKssWL0;75(#gka3|vI4Er7a(-l8G?y9Fx9@2|72z#Q3qQf;*) z{`NcD6!YK?QzxBM;n5pRyRcy8!DMOF#z=2-XExWu%uO(M@gLt8pC42v7fgTc+!!08 zHw?i*^w>Gy_S-KQgH|1yAsQNN7&0fn%K~jK=c#@<3OwFpe7nc&5FtH^}24diJ68KA^j?|3` zL0rRzbh0Zr4oe8BH^n426zB$mXP@X;j9<1D#n__CiegmM4Nt0CCOo0!0t43WYMBuM z$2$I0EnMC93o!&WvsCrg7M&~w=HERx2Ob)58_3_}2HfR{GF~LpC9o>Q%#H&?`wN(U zjDlF5OG=d*BAv;OjC|b0%gwl-GDpE9t0tqMWkbqMza{uxweZDy;YQ_1zooV-NivXy z4D=8OmCOAY=(bX7U>CWGhIeIkw8e0Px%|GRnI@l4OQboU~S^ z#!mZJ`*<576`}4k<|0n(PrXuaeJw9k8KR88wioAq!Ww?aj`5z^(p2PqE literal 0 HcmV?d00001 diff --git a/assets/images/character/Soldier.png b/assets/images/character/Soldier.png new file mode 100644 index 0000000000000000000000000000000000000000..f006107de917bf94ee86717690ff31dbcb314ed2 GIT binary patch literal 13244 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 Au>b%7 literal 0 HcmV?d00001 diff --git a/assets/images/enemies/Orc.png b/assets/images/enemies/Orc.png new file mode 100644 index 0000000000000000000000000000000000000000..4ef7b979619fb0be2d51885cce3c7ea2ca96385b GIT binary patch literal 1410 zcmcIk`&ZIu7-!kCRpt-wsF|WWSvYSvrMaeGtY#u}p=g=S6iYc;YUbq#h(gU%&X`en z+f?8b)5;rON=AaXwPJ^mrb$`@$vc#0Adp<$*B^HF7xbR@ytn6lKhNj$JkNQn6EG;J zZ64bo5Qq~xHaZak*^~mVv$k#l$L|ke_JGqz#fhlHkZzf$1_Jpw5*>Z$7_ntpsmfIn zyu{iQC;}`szp=i&axu%(qbKdO!STnj%QFctF8_3MYpSce|J%nM)wk*{;`5~5A?lHX z+s4ce@XhO$Mf-|hT~CwRUL8zvOObfelr`Z_p73j`T10L#x@m6JwxGRuu({j?3B>DU z;p`O?YadAEL$*)nhtuJZ$pgxEkEtcwN-*3qrE(}6wijODy7i=ONj|CfL-E?L2w%t} zO*V0@uS*rI)>lNdpFoQ|&h-uI{ph6Q4FiUpxm&qxM31Y*arf@lyWkt;Oh7+QDwTf6 zxDQ3^DywjRXS!*y(AD<9{G~#1Iy|G}xpQX?#aipV{QFg7I3Nj=A87L3wPOp|O&RmA z*YYXT<87j#zA(LC)rJdWj(+bS28RH2Xuq-7bUBGn3?5JtZb0#qYnA31{shB!b$c$A z`mTBp&syGf-WibGlapG-vYbqM3@c+-3VxL135rCn4z6T{xX(!<;`lmQA|vZO9$zk1 zNWN_-T7`mkmf-zcft^b)#S8Oqqeuf`T>WphmkLf{6(Kp> zjZar&8wib!&Miz!QZS1gv=Ss_XX*b@DWdF14O{i$Pg8Kv|B&UTR2OZNXx_fZ1r_PF;|CQ&&w# z9g~-rOxtID@|aM(CRzRt+@M2|XPIT{*de2#DzuQOqY^sPqOJ$h>8i;y*864R(t_!r zRut(q^l6l3Bvlpwl%}VW5xUJ!hW%;Kc{K=f<2Fkcr6Lwvhr*ss6qyo3D^xx%xF*5$ zCmb*+GRi=sJ(XrU#QPyEx07;_ruaE36dGE&ownPDR%tn-eWu2s|=(lU_F)Q6A z*Sx%OZSpe~z26fvw0Wc>nywsMfF222SRd_bpEmnsw{iFGa_W4DiXho)!i!CkoD*4@ z*Uuk!!dd5^(sqs^%IdOhX^3XS9fC_Zawc-jyfVvuKuAODj(A zM?c0=EWC9@Xsn9{%K{M! { : Column( mainAxisAlignment: MainAxisAlignment.center, children: [ + // const SpriteAnimationWidget( + // assetPath: 'assets/images/character/Soldier.png', + // scale: 5.0, // Make it bigger for visibility + // frameCount: + // 6, // Explicitly limit to 6 frames to avoid flickering from empty frames + // ), + // const SpriteAnimationWidget( + // assetPath: 'assets/images/character/Soldier-Attack01.png', + // scale: 5.0, // Make it bigger for visibility + // frameCount: + // 6, // Explicitly limit to 6 frames to avoid flickering from empty frames + // ), + const SizedBox(height: 20), const Icon( Icons.gavel, size: 100, diff --git a/lib/widgets/battle/character_status_card.dart b/lib/widgets/battle/character_status_card.dart index c2ac49f..d5ab7cc 100644 --- a/lib/widgets/battle/character_status_card.dart +++ b/lib/widgets/battle/character_status_card.dart @@ -5,6 +5,7 @@ import '../../game/enums.dart'; import '../../providers.dart'; import 'battle_animation_widget.dart'; import '../../game/config.dart'; +import '../test/sprite_animation_widget.dart'; // Temporary for testing class CharacterStatusCard extends StatelessWidget { final Character character; @@ -107,29 +108,27 @@ class CharacterStatusCard extends StatelessWidget { height: isPlayer ? ThemeConfig.playerImageSize : ThemeConfig.enemyImageSize, + clipBehavior: Clip.antiAlias, decoration: BoxDecoration( // color: isPlayer ? ThemeConfig.playerImageBgColor : null, borderRadius: BorderRadius.circular(8), ), child: Center( - child: (overrideImage != null || + child: + (overrideImage != null || (character.image != null && character.image!.isNotEmpty)) - ? Image.asset( - overrideImage ?? character.image!, - width: isPlayer - ? ThemeConfig.playerImageSize - : ThemeConfig.enemyImageSize, - height: isPlayer - ? ThemeConfig.playerImageSize - : ThemeConfig.enemyImageSize, - fit: BoxFit.contain, - errorBuilder: (context, error, stackTrace) { - return const Icon( - Icons.error_outline, - size: ThemeConfig.characterIconSize, - color: ThemeConfig.textColorWhite, - ); - }, + ? OverflowBox( + minWidth: 0, + maxWidth: double.infinity, + minHeight: 0, + maxHeight: double.infinity, + alignment: Alignment.center, + child: SpriteAnimationWidget( + // assetPath: 'assets/images/character/Soldier.png', + assetPath: overrideImage ?? character.image!, + scale: 5.0, // Zoomed in (300x300 in 200x200 box) + frameCount: 6, + ), ) : Icon( isPlayer ? Icons.person : Icons.psychology, diff --git a/lib/widgets/test/sprite_animation_widget.dart b/lib/widgets/test/sprite_animation_widget.dart new file mode 100644 index 0000000..eb199ca --- /dev/null +++ b/lib/widgets/test/sprite_animation_widget.dart @@ -0,0 +1,155 @@ +import 'dart:async'; +import 'dart:ui' as ui; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class SpriteAnimationWidget extends StatefulWidget { + final String assetPath; + final double tileWidth; + final double tileHeight; + final int frameCount; + final double scale; + + const SpriteAnimationWidget({ + super.key, + 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.scale = 1.0, + }); + + @override + State createState() => _SpriteAnimationWidgetState(); +} + +class _SpriteAnimationWidgetState extends State + with SingleTickerProviderStateMixin { + ui.Image? _image; + late AnimationController _controller; + bool _isLoading = true; + int _calculatedFrameCount = 6; + + @override + void initState() { + super.initState(); + _controller = AnimationController( + vsync: this, + duration: const Duration(milliseconds: 600), // 100ms per frame approx + ); + _loadImage(); + } + + Future _loadImage() async { + try { + final ByteData data = await rootBundle.load(widget.assetPath); + final List bytes = data.buffer.asUint8List(); + final Completer 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) { + debugPrint('Failed to load sprite image: $e'); + } + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + if (_isLoading || _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) { + return CustomPaint( + size: Size( + widget.tileWidth * widget.scale, + widget.tileHeight * widget.scale, + ), + painter: SpriteSheetPainter( + image: _image!, + currentFrame: + (_controller.value * _calculatedFrameCount).floor() % + _calculatedFrameCount, + tileWidth: widget.tileWidth, + tileHeight: widget.tileHeight, + scale: widget.scale, + ), + ); + }, + ); + } +} + +class SpriteSheetPainter extends CustomPainter { + final ui.Image image; + final int currentFrame; + final double tileWidth; + final double tileHeight; + final double scale; + + SpriteSheetPainter({ + required this.image, + required this.currentFrame, + required this.tileWidth, + required this.tileHeight, + required this.scale, + }); + + @override + void paint(Canvas canvas, Size size) { + // Correct src rect calculation + // Assuming horizontal strip for the animation row. + // Ideally we would want to select which 'row' (Y) to animate, but for now assuming row 0. + // If the image is a single row, srcY is 0. + final double srcX = currentFrame * tileWidth; + final double srcY = 0.0; // Default to first row + + final Rect src = Rect.fromLTWH(srcX, srcY, tileWidth, tileHeight); + final Rect dst = Rect.fromLTWH(0, 0, tileWidth * scale, tileHeight * scale); + + canvas.drawImageRect( + image, + src, + dst, + Paint()..filterQuality = FilterQuality.none, + ); + } + + @override + bool shouldRepaint(covariant SpriteSheetPainter oldDelegate) { + return oldDelegate.currentFrame != currentFrame || + oldDelegate.image != image; + } +}