- ArenaScreen: 아레나 메인 화면 - ArenaSetupScreen: 전투 설정 화면 - ArenaBattleScreen: 전투 진행 화면 - 관련 위젯 추가
209 lines
5.4 KiB
Dart
209 lines
5.4 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
import 'package:asciineverdie/src/core/l10n/game_data_l10n.dart';
|
|
import 'package:asciineverdie/src/core/model/hall_of_fame.dart';
|
|
import 'package:asciineverdie/src/shared/retro_colors.dart';
|
|
|
|
/// 아레나 순위 카드 위젯
|
|
///
|
|
/// 명예의 전당 캐릭터를 순위와 함께 표시
|
|
class ArenaRankCard extends StatelessWidget {
|
|
const ArenaRankCard({
|
|
super.key,
|
|
required this.entry,
|
|
required this.rank,
|
|
required this.score,
|
|
this.isSelected = false,
|
|
this.isHighlighted = false,
|
|
this.compact = false,
|
|
this.onTap,
|
|
});
|
|
|
|
/// 캐릭터 엔트리
|
|
final HallOfFameEntry entry;
|
|
|
|
/// 순위 (1-based)
|
|
final int rank;
|
|
|
|
/// 아레나 점수
|
|
final int score;
|
|
|
|
/// 선택 상태 (상대로 선택됨)
|
|
final bool isSelected;
|
|
|
|
/// 하이라이트 상태 (내 캐릭터 표시)
|
|
final bool isHighlighted;
|
|
|
|
/// 컴팩트 모드 (작은 사이즈)
|
|
final bool compact;
|
|
|
|
/// 탭 콜백
|
|
final VoidCallback? onTap;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final rankColor = _getRankColor(rank);
|
|
final rankIcon = _getRankIcon(rank);
|
|
|
|
// 배경색 결정
|
|
Color bgColor;
|
|
Color borderColor;
|
|
if (isSelected) {
|
|
bgColor = Colors.red.withValues(alpha: 0.15);
|
|
borderColor = Colors.red;
|
|
} else if (isHighlighted) {
|
|
bgColor = Colors.blue.withValues(alpha: 0.15);
|
|
borderColor = Colors.blue;
|
|
} else {
|
|
bgColor = RetroColors.panelBgOf(context);
|
|
borderColor = RetroColors.borderOf(context);
|
|
}
|
|
|
|
return Card(
|
|
margin: EdgeInsets.symmetric(
|
|
vertical: compact ? 2 : 4,
|
|
horizontal: compact ? 0 : 8,
|
|
),
|
|
color: bgColor,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(compact ? 6 : 8),
|
|
side: BorderSide(
|
|
color: borderColor,
|
|
width: (isSelected || isHighlighted) ? 2 : 1,
|
|
),
|
|
),
|
|
child: InkWell(
|
|
onTap: onTap,
|
|
borderRadius: BorderRadius.circular(compact ? 6 : 8),
|
|
child: Padding(
|
|
padding: EdgeInsets.all(compact ? 8 : 12),
|
|
child: Row(
|
|
children: [
|
|
// 순위 배지
|
|
_buildRankBadge(rankColor, rankIcon),
|
|
SizedBox(width: compact ? 8 : 12),
|
|
// 캐릭터 정보
|
|
Expanded(child: _buildCharacterInfo(context)),
|
|
// 점수
|
|
if (!compact) _buildScoreColumn(context),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildRankBadge(Color color, IconData? icon) {
|
|
final size = compact ? 24.0 : 36.0;
|
|
final iconSize = compact ? 12.0 : 18.0;
|
|
final fontSize = compact ? 7.0 : 10.0;
|
|
|
|
return Container(
|
|
width: size,
|
|
height: size,
|
|
decoration: BoxDecoration(
|
|
color: color.withValues(alpha: 0.2),
|
|
shape: BoxShape.circle,
|
|
border: Border.all(color: color, width: compact ? 1.5 : 2),
|
|
),
|
|
child: Center(
|
|
child: icon != null
|
|
? Icon(icon, color: color, size: iconSize)
|
|
: Text(
|
|
'$rank',
|
|
style: TextStyle(
|
|
fontFamily: 'PressStart2P',
|
|
fontSize: fontSize,
|
|
color: color,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildCharacterInfo(BuildContext context) {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// 이름
|
|
Text(
|
|
entry.characterName,
|
|
style: TextStyle(
|
|
fontFamily: 'PressStart2P',
|
|
fontSize: compact ? 6 : 9,
|
|
color: RetroColors.textPrimaryOf(context),
|
|
),
|
|
overflow: TextOverflow.ellipsis,
|
|
maxLines: 1,
|
|
),
|
|
SizedBox(height: compact ? 2 : 4),
|
|
// 종족/클래스 + 레벨
|
|
Text(
|
|
compact
|
|
? 'Lv.${entry.level}'
|
|
: '${GameDataL10n.getRaceName(context, entry.race)} '
|
|
'${GameDataL10n.getKlassName(context, entry.klass)} '
|
|
'Lv.${entry.level}',
|
|
style: TextStyle(
|
|
fontFamily: 'PressStart2P',
|
|
fontSize: compact ? 5 : 7,
|
|
color: RetroColors.textSecondaryOf(context),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _buildScoreColumn(BuildContext context) {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.end,
|
|
children: [
|
|
Text(
|
|
'$score',
|
|
style: TextStyle(
|
|
fontFamily: 'PressStart2P',
|
|
fontSize: 10,
|
|
color: RetroColors.goldOf(context),
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
Text(
|
|
'SCORE',
|
|
style: TextStyle(
|
|
fontFamily: 'PressStart2P',
|
|
fontSize: 6,
|
|
color: RetroColors.textMutedOf(context),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
Color _getRankColor(int rank) {
|
|
switch (rank) {
|
|
case 1:
|
|
return Colors.amber.shade700;
|
|
case 2:
|
|
return Colors.grey.shade500;
|
|
case 3:
|
|
return Colors.brown.shade400;
|
|
default:
|
|
return Colors.blue.shade400;
|
|
}
|
|
}
|
|
|
|
IconData? _getRankIcon(int rank) {
|
|
switch (rank) {
|
|
case 1:
|
|
return Icons.emoji_events;
|
|
case 2:
|
|
return Icons.workspace_premium;
|
|
case 3:
|
|
return Icons.military_tech;
|
|
default:
|
|
return null;
|
|
}
|
|
}
|
|
}
|