refactoring : barrel pattern
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../game/enums.dart';
|
||||
import '../../game/config.dart';
|
||||
|
||||
class BattleControls extends StatelessWidget {
|
||||
final bool isAttackEnabled;
|
||||
final bool isDefendEnabled;
|
||||
final VoidCallback onAttackPressed;
|
||||
final VoidCallback onDefendPressed;
|
||||
|
||||
const BattleControls({
|
||||
super.key,
|
||||
required this.isAttackEnabled,
|
||||
required this.isDefendEnabled,
|
||||
required this.onAttackPressed,
|
||||
required this.onDefendPressed,
|
||||
});
|
||||
|
||||
Widget _buildFloatingActionButton({
|
||||
required String label,
|
||||
required Color color,
|
||||
required ActionType actionType,
|
||||
required bool isEnabled,
|
||||
required VoidCallback onPressed,
|
||||
}) {
|
||||
String iconPath;
|
||||
if (actionType == ActionType.attack) {
|
||||
iconPath = 'assets/data/icon/icon_weapon.png';
|
||||
} else {
|
||||
iconPath = 'assets/data/icon/icon_shield.png';
|
||||
}
|
||||
|
||||
return FloatingActionButton(
|
||||
heroTag: label,
|
||||
onPressed: isEnabled ? onPressed : null,
|
||||
backgroundColor: isEnabled ? color : ThemeConfig.btnDisabled,
|
||||
child: Image.asset(
|
||||
iconPath,
|
||||
width: 32,
|
||||
height: 32,
|
||||
color: ThemeConfig.textColorWhite, // Tint icon white
|
||||
fit: BoxFit.contain,
|
||||
filterQuality: FilterQuality.high,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
_buildFloatingActionButton(
|
||||
label: "ATK",
|
||||
color: ThemeConfig.btnActionActive,
|
||||
actionType: ActionType.attack,
|
||||
isEnabled: isAttackEnabled,
|
||||
onPressed: onAttackPressed,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
_buildFloatingActionButton(
|
||||
label: "DEF",
|
||||
color: ThemeConfig.btnDefendActive,
|
||||
actionType: ActionType.defend,
|
||||
isEnabled: isDefendEnabled,
|
||||
onPressed: onDefendPressed,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../providers.dart';
|
||||
import '../../game/config.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
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
|
||||
|
||||
final int tier = (stage - 1) ~/ 3 + 1;
|
||||
final int round = (stage - 1) % 3 + 1;
|
||||
String tierName = "";
|
||||
|
||||
switch (tier) {
|
||||
case 1:
|
||||
tierName = "지하 불법 투기장";
|
||||
break;
|
||||
case 2:
|
||||
tierName = "콜로세움";
|
||||
break;
|
||||
case 3:
|
||||
default:
|
||||
tierName = "왕의 투기장";
|
||||
break;
|
||||
}
|
||||
|
||||
return "Tier $tier $tierName - $round";
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final battleProvider = context.watch<BattleProvider>();
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Flexible(
|
||||
child: FittedBox(
|
||||
fit: BoxFit.scaleDown,
|
||||
child: Text(
|
||||
_getStageDisplayString(battleProvider.stage),
|
||||
style: const TextStyle(
|
||||
color: ThemeConfig.textColorWhite,
|
||||
fontSize: ThemeConfig.fontSizeLarge,
|
||||
fontWeight: ThemeConfig.fontWeightBold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: FittedBox(
|
||||
fit: BoxFit.scaleDown,
|
||||
child: Text(
|
||||
"${AppStrings.turn} ${battleProvider.turnCount}",
|
||||
style: const TextStyle(
|
||||
color: ThemeConfig.textColorWhite,
|
||||
fontSize: ThemeConfig.fontSizeHeader,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../../game/model/entity.dart';
|
||||
import '../../game/models.dart';
|
||||
import '../../game/enums.dart';
|
||||
import '../../providers/battle_provider.dart';
|
||||
import '../../providers.dart';
|
||||
import 'battle_animation_widget.dart';
|
||||
import '../../game/config/theme_config.dart';
|
||||
import '../../game/config/animation_config.dart';
|
||||
import '../../game/config.dart';
|
||||
|
||||
class CharacterStatusCard extends StatelessWidget {
|
||||
final Character character;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../game/config/theme_config.dart';
|
||||
import '../../game/config/animation_config.dart';
|
||||
import '../../game/config.dart';
|
||||
|
||||
class FloatingDamageText extends StatefulWidget {
|
||||
final String damage;
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../game/enums.dart';
|
||||
import '../../game/models.dart';
|
||||
import '../../game/config.dart';
|
||||
|
||||
class RiskSelectionDialog extends StatelessWidget {
|
||||
final ActionType actionType;
|
||||
final Character player;
|
||||
final Function(RiskLevel) onSelected;
|
||||
|
||||
const RiskSelectionDialog({
|
||||
super.key,
|
||||
required this.actionType,
|
||||
required this.player,
|
||||
required this.onSelected,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final baseValue = actionType == ActionType.attack
|
||||
? player.totalAtk
|
||||
: player.totalDefense;
|
||||
|
||||
return SimpleDialog(
|
||||
title: Text("Select Risk Level for ${actionType.name}"),
|
||||
children: RiskLevel.values.map((risk) {
|
||||
String infoText = "";
|
||||
Color infoColor = Colors.black;
|
||||
double efficiency = 0.0;
|
||||
int expectedValue = 0;
|
||||
|
||||
switch (risk) {
|
||||
case RiskLevel.safe:
|
||||
efficiency = actionType == ActionType.attack
|
||||
? BattleConfig.attackSafeEfficiency
|
||||
: BattleConfig.defendSafeEfficiency;
|
||||
infoColor = ThemeConfig.riskSafe;
|
||||
break;
|
||||
case RiskLevel.normal:
|
||||
efficiency = actionType == ActionType.attack
|
||||
? BattleConfig.attackNormalEfficiency
|
||||
: BattleConfig.defendNormalEfficiency;
|
||||
infoColor = ThemeConfig.riskNormal;
|
||||
break;
|
||||
case RiskLevel.risky:
|
||||
efficiency = actionType == ActionType.attack
|
||||
? BattleConfig.attackRiskyEfficiency
|
||||
: BattleConfig.defendRiskyEfficiency;
|
||||
infoColor = ThemeConfig.riskRisky;
|
||||
break;
|
||||
}
|
||||
|
||||
expectedValue = (baseValue * efficiency).toInt();
|
||||
String valueUnit = actionType == ActionType.attack ? "Dmg" : "Armor";
|
||||
|
||||
double baseChance = 0.0;
|
||||
switch (risk) {
|
||||
case RiskLevel.safe:
|
||||
baseChance = BattleConfig.safeBaseChance;
|
||||
break;
|
||||
case RiskLevel.normal:
|
||||
baseChance = BattleConfig.normalBaseChance;
|
||||
break;
|
||||
case RiskLevel.risky:
|
||||
baseChance = BattleConfig.riskyBaseChance;
|
||||
break;
|
||||
}
|
||||
|
||||
double finalChance = baseChance + (player.totalLuck / 100.0);
|
||||
if (finalChance > 1.0) finalChance = 1.0;
|
||||
String successRate = "${(finalChance * 100).toInt()}%";
|
||||
|
||||
infoText =
|
||||
"Success: $successRate, Eff: ${(efficiency * 100).toInt()}% ($expectedValue $valueUnit)";
|
||||
|
||||
return SimpleDialogOption(
|
||||
onPressed: () => onSelected(risk),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
risk.name,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
Text(infoText, style: TextStyle(fontSize: 12, color: infoColor)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user