diff --git a/examples/lib/stories/camera_and_viewport/fixed_resolution_example.dart b/examples/lib/stories/camera_and_viewport/fixed_resolution_example.dart index bd1ee5b2782..276a28405ca 100644 --- a/examples/lib/stories/camera_and_viewport/fixed_resolution_example.dart +++ b/examples/lib/stories/camera_and_viewport/fixed_resolution_example.dart @@ -6,23 +6,33 @@ import 'package:flame/palette.dart'; import 'package:flame/text.dart'; import 'package:flutter/material.dart'; -class FixedResolutionExample extends FlameGame { +class FixedResolutionExample extends FlameGame with ScrollCallbacks { static const description = ''' This example shows how to create a viewport with a fixed resolution. It is useful when you want the visible part of the game to be the same on all devices no matter the actual screen size of the device. Resize the window or change device orientation to see the difference. - + If you tap once you will set the zoom to 2 and if you tap again it goes back - to 1, so that you can test how it works with a zoom level. + to 1, so that you can test how it works with a zoom level. Scroll to zoom + freely in between. '''; + static const zoomPerScrollUnit = 0.05; + FixedResolutionExample() : super( camera: CameraComponent.withFixedResolution(width: 600, height: 1024), world: FixedResolutionWorld(), ); + @override + void onScroll(ScrollEvent event) { + final zoom = + camera.viewfinder.zoom + event.scrollDelta.y.sign * zoomPerScrollUnit; + camera.viewfinder.zoom = zoom.clamp(0.25, 4.0); + } + @override Future onLoad() async { final textRenderer = TextPaint( diff --git a/examples/lib/stories/camera_and_viewport/static_components_example.dart b/examples/lib/stories/camera_and_viewport/static_components_example.dart index e83bee60361..f44f7c6da76 100644 --- a/examples/lib/stories/camera_and_viewport/static_components_example.dart +++ b/examples/lib/stories/camera_and_viewport/static_components_example.dart @@ -7,14 +7,19 @@ import 'package:flame/extensions.dart'; import 'package:flame/game.dart'; import 'package:flame/parallax.dart'; -class StaticComponentsExample extends FlameGame { +class StaticComponentsExample extends FlameGame with ScrollCallbacks { static const description = ''' This example shows a parallax which is attached to the viewport (behind the world), four Flame logos that are added to the world, and a player added to the world which is also followed by the camera when you click somewhere. The text components that are added are self-explanatory. + + Scroll to zoom: the world components scale with the camera, while the + viewport and backdrop components stay exactly where they are. '''; + static const zoomPerScrollUnit = 0.05; + late final ParallaxComponent myParallax; StaticComponentsExample({ @@ -27,6 +32,13 @@ class StaticComponentsExample extends FlameGame { world: _StaticComponentWorld(), ); + @override + void onScroll(ScrollEvent event) { + final zoom = + camera.viewfinder.zoom + event.scrollDelta.y.sign * zoomPerScrollUnit; + camera.viewfinder.zoom = zoom.clamp(0.25, 4.0); + } + @override Future onLoad() async { myParallax = MyParallaxComponent()..parallax?.baseVelocity.setZero(); diff --git a/packages/flame/test/events/component_mixins/scroll_callbacks_test.dart b/packages/flame/test/events/component_mixins/scroll_callbacks_test.dart index 15c6fd1f051..23f3b3d7411 100644 --- a/packages/flame/test/events/component_mixins/scroll_callbacks_test.dart +++ b/packages/flame/test/events/component_mixins/scroll_callbacks_test.dart @@ -2,6 +2,7 @@ import 'package:flame/components.dart'; import 'package:flame/events.dart'; import 'package:flame/game.dart'; import 'package:flame_test/flame_test.dart'; +import 'package:flutter/gestures.dart' show PointerDeviceKind; import 'package:flutter_test/flutter_test.dart'; void main() { @@ -76,6 +77,25 @@ void main() { }, ); + testWidgets( + 'scroll events reach the game through the widget tree', + (tester) async { + final game = _ScrollCallbacksGame(); + await tester.pumpWidget(GameWidget(game: game)); + await tester.pump(); + await tester.pump(); + + final testPointer = TestPointer(1, PointerDeviceKind.mouse); + testPointer.hover(const Offset(10, 10)); + await tester.sendEventToBinding( + testPointer.scroll(const Offset(0, -300)), + ); + + expect(game.receivedScrolls, hasLength(1)); + expect(game.receivedScrolls.last.scrollDelta, Vector2(0, -300)); + }, + ); + testWithFlameGame( 'scroll events have correct raw event', (game) async {