diff --git a/packages/flame/lib/src/camera/camera_component.dart b/packages/flame/lib/src/camera/camera_component.dart index b8c6c165888..a95d4685df0 100644 --- a/packages/flame/lib/src/camera/camera_component.dart +++ b/packages/flame/lib/src/camera/camera_component.dart @@ -284,29 +284,24 @@ class CameraComponent extends Component { } /// Returns true if this camera is able to see the [component]. - /// - /// Will return false if the component does not belong to the [world] this - /// camera is looking at. - /// - /// For components deeply nested in the world, consider use the [HasAncestor] - /// or [ParentIsA] mixin with [World] type to make the world lookup faster. - bool canSee(PositionComponent component) { - if (world == null || !component.isMounted) { - return false; - } - - World? componentWorld; - - // Try to find which world the given component belongs to. - if (component is ParentIsA) { - componentWorld = (component as ParentIsA).parent; - } else if (component is HasAncestor) { - componentWorld = (component as HasAncestor).ancestor; - } else { - componentWorld = component.findParent(); - } - - if (world != componentWorld) { + /// + /// Will always return false if + /// - [world] is null or + /// - [world] is not mounted or + /// - [component] is not mounted or + /// - [componentWorld] is non-null and does not match with [world] + /// + /// If [componentWorld] is null, this method does not take into consideration + /// the world to which the given [component] belongs (if any). This means, in + /// such cases, any component overlapping the [visibleWorldRect] will be + /// reported as visible, even if it is not part of the [world] this camera is + /// currently looking at. This can be changed by passing the the component's + /// world as [componentWorld]. + bool canSee(PositionComponent component, {World? componentWorld}) { + if (world == null || + !world!.isMounted || + !component.isMounted || + (componentWorld != null && componentWorld != world)) { return false; } diff --git a/packages/flame/test/camera/camera_component_test.dart b/packages/flame/test/camera/camera_component_test.dart index 09bfcb6f54d..99834e391c9 100644 --- a/packages/flame/test/camera/camera_component_test.dart +++ b/packages/flame/test/camera/camera_component_test.dart @@ -326,45 +326,48 @@ void main() { expect(camera.canSee(player), true); }); - testWithFlameGame('unmounted component', (game) async { + testWithFlameGame('unmounted world', (game) async { final player = PositionComponent(); - final world = World(); + final world = World(children: [player]); final camera = CameraComponent(world: world); - await game.addAll([camera, world]); + await game.addAll([camera]); await game.ready(); expect(camera.canSee(player), false); - await world.add(player); + await game.add(world); await game.ready(); expect(camera.canSee(player), true); }); - testWithFlameGame('component with parent world', (game) async { - final player = _ParentIsAWorld(); - final world = World(children: [player]); - final camera = CameraComponent(); + testWithFlameGame('unmounted component', (game) async { + final player = PositionComponent(); + final world = World(); + final camera = CameraComponent(world: world); await game.addAll([camera, world]); await game.ready(); expect(camera.canSee(player), false); - camera.world = world; + await world.add(player); + await game.ready(); expect(camera.canSee(player), true); }); - testWithFlameGame('component with ancestor world', (game) async { - final player = _HasAncestorWorld(); - final level = PositionComponent(children: [player]); - final world = World(children: [level]); - final camera = CameraComponent(); + testWithFlameGame('component from another world', (game) async { + final player = PositionComponent(); + final world1 = World(children: [player]); + final world2 = World(); + final camera = CameraComponent(world: world2); - await game.addAll([camera, world]); + await game.addAll([camera, world1, world2]); await game.ready(); - expect(camera.canSee(player), false); - camera.world = world; + // can see when player world is not known. expect(camera.canSee(player), true); + + // can't see when the player world is known. + expect(camera.canSee(player, componentWorld: world1), false); }); }); } @@ -375,7 +378,3 @@ class _SolidBackground extends Component with HasPaint { @override void render(Canvas canvas) => canvas.drawColor(color, BlendMode.src); } - -class _HasAncestorWorld extends PositionComponent with HasAncestor {} - -class _ParentIsAWorld extends PositionComponent with ParentIsA {}