From bd130b711b5cb486b8f05225711c6e6c3fe574e6 Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Thu, 21 Dec 2023 17:42:07 +0100 Subject: [PATCH] fix: The `visibleGameSize` should be based on `viewport.virtualSize` (#2945) The `visibleGameSize` should be based on the virtual size of the viewport, otherwise it won't work for `FixedResolutionViewport` for example. We noticed this when using the `ScreenHitbox` in a world that was looked upon by a camera with a `FixedResolutionViewport`. --- .../collision_detection/circles_example.dart | 34 +++++++++--------- packages/flame/lib/src/camera/viewfinder.dart | 2 +- .../test/collisions/screen_hibox_test.dart | 36 +++++++++++++++++++ 3 files changed, 54 insertions(+), 18 deletions(-) diff --git a/examples/lib/stories/collision_detection/circles_example.dart b/examples/lib/stories/collision_detection/circles_example.dart index f3e8b7de1..4dc288465 100644 --- a/examples/lib/stories/collision_detection/circles_example.dart +++ b/examples/lib/stories/collision_detection/circles_example.dart @@ -2,41 +2,41 @@ import 'package:flame/collisions.dart'; import 'package:flame/components.dart'; import 'package:flame/events.dart'; import 'package:flame/game.dart'; -import 'package:flame/input.dart'; import 'package:flutter/material.dart' hide Image, Draggable; -class CirclesExample extends FlameGame with HasCollisionDetection, TapDetector { +class CirclesExample extends FlameGame { static const description = ''' This example will create a circle every time you tap on the screen. It will have the initial velocity towards the center of the screen and if it touches another circle both of them will change color. '''; - @override - Future onLoad() async { - add(ScreenHitbox()); - } + CirclesExample() + : super( + camera: CameraComponent.withFixedResolution(width: 600, height: 400), + world: MyWorld(), + ); +} + +class MyWorld extends World with TapCallbacks, HasCollisionDetection { + MyWorld() : super(children: [ScreenHitbox()..debugMode = true]); @override - void onTapDown(TapDownInfo info) { - add(MyCollidable(info.eventPosition.widget)); + void onTapDown(TapDownEvent info) { + add(MyCollidable(position: info.localPosition)); } } class MyCollidable extends PositionComponent with HasGameReference, CollisionCallbacks { + MyCollidable({super.position}) + : super(size: Vector2.all(30), anchor: Anchor.center); + late Vector2 velocity; final _collisionColor = Colors.amber; final _defaultColor = Colors.cyan; late ShapeHitbox hitbox; - MyCollidable(Vector2 position) - : super( - position: position, - size: Vector2.all(100), - anchor: Anchor.center, - ); - @override Future onLoad() async { final defaultPaint = Paint() @@ -46,8 +46,8 @@ class MyCollidable extends PositionComponent ..paint = defaultPaint ..renderShape = true; add(hitbox); - final center = game.size / 2; - velocity = (center - position)..scaleTo(150); + velocity = -position + ..scaleTo(50); } @override diff --git a/packages/flame/lib/src/camera/viewfinder.dart b/packages/flame/lib/src/camera/viewfinder.dart index 33563c73a..59279bd3c 100644 --- a/packages/flame/lib/src/camera/viewfinder.dart +++ b/packages/flame/lib/src/camera/viewfinder.dart @@ -152,7 +152,7 @@ class Viewfinder extends Component Rect? visibleRect; @protected Rect computeVisibleRect() { - final viewportSize = camera.viewport.size; + final viewportSize = camera.viewport.virtualSize; final currentTransform = transform; currentTransform.globalToLocal(_zeroVector, output: _topLeft); currentTransform.globalToLocal(viewportSize, output: _bottomRight); diff --git a/packages/flame/test/collisions/screen_hibox_test.dart b/packages/flame/test/collisions/screen_hibox_test.dart index 345b8129a..1804bfaf9 100644 --- a/packages/flame/test/collisions/screen_hibox_test.dart +++ b/packages/flame/test/collisions/screen_hibox_test.dart @@ -115,5 +115,41 @@ void main() { expect(testBlock.endCounter, 0); }, }); + + runCollisionTestRegistry({ + 'collides with FixedResolutionViewport': (hasCollisionDetection) async { + final game = hasCollisionDetection as FlameGame; + game.camera = CameraComponent.withFixedResolution( + width: 100, + height: 100, + ); + final testBlock = TestBlock( + Vector2.all(-50), + Vector2.all(2), + )..anchor = Anchor.center; + final screenHitbox = ScreenHitbox(); + await game.world.addAll([screenHitbox, testBlock]); + await game.ready(); + game.update(0); + + expect(testBlock.startCounter, 1); + expect(testBlock.onCollisionCounter, 1); + expect(testBlock.endCounter, 0); + + testBlock.position = Vector2.all(50); + game.update(0); + + expect(testBlock.startCounter, 1); + expect(testBlock.onCollisionCounter, 2); + expect(testBlock.endCounter, 0); + + testBlock.position = Vector2.all(0); + game.update(0); + + expect(testBlock.startCounter, 1); + expect(testBlock.onCollisionCounter, 2); + expect(testBlock.endCounter, 1); + }, + }); }); }