This commit is contained in:
2025-12-09 16:24:52 +09:00
parent f57714b22c
commit 5b1ce14ed4
21 changed files with 282 additions and 98 deletions
+3 -8
View File
@@ -723,14 +723,9 @@ class _BattleScreenState extends State<BattleScreen> {
onPressed: () {
bool success = battleProvider.selectReward(item);
if (!success) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text(
"${AppStrings.inventoryFull} Cannot take item.",
),
backgroundColor:
ThemeConfig.snackBarErrorBg,
),
ToastUtils.showTopToast(
context,
"${AppStrings.inventoryFull} Cannot take item.",
);
}
},
+1
View File
@@ -1,2 +1,3 @@
export 'utils/game_math.dart';
export 'utils/item_utils.dart';
export 'utils/toast_utils.dart';
+78
View File
@@ -0,0 +1,78 @@
import 'package:flutter/material.dart';
import '../game/config.dart';
class ToastUtils {
static void showTopToast(
BuildContext context,
String message, {
Color? color,
}) {
final overlay = Overlay.of(context);
late OverlayEntry overlayEntry;
overlayEntry = OverlayEntry(
builder: (context) => Positioned(
top: MediaQuery.of(context).padding.top + 10,
left: 20,
right: 20,
child: Material(
color: Colors.transparent,
child: TweenAnimationBuilder<double>(
tween: Tween(begin: 0.0, end: 1.0),
duration: const Duration(milliseconds: 300),
curve: Curves.easeOutBack,
builder: (context, value, child) {
return Transform.translate(
offset: Offset(0, -50 * (1 - value)),
child: Opacity(
opacity: value.clamp(0.0, 1.0),
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 12,
),
decoration: BoxDecoration(
color: color ?? ThemeConfig.snackBarErrorBg,
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
blurRadius: 8,
offset: const Offset(0, 4),
),
],
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.info_outline, color: Colors.white),
const SizedBox(width: 12),
Expanded(
child: Text(
message,
style: const TextStyle(
color: Colors.white,
fontSize: ThemeConfig.fontSizeMedium,
fontWeight: FontWeight.bold,
),
),
),
],
),
),
),
);
},
),
),
),
);
overlay.insert(overlayEntry);
// Auto remove after duration
Future.delayed(const Duration(seconds: 2), () {
overlayEntry.remove();
});
}
}
+9 -6
View File
@@ -7,13 +7,12 @@ class BattleHeader extends StatelessWidget {
const BattleHeader({super.key});
String _getStageDisplayString(int stage) {
// 3 Stages per Tier logic
// Tier 1: 1, 2, 3 -> Underground Illegal Arena
// Tier 2: 4, 5, 6 -> Colosseum
// Tier 3: 7, 8, 9 -> King's Arena
// Tier 1: 1-12 -> Underground Illegal Arena
// Tier 2: 13-24 -> Colosseum
// Tier 3: 25-36 -> King's Arena
final int tier = (stage - 1) ~/ 3 + 1;
final int round = (stage - 1) % 3 + 1;
final int tier = (stage - 1) ~/ 12 + 1;
final int round = (stage - 1) % 12 + 1;
String tierName = "";
switch (tier) {
@@ -29,6 +28,10 @@ class BattleHeader extends StatelessWidget {
break;
}
if (round == 12) {
return "$tierName - BOSS";
}
return "$tierName - $round";
}
+15 -2
View File
@@ -122,11 +122,24 @@ class CharacterStatusCard extends StatelessWidget {
size: 60,
color: ThemeConfig.textColorWhite,
) // 플레이어 아이콘
: Image.asset(
'assets/data/enemy/enemy_01.png',
: (character.image != null && character.image!.isNotEmpty)
? Image.asset(
character.image!,
width: 200,
height: 200,
fit: BoxFit.contain,
errorBuilder: (context, error, stackTrace) {
return const Icon(
Icons.psychology,
size: 60,
color: ThemeConfig.textColorWhite,
);
},
)
: const Icon(
Icons.psychology,
size: 60,
color: ThemeConfig.textColorWhite,
), // 적 이미지
),
),
+18 -20
View File
@@ -6,6 +6,7 @@ import '../../../game/model/item.dart';
import '../../../game/config/theme_config.dart';
import '../../../game/config/game_config.dart';
import '../../../game/model/entity.dart';
import '../../utils.dart'; // Import for ToastUtils
import '../inventory/inventory_grid_widget.dart';
import '../common/item_card_widget.dart';
@@ -115,6 +116,7 @@ class ShopUI extends StatelessWidget {
item,
shopProvider,
player,
battleProvider, // Pass battleProvider
),
child: ItemCardWidget(
item: item,
@@ -155,11 +157,9 @@ class ShopUI extends StatelessWidget {
battleProvider.stage,
);
if (!success) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text("Not enough gold to reroll!"),
backgroundColor: Colors.red,
),
ToastUtils.showTopToast(
context,
"Not enough gold to reroll!",
);
}
}
@@ -205,13 +205,13 @@ class ShopUI extends StatelessWidget {
Item item,
ShopProvider shopProvider,
Character player,
BattleProvider battleProvider,
) {
if (player.gold < item.price) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text("Not enough gold!"),
backgroundColor: Colors.red,
),
ToastUtils.showTopToast(
context,
"Not enough gold!",
color: ThemeConfig.snackBarErrorBg,
);
return;
}
@@ -236,18 +236,16 @@ class ShopUI extends StatelessWidget {
if (success) {
battleProvider.refreshUI(); // Update UI
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text("Bought ${item.name}"),
backgroundColor: Colors.green,
),
ToastUtils.showTopToast(
context,
"Bought ${item.name}",
color: Colors.green,
);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(shopProvider.lastShopMessage),
backgroundColor: Colors.red,
),
ToastUtils.showTopToast(
context,
shopProvider.lastShopMessage,
color: ThemeConfig.snackBarErrorBg,
);
}
},