feat: pr suggestions

pull/160/head
Erick Zanardo 4 years ago
parent e9d1819ec0
commit 338b26a50f

@ -1,54 +1,81 @@
import 'dart:async'; import 'dart:async';
import 'package:flame/components.dart'; import 'package:flame/components.dart';
import 'package:flutter/material.dart'; import 'package:flame/game.dart';
import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_components/pinball_components.dart';
/// A [Component] that controls its game camera focus /// Adds helpers methods to Flame's [Camera]
class CameraController extends Component with HasGameRef, KeyboardHandler { extension CameraX on Camera {
/// The camera position for the board /// Instantly apply the point of focus to the [Camera]
@visibleForTesting void snapToFocus(FocusData data) {
static final gamePosition = Vector2(0, -7.8); followVector2(data.position);
zoom = data.zoom;
}
/// Returns a [CameraZoom] that can be added to a [FlameGame]
CameraZoom focusToCameraZoom(FocusData data) {
final zoom = CameraZoom(value: data.zoom);
zoom.completed.then((_) {
moveTo(data.position);
});
return zoom;
}
}
/// The camera position for the pinball panel /// {@template focus_data}
@visibleForTesting /// Model class that defines a focus point of the camera
static final backboardPosition = Vector2(0, -100.8); /// {@endtemplate}
class FocusData {
/// {@template focus_data}
FocusData({
required this.zoom,
required this.position,
});
/// The zoom value for the game mode /// The amount of zoom
@visibleForTesting final double zoom;
late final double gameZoom;
/// The zoom value for the panel mode /// The position of the camera
@visibleForTesting final Vector2 position;
late final double backboardZoom; }
/// A [Component] that controls its game camera focus
class CameraController extends Component with HasGameRef, KeyboardHandler {
/// Holds the data for the game focus point
late final FocusData gameFocus;
/// Holds the data for the backboard focus point
late final FocusData backboardFocus;
@override @override
Future<void> onLoad() async { Future<void> onLoad() async {
await super.onLoad(); await super.onLoad();
gameZoom = gameRef.size.y / 16; final gameZoom = gameRef.size.y / 16;
backboardZoom = gameRef.size.y / 18; final backboardZoom = gameRef.size.y / 18;
gameFocus = FocusData(
zoom: gameZoom,
position: Vector2(0, -7.8),
);
backboardFocus = FocusData(
zoom: backboardZoom,
position: Vector2(0, -100.8),
);
// Game starts with the camera focused on the panel // Game starts with the camera focused on the panel
gameRef.camera gameRef.camera
..speed = 100 ..speed = 100
..followVector2(backboardPosition) ..snapToFocus(backboardFocus);
..zoom = backboardZoom;
} }
/// Move the camera focus to the game board /// Move the camera focus to the game board
Future<void> focusOnGame() async { void focusOnGame() {
final zoom = CameraZoom(value: gameZoom); gameRef.add(gameRef.camera.focusToCameraZoom(gameFocus));
unawaited(gameRef.add(zoom));
await zoom.completed;
gameRef.camera.moveTo(gamePosition);
} }
/// Move the camera focus to the backboard /// Move the camera focus to the backboard
Future<void> focusOnBackboard() async { void focusOnBackboard() {
final zoom = CameraZoom(value: backboardZoom); gameRef.add(gameRef.camera.focusToCameraZoom(backboardFocus));
unawaited(gameRef.add(zoom));
await zoom.completed;
gameRef.camera.moveTo(backboardPosition);
} }
} }

@ -4,7 +4,7 @@ export 'camera_controller.dart';
export 'controlled_ball.dart'; export 'controlled_ball.dart';
export 'controlled_flipper.dart'; export 'controlled_flipper.dart';
export 'flutter_forest.dart'; export 'flutter_forest.dart';
export 'game_controller.dart'; export 'game_flow_controller.dart';
export 'plunger.dart'; export 'plunger.dart';
export 'score_points.dart'; export 'score_points.dart';
export 'sparky_fire_zone.dart'; export 'sparky_fire_zone.dart';

@ -4,7 +4,7 @@ import 'package:pinball/game/game.dart';
import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_components/pinball_components.dart';
/// A [Component] that controls the game over and game restart logic /// A [Component] that controls the game over and game restart logic
class GameController extends Component class GameFlowController extends Component
with BlocComponent<GameBloc, GameState>, HasGameRef { with BlocComponent<GameBloc, GameState>, HasGameRef {
@override @override
bool listenWhen(GameState? previousState, GameState newState) { bool listenWhen(GameState? previousState, GameState newState) {

@ -32,13 +32,13 @@ class PinballGame extends Forge2DGame
final PinballAudio audio; final PinballAudio audio;
late final GameController gameController; late final GameFlowController gameFlowController;
@override @override
Future<void> onLoad() async { Future<void> onLoad() async {
_addContactCallbacks(); _addContactCallbacks();
unawaited(add(gameController = GameController())); unawaited(add(gameFlowController = GameFlowController()));
unawaited(add(CameraController())); unawaited(add(CameraController()));
unawaited(add(Backboard(position: Vector2(0, -88)))); unawaited(add(Backboard(position: Vector2(0, -88))));

@ -20,7 +20,7 @@ class PlayButtonOverlay extends StatelessWidget {
final l10n = context.l10n; final l10n = context.l10n;
return Center( return Center(
child: ElevatedButton( child: ElevatedButton(
onPressed: _game.gameController.start, onPressed: _game.gameFlowController.start,
child: Text(l10n.play), child: Text(l10n.play),
), ),
); );

@ -1,7 +1,5 @@
// ignore_for_file: cascade_invocations // ignore_for_file: cascade_invocations
import 'dart:async';
import 'package:flame/game.dart'; import 'package:flame/game.dart';
import 'package:flame_test/flame_test.dart'; import 'package:flame_test/flame_test.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
@ -25,28 +23,30 @@ void main() {
}); });
test('correctly calculates the zooms', () async { test('correctly calculates the zooms', () async {
expect(controller.gameZoom.toInt(), equals(12)); expect(controller.gameFocus.zoom.toInt(), equals(12));
expect(controller.backboardZoom.toInt(), equals(11)); expect(controller.backboardFocus.zoom.toInt(), equals(11));
}); });
test('correctly sets the initial zoom and position', () async { test('correctly sets the initial zoom and position', () async {
expect(game.camera.zoom, equals(controller.backboardZoom)); expect(game.camera.zoom, equals(controller.backboardFocus.zoom));
expect(game.camera.follow, equals(CameraController.backboardPosition)); expect(game.camera.follow, equals(controller.backboardFocus.position));
}); });
group('focusOnBoard', () { group('focusOnBoard', () {
test('changes the zoom', () async { test('changes the zoom', () async {
unawaited(controller.focusOnGame()); controller.focusOnGame();
await game.ready(); await game.ready();
final zoom = game.firstChild<CameraZoom>(); final zoom = game.firstChild<CameraZoom>();
expect(zoom, isNotNull); expect(zoom, isNotNull);
expect(zoom?.value, equals(controller.gameZoom)); expect(zoom?.value, equals(controller.gameFocus.zoom));
}); });
test('moves the camera after the zoom is completed', () async { test('moves the camera after the zoom is completed', () async {
final future = controller.focusOnGame(); controller.focusOnGame();
await game.ready(); await game.ready();
final cameraZoom = game.firstChild<CameraZoom>()!;
final future = cameraZoom.completed;
game.update(10); game.update(10);
game.update(0); // Ensure that the component was removed game.update(0); // Ensure that the component was removed
@ -59,17 +59,19 @@ void main() {
group('focusOnBackboard', () { group('focusOnBackboard', () {
test('changes the zoom', () async { test('changes the zoom', () async {
unawaited(controller.focusOnBackboard()); controller.focusOnBackboard();
await game.ready(); await game.ready();
final zoom = game.firstChild<CameraZoom>(); final zoom = game.firstChild<CameraZoom>();
expect(zoom, isNotNull); expect(zoom, isNotNull);
expect(zoom?.value, equals(controller.backboardZoom)); expect(zoom?.value, equals(controller.backboardFocus.zoom));
}); });
test('moves the camera after the zoom is completed', () async { test('moves the camera after the zoom is completed', () async {
final future = controller.focusOnBackboard(); controller.focusOnBackboard();
await game.ready(); await game.ready();
final cameraZoom = game.firstChild<CameraZoom>()!;
final future = cameraZoom.completed;
game.update(10); game.update(10);
game.update(0); // Ensure that the component was removed game.update(0); // Ensure that the component was removed

@ -10,8 +10,8 @@ import '../../helpers/helpers.dart';
// TODO(erickzanardo): This will not be needed anymore when // TODO(erickzanardo): This will not be needed anymore when
// this issue is merged: https://github.com/flame-engine/flame/issues/1513 // this issue is merged: https://github.com/flame-engine/flame/issues/1513
class WrappedGameController extends GameController { class WrappedGameFlowController extends GameFlowController {
WrappedGameController(this._gameRef); WrappedGameFlowController(this._gameRef);
final PinballGame _gameRef; final PinballGame _gameRef;
@ -20,7 +20,7 @@ class WrappedGameController extends GameController {
} }
void main() { void main() {
group('GameController', () { group('GameFlowController', () {
group('listenWhen', () { group('listenWhen', () {
test('is true when the game over state has changed', () { test('is true when the game over state has changed', () {
final state = GameState( final state = GameState(
@ -33,7 +33,7 @@ void main() {
final previous = GameState.initial(); final previous = GameState.initial();
expect( expect(
GameController().listenWhen(previous, state), GameFlowController().listenWhen(previous, state),
isTrue, isTrue,
); );
}); });
@ -43,14 +43,14 @@ void main() {
late PinballGame game; late PinballGame game;
late Backboard backboard; late Backboard backboard;
late CameraController cameraController; late CameraController cameraController;
late GameController gameController; late GameFlowController gameFlowController;
late ActiveOverlaysNotifier overlays; late ActiveOverlaysNotifier overlays;
setUp(() { setUp(() {
game = MockPinballGame(); game = MockPinballGame();
backboard = MockBackboard(); backboard = MockBackboard();
cameraController = MockCameraController(); cameraController = MockCameraController();
gameController = WrappedGameController(game); gameFlowController = WrappedGameFlowController(game);
overlays = MockActiveOverlaysNotifier(); overlays = MockActiveOverlaysNotifier();
when(backboard.gameOverMode).thenAnswer((_) async {}); when(backboard.gameOverMode).thenAnswer((_) async {});
@ -68,7 +68,7 @@ void main() {
test( test(
'changes the backboard and camera correctly when it is a game over', 'changes the backboard and camera correctly when it is a game over',
() { () {
gameController.onNewState( gameFlowController.onNewState(
GameState( GameState(
score: 10, score: 10,
balls: 0, balls: 0,
@ -86,7 +86,7 @@ void main() {
test( test(
'changes the backboard and camera correctly when it is not a game over', 'changes the backboard and camera correctly when it is not a game over',
() { () {
gameController.onNewState(GameState.initial()); gameFlowController.onNewState(GameState.initial());
verify(backboard.waitingMode).called(1); verify(backboard.waitingMode).called(1);
verify(cameraController.focusOnGame).called(1); verify(cameraController.focusOnGame).called(1);

@ -7,14 +7,14 @@ import '../../helpers/helpers.dart';
void main() { void main() {
group('PlayButtonOverlay', () { group('PlayButtonOverlay', () {
late PinballGame game; late PinballGame game;
late GameController gameController; late GameFlowController gameFlowController;
setUp(() { setUp(() {
game = MockPinballGame(); game = MockPinballGame();
gameController = MockGameController(); gameFlowController = MockGameFlowController();
when(() => game.gameController).thenReturn(gameController); when(() => game.gameFlowController).thenReturn(gameFlowController);
when(gameController.start).thenAnswer((_) {}); when(gameFlowController.start).thenAnswer((_) {});
}); });
testWidgets('renders correctly', (tester) async { testWidgets('renders correctly', (tester) async {
@ -23,13 +23,13 @@ void main() {
expect(find.text('Play'), findsOneWidget); expect(find.text('Play'), findsOneWidget);
}); });
testWidgets('calls gameController.start when taped', (tester) async { testWidgets('calls gameFlowController.start when taped', (tester) async {
await tester.pumpApp(PlayButtonOverlay(game: game)); await tester.pumpApp(PlayButtonOverlay(game: game));
await tester.tap(find.text('Play')); await tester.tap(find.text('Play'));
await tester.pump(); await tester.pump();
verify(gameController.start).called(1); verify(gameFlowController.start).called(1);
}); });
}); });
} }

@ -85,4 +85,4 @@ class MockCameraController extends Mock implements CameraController {}
class MockActiveOverlaysNotifier extends Mock class MockActiveOverlaysNotifier extends Mock
implements ActiveOverlaysNotifier {} implements ActiveOverlaysNotifier {}
class MockGameController extends Mock implements GameController {} class MockGameFlowController extends Mock implements GameFlowController {}

Loading…
Cancel
Save