Files
BlockSeasons/lib/ui/widgets/hud_widget.dart
T
2026-06-12 07:13:47 +09:00

90 lines
2.7 KiB
Dart

import 'package:flutter/material.dart';
import '../../game/models/objective.dart';
import '../../state/game_session_notifier.dart';
class HudWidget extends StatelessWidget {
const HudWidget({super.key, required this.view});
final GameViewState view;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Visibility(
visible: !view.endless,
maintainSize: true,
maintainAnimation: true,
maintainState: true,
child: _movesChip(theme),
),
AnimatedSwitcher(
duration: const Duration(milliseconds: 200),
transitionBuilder: (child, anim) =>
ScaleTransition(scale: anim, child: child),
child: Text(
'${view.score}',
key: ValueKey(view.score),
style: theme.textTheme.headlineMedium
?.copyWith(fontWeight: FontWeight.w800),
),
),
_comboChip(theme),
],
),
const SizedBox(height: 8),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
for (final obj in view.objectives) ...[
_objectiveChip(theme, obj),
const SizedBox(width: 12),
],
],
),
],
);
}
Widget _movesChip(ThemeData theme) {
return Chip(
avatar: const Icon(Icons.swipe, size: 18),
label: Text('${view.movesLeft}'),
labelStyle: theme.textTheme.titleMedium,
);
}
Widget _comboChip(ThemeData theme) {
final visible = view.comboStreak >= 2;
return AnimatedOpacity(
duration: const Duration(milliseconds: 150),
opacity: visible ? 1 : 0,
child: Chip(
avatar: const Icon(Icons.local_fire_department,
size: 18, color: Colors.deepOrange),
label: Text('x${view.comboStreak}'),
labelStyle: theme.textTheme.titleMedium,
),
);
}
Widget _objectiveChip(ThemeData theme, Objective obj) {
final (icon, color) = switch (obj) {
ClearGemsObjective() => (Icons.diamond, const Color(0xFF7CF5FF)),
ReachScoreObjective() => (Icons.star, Colors.amber),
ClearLinesObjective() => (Icons.table_rows, Colors.lightGreen),
};
final done = obj.isComplete;
return Chip(
avatar: Icon(done ? Icons.check_circle : icon, size: 18, color: color),
label: Text('${obj.current.clamp(0, obj.target)}/${obj.target}'),
labelStyle: theme.textTheme.titleSmall,
);
}
}