mirror of https://github.com/flutter/pinball.git
feat: adding camera zoom effect (#153)
* feat: adding camera zoom effect * testing ci * testing ci * Apply suggestions from code review Co-authored-by: Allison Ryan <77211884+allisonryan0002@users.noreply.github.com> * testing ci * testing ci * ci * feat: pr suggestion * fix: lint * fix: lint * Apply suggestions from code review Co-authored-by: Alejandro Santiago <dev@alestiago.com> Co-authored-by: Allison Ryan <77211884+allisonryan0002@users.noreply.github.com> Co-authored-by: Alejandro Santiago <dev@alestiago.com>pull/162/head
parent
2f40dcc971
commit
daebb0b749
@ -0,0 +1,56 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flame/components.dart';
|
||||
import 'package:flame/effects.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// {@template camera_zoom}
|
||||
/// Applies zoom to the camera of the game where this is added to
|
||||
/// {@endtemplate}
|
||||
class CameraZoom extends Effect with HasGameRef {
|
||||
/// {@macro camera_zoom}
|
||||
CameraZoom({
|
||||
required this.value,
|
||||
}) : super(
|
||||
EffectController(
|
||||
duration: 0.4,
|
||||
curve: Curves.easeOut,
|
||||
),
|
||||
);
|
||||
|
||||
/// The total zoom value to be applied to the camera
|
||||
final double value;
|
||||
|
||||
late final Tween<double> _tween;
|
||||
|
||||
final Completer<void> _completer = Completer();
|
||||
|
||||
@override
|
||||
Future<void> onLoad() async {
|
||||
_tween = Tween(
|
||||
begin: gameRef.camera.zoom,
|
||||
end: value,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void apply(double progress) {
|
||||
gameRef.camera.zoom = _tween.transform(progress);
|
||||
}
|
||||
|
||||
/// Returns a [Future] that completes once the zoom is finished
|
||||
Future<void> get completed {
|
||||
if (controller.completed) {
|
||||
return Future.value();
|
||||
}
|
||||
|
||||
return _completer.future;
|
||||
}
|
||||
|
||||
@override
|
||||
void onRemove() {
|
||||
_completer.complete();
|
||||
|
||||
super.onRemove();
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
import 'package:flame/components.dart';
|
||||
import 'package:flame/input.dart';
|
||||
import 'package:pinball_components/pinball_components.dart';
|
||||
import 'package:sandbox/common/common.dart';
|
||||
|
||||
class BasicCameraZoomGame extends BasicGame with TapDetector {
|
||||
static const info = '''
|
||||
Simple game to demonstrate how the CameraZoom can be used.
|
||||
Tap to zoom in/out
|
||||
''';
|
||||
|
||||
bool zoomApplied = false;
|
||||
|
||||
@override
|
||||
Future<void> onLoad() async {
|
||||
final sprite = await loadSprite(Assets.images.flutterSignPost.keyName);
|
||||
|
||||
await add(
|
||||
SpriteComponent(
|
||||
sprite: sprite,
|
||||
size: Vector2(4, 8),
|
||||
anchor: Anchor.center,
|
||||
),
|
||||
);
|
||||
|
||||
camera.followVector2(Vector2.zero());
|
||||
}
|
||||
|
||||
@override
|
||||
void onTap() {
|
||||
if (firstChild<CameraZoom>() == null) {
|
||||
final zoom = CameraZoom(value: zoomApplied ? 30 : 10);
|
||||
add(zoom);
|
||||
zoomApplied = !zoomApplied;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
import 'package:dashbook/dashbook.dart';
|
||||
import 'package:flame/game.dart';
|
||||
import 'package:sandbox/common/common.dart';
|
||||
import 'package:sandbox/stories/zoom/basic_zoom_game.dart';
|
||||
|
||||
void addZoomStories(Dashbook dashbook) {
|
||||
dashbook.storiesOf('CameraZoom').add(
|
||||
'Basic',
|
||||
(context) => GameWidget(
|
||||
game: BasicCameraZoomGame(),
|
||||
),
|
||||
codeLink: buildSourceLink('zoom/basic_zoom_game.dart'),
|
||||
info: BasicCameraZoomGame.info,
|
||||
);
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
// ignore_for_file: cascade_invocations
|
||||
|
||||
import 'package:flame/components.dart';
|
||||
import 'package:flame_test/flame_test.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:pinball_components/pinball_components.dart';
|
||||
|
||||
import '../../helpers/helpers.dart';
|
||||
|
||||
void main() {
|
||||
group('CameraZoom', () {
|
||||
final tester = FlameTester(TestGame.new);
|
||||
|
||||
tester.testGameWidget(
|
||||
'renders correctly',
|
||||
setUp: (game, tester) async {
|
||||
game.camera.followVector2(Vector2.zero());
|
||||
game.camera.zoom = 10;
|
||||
final sprite = await game.loadSprite(
|
||||
Assets.images.flutterSignPost.keyName,
|
||||
);
|
||||
|
||||
await game.add(
|
||||
SpriteComponent(
|
||||
sprite: sprite,
|
||||
size: Vector2(4, 8),
|
||||
anchor: Anchor.center,
|
||||
),
|
||||
);
|
||||
|
||||
await game.add(CameraZoom(value: 40));
|
||||
},
|
||||
verify: (game, tester) async {
|
||||
await expectLater(
|
||||
find.byGame<TestGame>(),
|
||||
matchesGoldenFile('golden/camera_zoom/no_zoom.png'),
|
||||
);
|
||||
|
||||
game.update(0.2);
|
||||
await tester.pump();
|
||||
await expectLater(
|
||||
find.byGame<TestGame>(),
|
||||
matchesGoldenFile('golden/camera_zoom/in_between.png'),
|
||||
);
|
||||
|
||||
game.update(0.4);
|
||||
await tester.pump();
|
||||
await expectLater(
|
||||
find.byGame<TestGame>(),
|
||||
matchesGoldenFile('golden/camera_zoom/finished.png'),
|
||||
);
|
||||
game.update(0.1);
|
||||
await tester.pump();
|
||||
|
||||
expect(game.firstChild<CameraZoom>(), isNull);
|
||||
},
|
||||
);
|
||||
|
||||
tester.test(
|
||||
'completes when checked after it is finished',
|
||||
(game) async {
|
||||
await game.add(CameraZoom(value: 40));
|
||||
game.update(10);
|
||||
final cameraZoom = game.firstChild<CameraZoom>();
|
||||
final future = cameraZoom!.completed;
|
||||
|
||||
expect(future, completes);
|
||||
},
|
||||
);
|
||||
|
||||
tester.test(
|
||||
'completes when checked before it is finished',
|
||||
(game) async {
|
||||
final zoom = CameraZoom(value: 40);
|
||||
final future = zoom.completed;
|
||||
|
||||
await game.add(zoom);
|
||||
game.update(10);
|
||||
game.update(0);
|
||||
|
||||
expect(future, completes);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 31 KiB |
Loading…
Reference in new issue