feat: adding mobile controls

pull/377/head
Erick Zanardo 3 years ago
parent a55fec26e4
commit 72f8b6c5a4

@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
import 'package:leaderboard_repository/leaderboard_repository.dart';
import 'package:pinball/game/components/backbox/bloc/backbox_bloc.dart';
import 'package:pinball/game/components/backbox/displays/displays.dart';
import 'package:pinball/game/game.dart';
import 'package:pinball_components/pinball_components.dart';
import 'package:pinball_flame/pinball_flame.dart';
import 'package:pinball_theme/pinball_theme.dart' hide Assets;
@ -12,7 +13,7 @@ import 'package:pinball_theme/pinball_theme.dart' hide Assets;
/// {@template backbox}
/// The [Backbox] of the pinball machine.
/// {@endtemplate}
class Backbox extends PositionComponent with ZIndex {
class Backbox extends PositionComponent with ZIndex, HasGameRef {
/// {@macro backbox}
Backbox({
required LeaderboardRepository leaderboardRepository,
@ -58,6 +59,8 @@ class Backbox extends PositionComponent with ZIndex {
} else if (state is LeaderboardSuccessState) {
_display.add(LeaderboardDisplay(entries: state.entries));
} else if (state is InitialsFormState) {
// TODO check
gameRef.overlays.add(PinballGame.mobileControlsOverlay);
_display.add(
InitialsInputDisplay(
score: state.score,

@ -7,6 +7,8 @@ import 'package:flame/input.dart';
import 'package:flame_bloc/flame_bloc.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:leaderboard_repository/leaderboard_repository.dart';
import 'package:pinball/game/behaviors/behaviors.dart';
import 'package:pinball/game/game.dart';
@ -38,6 +40,9 @@ class PinballGame extends PinballForge2DGame
/// Identifier of the play button overlay
static const playButtonOverlay = 'play_button';
/// Identifier of the mobile controls overlay
static const mobileControlsOverlay = 'mobile_controls';
@override
Color backgroundColor() => Colors.transparent;
@ -112,6 +117,16 @@ class PinballGame extends PinballForge2DGame
final focusedBoardSide = <int, BoardSide>{};
void triggerVirtualKeyUp(LogicalKeyboardKey key) {
final keyControllers = descendants().whereType<KeyboardInputController>();
for (final controller in keyControllers) {
if (!controller.onVirtualKeyUp(key)) {
break;
}
}
}
@override
void onTapDown(int pointerId, TapDownInfo info) {
if (info.raw.kind == PointerDeviceKind.touch) {

@ -3,6 +3,7 @@
import 'package:flame/game.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:leaderboard_repository/leaderboard_repository.dart';
import 'package:pinball/assets_manager/assets_manager.dart';
@ -137,6 +138,36 @@ class PinballGameLoadedView extends StatelessWidget {
child: PlayButtonOverlay(),
);
},
PinballGame.mobileControlsOverlay: (context, game) {
return Positioned(
bottom: 0,
left: 0,
right: 0,
child: MobileControls(
onTapUp: () {
game.triggerVirtualKeyUp(LogicalKeyboardKey.arrowUp);
},
onTapDown: () {
game.triggerVirtualKeyUp(
LogicalKeyboardKey.arrowDown,
);
},
onTapLeft: () {
game.triggerVirtualKeyUp(
LogicalKeyboardKey.arrowLeft,
);
},
onTapRight: () {
game.triggerVirtualKeyUp(
LogicalKeyboardKey.arrowRight,
);
},
onTapEnter: () {
game.triggerVirtualKeyUp(LogicalKeyboardKey.enter);
},
),
);
},
},
),
),

@ -0,0 +1,51 @@
import 'package:flutter/material.dart';
import 'package:pinball/game/game.dart';
import 'package:pinball_ui/pinball_ui.dart';
/// {@template mobile_controls}
/// Widget with the controls used to enable the user initials input on mobile.
/// {@endtemplate}
class MobileControls extends StatelessWidget {
/// {@macro mobile_controls}
const MobileControls({Key? key,
required this.onTapUp,
required this.onTapDown,
required this.onTapLeft,
required this.onTapRight,
required this.onTapEnter,
}) : super(key: key);
/// Called when dpad up is pressed
final VoidCallback onTapUp;
/// Called when dpad down is pressed
final VoidCallback onTapDown;
/// Called when dpad left is pressed
final VoidCallback onTapLeft;
/// Called when dpad right is pressed
final VoidCallback onTapRight;
/// Called when enter is pressed
final VoidCallback onTapEnter;
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
MobileDpad(
onTapUp: onTapUp,
onTapDown: onTapUp,
onTapLeft: onTapLeft,
onTapRight: onTapRight,
),
PinballButton(
text: 'Enter', // TODO l10n
onTap: onTapEnter,
),
],
);
}
}

@ -0,0 +1,75 @@
import 'package:flutter/material.dart';
import 'package:pinball_ui/pinball_ui.dart';
/// {@template mobile_dpad}
/// Widget that renders a 4 direction dpad.
/// {@endtemplate}
class MobileDpad extends StatelessWidget {
/// {@template mobile_dpad}
const MobileDpad({
Key? key,
required this.onTapUp,
required this.onTapDown,
required this.onTapLeft,
required this.onTapRight,
}) : super(key: key);
static const _size = 180.0;
/// Called when dpad up is pressed
final VoidCallback onTapUp;
/// Called when dpad down is pressed
final VoidCallback onTapDown;
/// Called when dpad left is pressed
final VoidCallback onTapLeft;
/// Called when dpad right is pressed
final VoidCallback onTapRight;
@override
Widget build(BuildContext context) {
return SizedBox(
width: _size,
height: _size,
child: Column(
children: [
Row(
children: [
const Expanded(child: SizedBox()),
PinballDpadButton(
direction: PinballDpadDirection.up,
onTap: onTapUp,
),
const Expanded(child: SizedBox()),
],
),
Row(
children: [
PinballDpadButton(
direction: PinballDpadDirection.left,
onTap: onTapLeft,
),
const Expanded(child: SizedBox()),
PinballDpadButton(
direction: PinballDpadDirection.right,
onTap: onTapRight,
),
],
),
Row(
children: [
const Expanded(child: SizedBox()),
PinballDpadButton(
direction: PinballDpadDirection.down,
onTap: onTapDown,
),
const Expanded(child: SizedBox()),
],
),
],
),
);
}
}

@ -1,5 +1,7 @@
export 'bonus_animation.dart';
export 'game_hud.dart';
export 'mobile_controls.dart';
export 'mobile_dpad.dart';
export 'play_button_overlay.dart';
export 'round_count_display.dart';
export 'score_view.dart';

@ -18,6 +18,18 @@ class KeyboardInputController extends Component with KeyboardHandler {
final Map<LogicalKeyboardKey, KeyHandlerCallback> _keyUp;
final Map<LogicalKeyboardKey, KeyHandlerCallback> _keyDown;
/// Trigger a virtual key up, can be used to simulate a key up event, without
/// having a real physical event happening.
bool onVirtualKeyUp(LogicalKeyboardKey key) {
final handler = _keyUp[key];
if (handler != null) {
return handler();
}
return true;
}
@override
bool onKeyEvent(RawKeyEvent event, Set<LogicalKeyboardKey> keysPressed) {
final isUp = event is RawKeyUpEvent;

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

@ -3,8 +3,6 @@
/// FlutterGen
/// *****************************************************
// ignore_for_file: directives_ordering,unnecessary_import
import 'package:flutter/widgets.dart';
class $AssetsImagesGen {
@ -17,7 +15,14 @@ class $AssetsImagesGen {
class $AssetsImagesButtonGen {
const $AssetsImagesButtonGen();
/// File path: assets/images/button/pinball_button.png
AssetGenImage get dpadDown =>
const AssetGenImage('assets/images/button/dpad_down.png');
AssetGenImage get dpadLeft =>
const AssetGenImage('assets/images/button/dpad_left.png');
AssetGenImage get dpadRight =>
const AssetGenImage('assets/images/button/dpad_right.png');
AssetGenImage get dpadUp =>
const AssetGenImage('assets/images/button/dpad_up.png');
AssetGenImage get pinballButton =>
const AssetGenImage('assets/images/button/pinball_button.png');
}
@ -25,7 +30,6 @@ class $AssetsImagesButtonGen {
class $AssetsImagesDialogGen {
const $AssetsImagesDialogGen();
/// File path: assets/images/dialog/background.png
AssetGenImage get background =>
const AssetGenImage('assets/images/dialog/background.png');
}

@ -3,14 +3,9 @@
/// FlutterGen
/// *****************************************************
// ignore_for_file: directives_ordering,unnecessary_import
class FontFamily {
FontFamily._();
/// Font family: PixeloidMono
static const String pixeloidMono = 'PixeloidMono';
/// Font family: PixeloidSans
static const String pixeloidSans = 'PixeloidSans';
}

@ -0,0 +1,66 @@
import 'package:flutter/material.dart';
import 'package:pinball_ui/gen/gen.dart';
import 'package:pinball_ui/pinball_ui.dart';
/// Enum with all possibile directions of a [PinballDpadButton].
enum PinballDpadDirection {
/// Up
up,
/// Down
down,
/// Left
left,
/// Right
right,
}
extension _PinballDpadDirectionX on PinballDpadDirection {
String toAsset() {
switch (this) {
case PinballDpadDirection.up:
return Assets.images.button.dpadUp.keyName;
case PinballDpadDirection.down:
return Assets.images.button.dpadDown.keyName;
case PinballDpadDirection.left:
return Assets.images.button.dpadLeft.keyName;
case PinballDpadDirection.right:
return Assets.images.button.dpadRight.keyName;
}
}
}
/// {@template pinball_dpad_button}
/// Widget that renders a Dpad button with a given direction.
/// {@endtemplate}
class PinballDpadButton extends StatelessWidget {
/// {@macro pinball_dpad_button}
const PinballDpadButton({
Key? key,
required this.direction,
required this.onTap,
}) : super(key: key);
/// Which [PinballDpadDirection] this button is.
final PinballDpadDirection direction;
/// The function executed when the button is pressed.
final VoidCallback onTap;
@override
Widget build(BuildContext context) {
return Material(
color: PinballColors.transparent,
child: InkWell(
onTap: onTap,
child: Image.asset(
direction.toAsset(),
width: 60,
height: 60,
),
),
);
}
}

@ -1,4 +1,5 @@
export 'animated_ellipsis_text.dart';
export 'crt_background.dart';
export 'pinball_button.dart';
export 'pinball_dpad.dart';
export 'pinball_loading_indicator.dart';

@ -6,7 +6,8 @@ import 'package:flutter/foundation.dart';
class PlatformHelper {
/// {@macro platform_helper}
bool get isMobile {
return defaultTargetPlatform == TargetPlatform.iOS ||
defaultTargetPlatform == TargetPlatform.android;
return true;
//return defaultTargetPlatform == TargetPlatform.iOS ||
// defaultTargetPlatform == TargetPlatform.android;
}
}

Loading…
Cancel
Save