From 3461d6119e1b243d3e83795f9c6d13e4421a6153 Mon Sep 17 00:00:00 2001 From: Jochum van der Ploeg Date: Mon, 9 May 2022 22:27:25 +0200 Subject: [PATCH] fix: handle game resizing --- .../behaviors/camera_focusing_behavior.dart | 87 +++++++++++-------- .../camera_focusing_behavior_test.dart | 14 +++ 2 files changed, 66 insertions(+), 35 deletions(-) diff --git a/lib/game/behaviors/camera_focusing_behavior.dart b/lib/game/behaviors/camera_focusing_behavior.dart index 8a13821d..4ad1e2fc 100644 --- a/lib/game/behaviors/camera_focusing_behavior.dart +++ b/lib/game/behaviors/camera_focusing_behavior.dart @@ -1,3 +1,5 @@ +import 'dart:math'; + import 'package:flame/components.dart'; import 'package:flame/game.dart'; import 'package:flame_bloc/flame_bloc.dart'; @@ -7,9 +9,9 @@ import 'package:pinball_components/pinball_components.dart'; /// {@template focus_data} /// Defines a [Camera] focus point. /// {@endtemplate} -class FocusData { - /// {@template focus_data} - FocusData({ +class _FocusData { + /// {@macro focus_data} + const _FocusData({ required this.zoom, required this.position, }); @@ -24,7 +26,11 @@ class FocusData { /// Changes the game focus when the [GameBloc] status changes. class CameraFocusingBehavior extends Component with FlameBlocListenable, HasGameRef { - late final Map _foci; + final Map _foci = {}; + + GameStatus? _activeFocus; + + final Vector2 _previousSize = Vector2.zero(); @override bool listenWhen(GameState? previousState, GameState newState) { @@ -32,51 +38,62 @@ class CameraFocusingBehavior extends Component } @override - void onNewState(GameState state) { - switch (state.status) { - case GameStatus.waiting: - break; - case GameStatus.playing: - _zoom(_foci['game']!); - break; - case GameStatus.gameOver: - _zoom(_foci['backbox']!); - break; - } - } + void onNewState(GameState state) => _zoomTo(state.status); @override - Future onLoad() async { - await super.onLoad(); - _foci = { - 'game': FocusData( - zoom: gameRef.size.y / 16, - position: Vector2(0, -7.8), - ), - 'waiting': FocusData( - zoom: gameRef.size.y / 18, + void onGameResize(Vector2 size) { + super.onGameResize(size); + if (size == _previousSize) { + return; + } + _previousSize.setFrom(size); + + final maxWidth = size.x / 90; + final maxHeight = size.y / 160; + + final scale = min(maxHeight, maxWidth); + + _foci.addAll({ + GameStatus.waiting: _FocusData( + zoom: scale + (maxWidth > maxHeight ? 0.3 : -0.5), position: Vector2(0, -112), ), - 'backbox': FocusData( - zoom: gameRef.size.y / 10, + GameStatus.playing: _FocusData( + zoom: scale + (maxWidth > maxHeight ? 0.5 : -0.2), + position: Vector2(0, -7.8), + ), + GameStatus.gameOver: _FocusData( + zoom: scale + (maxWidth > maxHeight ? 2.8 : 3.3), position: Vector2(0, -111), ), - }; + }); + + if (_activeFocus != null) { + _snap(_activeFocus!); + } + } - _snap(_foci['waiting']!); + @override + Future onLoad() async { + await super.onLoad(); + _snap(GameStatus.waiting); } - void _snap(FocusData data) { + void _snap(GameStatus focusKey) { + final focusData = _foci[_activeFocus = focusKey]!; + gameRef.camera ..speed = 100 - ..followVector2(data.position) - ..zoom = data.zoom; + ..followVector2(focusData.position) + ..zoom = focusData.zoom; } - void _zoom(FocusData data) { - final zoom = CameraZoom(value: data.zoom); + void _zoomTo(GameStatus focusKey) { + final focusData = _foci[_activeFocus = focusKey]!; + + final zoom = CameraZoom(value: focusData.zoom); zoom.completed.then((_) { - gameRef.camera.moveTo(data.position); + gameRef.camera.moveTo(focusData.position); }); add(zoom); } diff --git a/test/game/behaviors/camera_focusing_behavior_test.dart b/test/game/behaviors/camera_focusing_behavior_test.dart index a856b392..092f3efe 100644 --- a/test/game/behaviors/camera_focusing_behavior_test.dart +++ b/test/game/behaviors/camera_focusing_behavior_test.dart @@ -53,6 +53,20 @@ void main() { }, ); + flameTester.test('sets zoom on resize', (game) async { + final behavior = CameraFocusingBehavior(); + + await game.ensureAdd( + FlameBlocProvider.value( + value: GameBloc(), + children: [behavior], + ), + ); + + game.onGameResize(game.canvasSize * 2); + expect(game.camera.zoom, equals(6.55)); + }); + flameTester.test( 'listenWhen only listens when status changes', (game) async {