diff --git a/assets/images/components/key.png b/assets/images/components/key.png new file mode 100644 index 00000000..588c2b89 Binary files /dev/null and b/assets/images/components/key.png differ diff --git a/lib/gen/assets.gen.dart b/lib/gen/assets.gen.dart index f5b935a5..d26f842c 100644 --- a/lib/gen/assets.gen.dart +++ b/lib/gen/assets.gen.dart @@ -47,6 +47,10 @@ class $AssetsImagesComponentsGen { /// File path: assets/images/components/background.png AssetGenImage get background => const AssetGenImage('assets/images/components/background.png'); + + /// File path: assets/images/components/key.png + AssetGenImage get key => + const AssetGenImage('assets/images/components/key.png'); } class $AssetsImagesScoreGen { diff --git a/lib/l10n/arb/app_en.arb b/lib/l10n/arb/app_en.arb index 9655d8be..e161f840 100644 --- a/lib/l10n/arb/app_en.arb +++ b/lib/l10n/arb/app_en.arb @@ -8,6 +8,10 @@ "@howToPlay": { "description": "Text displayed on the landing page how to play button" }, + "tipsForFlips": "Tips for flips", + "@tipsForFlips": { + "description": "Text displayed on the landing page how to play button" + }, "launchControls": "Launch Controls", "@launchControls": { "description": "Text displayed on the how to play dialog with the launch controls" @@ -24,6 +28,10 @@ "@select": { "description": "Text displayed on the character selection page select button" }, + "space": "Space", + "@space": { + "description": "Text displayed on space control button" + }, "characterSelectionTitle": "Choose your character!", "@characterSelectionTitle": { "description": "Title text displayed on the character selection page" @@ -80,4 +88,4 @@ "@rounds": { "description": "Text displayed on the scoreboard widget to indicate rounds left" } -} +} \ No newline at end of file diff --git a/lib/start_game/widgets/how_to_play_dialog.dart b/lib/start_game/widgets/how_to_play_dialog.dart index 4a9cbfbf..0f03bada 100644 --- a/lib/start_game/widgets/how_to_play_dialog.dart +++ b/lib/start_game/widgets/how_to_play_dialog.dart @@ -1,9 +1,21 @@ // ignore_for_file: public_member_api_docs import 'package:flutter/material.dart'; +import 'package:pinball/gen/gen.dart'; import 'package:pinball/l10n/l10n.dart'; +import 'package:pinball/theme/theme.dart'; import 'package:pinball_ui/pinball_ui.dart'; +enum Control { + left, + right, + down, + a, + d, + s, + space, +} + class HowToPlayDialog extends StatelessWidget { const HowToPlayDialog({Key? key}) : super(key: key); @@ -11,9 +23,26 @@ class HowToPlayDialog extends StatelessWidget { Widget build(BuildContext context) { final l10n = context.l10n; const spacing = SizedBox(height: 16); + final headerTextStyle = AppTextStyle.headline3.copyWith( + color: AppColors.darkBlue, + ); return PinballDialogLayout( - header: Text(l10n.howToPlay), + header: FittedBox( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + l10n.howToPlay, + style: headerTextStyle.copyWith(fontWeight: FontWeight.bold), + ), + Text( + l10n.tipsForFlips, + style: headerTextStyle, + ), + ], + ), + ), body: ListView( children: const [ spacing, @@ -36,15 +65,21 @@ class _LaunchControls extends StatelessWidget { return Column( children: [ - Text(l10n.launchControls), + Text( + l10n.launchControls, + style: AppTextStyle.headline3.copyWith( + color: AppColors.white, + fontSize: 16, + ), + ), const SizedBox(height: 10), Wrap( children: const [ - KeyIndicator.fromIcon(keyIcon: Icons.keyboard_arrow_down), + KeyButton(control: Control.down), spacing, - KeyIndicator.fromKeyName(keyName: 'SPACE'), + KeyButton(control: Control.space), spacing, - KeyIndicator.fromKeyName(keyName: 'S'), + KeyButton(control: Control.s), ], ) ], @@ -62,7 +97,13 @@ class _FlipperControls extends StatelessWidget { return Column( children: [ - Text(l10n.flipperControls), + Text( + l10n.flipperControls, + style: AppTextStyle.headline3.copyWith( + color: AppColors.white, + fontSize: 16, + ), + ), const SizedBox(height: 10), Column( children: [ @@ -70,17 +111,17 @@ class _FlipperControls extends StatelessWidget { mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: const [ - KeyIndicator.fromIcon(keyIcon: Icons.keyboard_arrow_left), + KeyButton(control: Control.left), rowSpacing, - KeyIndicator.fromIcon(keyIcon: Icons.keyboard_arrow_right), + KeyButton(control: Control.right), ], ), const SizedBox(height: 8), Wrap( children: const [ - KeyIndicator.fromKeyName(keyName: 'A'), + KeyButton(control: Control.a), rowSpacing, - KeyIndicator.fromKeyName(keyName: 'D'), + KeyButton(control: Control.d), ], ) ], @@ -90,65 +131,69 @@ class _FlipperControls extends StatelessWidget { } } -// TODO(allisonryan0002): remove visibility when adding final UI. @visibleForTesting -class KeyIndicator extends StatelessWidget { - const KeyIndicator._({ +class KeyButton extends StatelessWidget { + const KeyButton({ Key? key, - required String keyName, - required IconData keyIcon, - required bool fromIcon, - }) : _keyName = keyName, - _keyIcon = keyIcon, - _fromIcon = fromIcon, - super(key: key); + required this.control, + }) : super(key: key); - const KeyIndicator.fromKeyName({Key? key, required String keyName}) - : this._( - key: key, - keyName: keyName, - keyIcon: Icons.keyboard_arrow_down, - fromIcon: false, - ); - - const KeyIndicator.fromIcon({Key? key, required IconData keyIcon}) - : this._( - key: key, - keyName: '', - keyIcon: keyIcon, - fromIcon: true, - ); - - final String _keyName; - - final IconData _keyIcon; - - final bool _fromIcon; + final Control control; @override Widget build(BuildContext context) { - const iconPadding = EdgeInsets.all(15); - const textPadding = EdgeInsets.symmetric(vertical: 20, horizontal: 22); - final boarderColor = Colors.blue.withOpacity(0.5); - final color = Colors.blue.withOpacity(0.7); - + final textStyle = + control.isArrow ? AppTextStyle.headline1 : AppTextStyle.headline3; + const height = 60.0; + final width = control.isSpace ? height * 2.83 : height; return DecoratedBox( decoration: BoxDecoration( - borderRadius: BorderRadius.circular(5), - border: Border.all( - color: boarderColor, - width: 3, + image: DecorationImage( + fit: BoxFit.fill, + image: AssetImage( + Assets.images.components.key.keyName, + ), ), ), - child: _fromIcon - ? Padding( - padding: iconPadding, - child: Icon(_keyIcon, color: color), - ) - : Padding( - padding: textPadding, - child: Text(_keyName, style: TextStyle(color: color)), + child: SizedBox( + width: width, + height: height, + child: Center( + child: RotatedBox( + quarterTurns: control.isDown ? 1 : 0, + child: Text( + control.getCharacter(context), + style: textStyle.copyWith(color: AppColors.white), ), + ), + ), + ), ); } } + +extension on Control { + bool get isArrow => isDown || isRight || isLeft; + bool get isDown => this == Control.down; + bool get isRight => this == Control.right; + bool get isLeft => this == Control.left; + bool get isSpace => this == Control.space; + String getCharacter(BuildContext context) { + switch (this) { + case Control.a: + return 'A'; + case Control.d: + return 'D'; + case Control.down: + return '>'; // Will be rotated + case Control.left: + return '<'; + case Control.right: + return '>'; + case Control.s: + return 'S'; + case Control.space: + return context.l10n.space; + } + } +} diff --git a/test/start_game/widgets/how_to_play_dialog_test.dart b/test/start_game/widgets/how_to_play_dialog_test.dart index c31ac1a3..8bcca2a7 100644 --- a/test/start_game/widgets/how_to_play_dialog_test.dart +++ b/test/start_game/widgets/how_to_play_dialog_test.dart @@ -9,34 +9,28 @@ import '../../helpers/helpers.dart'; void main() { group('HowToPlayDialog', () { - testWidgets('displays content', (tester) async { - final l10n = await AppLocalizations.delegate.load(Locale('en')); + late AppLocalizations l10n; - await tester.pumpApp(HowToPlayDialog()); + setUp(() async { + l10n = await AppLocalizations.delegate.load(Locale('en')); + }); + testWidgets('displays content', (tester) async { + await tester.pumpApp(HowToPlayDialog()); + expect(find.text(l10n.howToPlay), findsOneWidget); + expect(find.text(l10n.tipsForFlips), findsOneWidget); expect(find.text(l10n.launchControls), findsOneWidget); + expect(find.text(l10n.flipperControls), findsOneWidget); }); }); - group('KeyIndicator', () { - testWidgets('fromKeyName renders correctly', (tester) async { - const keyName = 'A'; - - await tester.pumpApp( - KeyIndicator.fromKeyName(keyName: keyName), - ); - - expect(find.text(keyName), findsOneWidget); - }); - - testWidgets('fromIcon renders correctly', (tester) async { - const keyIcon = Icons.keyboard_arrow_down; - + group('KeyButton', () { + testWidgets('renders correctly', (tester) async { await tester.pumpApp( - KeyIndicator.fromIcon(keyIcon: keyIcon), + KeyButton(control: Control.a), ); - expect(find.byIcon(keyIcon), findsOneWidget); + expect(find.text('A'), findsOneWidget); }); }); }