Skip to content

Commit

Permalink
fix: handle game resizing (flutter#446)
Browse files Browse the repository at this point in the history
* fix: handle game resizing

* Update lib/game/behaviors/camera_focusing_behavior.dart

Co-authored-by: Erick <[email protected]>

Co-authored-by: Erick <[email protected]>
Co-authored-by: Allison Ryan <[email protected]>
  • Loading branch information
3 people authored May 9, 2022
1 parent 5e8ac20 commit 98ac639
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 35 deletions.
87 changes: 52 additions & 35 deletions lib/game/behaviors/camera_focusing_behavior.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:math';

import 'package:flame/components.dart';
import 'package:flame/game.dart';
import 'package:flame_bloc/flame_bloc.dart';
Expand All @@ -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,
});
Expand All @@ -24,59 +26,74 @@ class FocusData {
/// Changes the game focus when the [GameBloc] status changes.
class CameraFocusingBehavior extends Component
with FlameBlocListenable<GameBloc, GameState>, HasGameRef {
late final Map<String, FocusData> _foci;
final Map<GameStatus, _FocusData> _foci = {};

GameStatus? _activeFocus;

final _previousSize = Vector2.zero();

@override
bool listenWhen(GameState? previousState, GameState newState) {
return previousState?.status != newState.status;
}

@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<void> 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<void> 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);
}
Expand Down
14 changes: 14 additions & 0 deletions test/game/behaviors/camera_focusing_behavior_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,20 @@ void main() {
},
);

flameTester.test('sets zoom on resize', (game) async {
final behavior = CameraFocusingBehavior();

await game.ensureAdd(
FlameBlocProvider<GameBloc, GameState>.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 {
Expand Down

0 comments on commit 98ac639

Please sign in to comment.