mirror of https://github.com/flutter/pinball.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
123 lines
3.4 KiB
123 lines
3.4 KiB
import 'package:flutter/material.dart';
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
import 'package:pinball/game/game.dart';
|
|
import 'package:pinball/gen/gen.dart';
|
|
import 'package:pinball_ui/pinball_ui.dart';
|
|
|
|
/// {@template game_hud}
|
|
/// Overlay on the [PinballGame].
|
|
///
|
|
/// Displays the current [GameState.displayScore], [GameState.rounds] and
|
|
/// animates when the player gets a [GameBonus].
|
|
/// {@endtemplate}
|
|
class GameHud extends StatefulWidget {
|
|
/// {@macro game_hud}
|
|
const GameHud({Key? key}) : super(key: key);
|
|
|
|
@override
|
|
State<GameHud> createState() => _GameHudState();
|
|
}
|
|
|
|
class _GameHudState extends State<GameHud> {
|
|
bool showAnimation = false;
|
|
|
|
/// Ratio from sprite frame (width 500, height 144) w / h = ratio
|
|
static const _ratio = 3.47;
|
|
static const _width = 265.0;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final isGameOver = context.select((GameBloc bloc) => bloc.state.isGameOver);
|
|
|
|
return _ScoreViewDecoration(
|
|
child: SizedBox(
|
|
height: _width / _ratio,
|
|
width: _width,
|
|
child: BlocListener<GameBloc, GameState>(
|
|
listenWhen: (previous, current) =>
|
|
previous.bonusHistory.length != current.bonusHistory.length,
|
|
listener: (_, __) => setState(() => showAnimation = true),
|
|
child: AnimatedSwitcher(
|
|
duration: kThemeAnimationDuration,
|
|
child: showAnimation && !isGameOver
|
|
? _AnimationView(
|
|
onComplete: () {
|
|
if (mounted) {
|
|
setState(() => showAnimation = false);
|
|
}
|
|
},
|
|
)
|
|
: const ScoreView(),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _ScoreViewDecoration extends StatelessWidget {
|
|
const _ScoreViewDecoration({
|
|
Key? key,
|
|
required this.child,
|
|
}) : super(key: key);
|
|
|
|
final Widget child;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
const radius = BorderRadius.all(Radius.circular(12));
|
|
const borderWidth = 5.0;
|
|
|
|
return DecoratedBox(
|
|
decoration: BoxDecoration(
|
|
borderRadius: radius,
|
|
border: Border.all(
|
|
color: PinballColors.white,
|
|
width: borderWidth,
|
|
),
|
|
image: DecorationImage(
|
|
fit: BoxFit.cover,
|
|
image: AssetImage(
|
|
Assets.images.score.miniScoreBackground.path,
|
|
),
|
|
),
|
|
),
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(borderWidth - 1),
|
|
child: ClipRRect(
|
|
borderRadius: radius,
|
|
child: child,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _AnimationView extends StatelessWidget {
|
|
const _AnimationView({
|
|
Key? key,
|
|
required this.onComplete,
|
|
}) : super(key: key);
|
|
|
|
final VoidCallback onComplete;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final lastBonus = context.select(
|
|
(GameBloc bloc) => bloc.state.bonusHistory.last,
|
|
);
|
|
switch (lastBonus) {
|
|
case GameBonus.dashNest:
|
|
return BonusAnimation.dashNest(onCompleted: onComplete);
|
|
case GameBonus.sparkyTurboCharge:
|
|
return BonusAnimation.sparkyTurboCharge(onCompleted: onComplete);
|
|
case GameBonus.dinoChomp:
|
|
return BonusAnimation.dinoChomp(onCompleted: onComplete);
|
|
case GameBonus.googleWord:
|
|
return BonusAnimation.googleWord(onCompleted: onComplete);
|
|
case GameBonus.androidSpaceship:
|
|
return BonusAnimation.androidSpaceship(onCompleted: onComplete);
|
|
}
|
|
}
|
|
}
|