From 1085518fe279e674bef9a7b938d59926472511f3 Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Thu, 4 Jan 2024 22:56:07 +0100 Subject: [PATCH] fix: Consider displaced hitboxes in GestureHitboxes mixin (#2957) Previously the point sent in to `containsLocalPoint` for `GestureHitboxes` didn't take the parent transformation into consideration, this is fixed in this PR. --- .../components/mixins/gesture_hitboxes.dart | 8 +++- .../src/components/position_component.dart | 6 ++- .../mixins/gesture_hitboxes_test.dart | 43 +++++++++++++++++++ 3 files changed, 54 insertions(+), 3 deletions(-) diff --git a/packages/flame/lib/src/components/mixins/gesture_hitboxes.dart b/packages/flame/lib/src/components/mixins/gesture_hitboxes.dart index 19cebaf38d9..f7ebc60447d 100644 --- a/packages/flame/lib/src/components/mixins/gesture_hitboxes.dart +++ b/packages/flame/lib/src/components/mixins/gesture_hitboxes.dart @@ -19,8 +19,14 @@ mixin GestureHitboxes on Component { return hitboxes.any((hitbox) => hitbox.containsPoint(point)); } + static final _temporaryPoint = Vector2.zero(); + @override bool containsLocalPoint(Vector2 point) { - return hitboxes.any((hitbox) => hitbox.containsLocalPoint(point)); + return hitboxes.any( + (hitbox) => hitbox.containsLocalPoint( + hitbox.parentToLocal(point, output: _temporaryPoint), + ), + ); } } diff --git a/packages/flame/lib/src/components/position_component.dart b/packages/flame/lib/src/components/position_component.dart index 2237d9ae224..8a8498b53dd 100644 --- a/packages/flame/lib/src/components/position_component.dart +++ b/packages/flame/lib/src/components/position_component.dart @@ -273,10 +273,12 @@ class PositionComponent extends Component } @override - Vector2 parentToLocal(Vector2 point) => transform.globalToLocal(point); + Vector2 parentToLocal(Vector2 point, {Vector2? output}) => + transform.globalToLocal(point, output: output); @override - Vector2 localToParent(Vector2 point) => transform.localToGlobal(point); + Vector2 localToParent(Vector2 point, {Vector2? output}) => + transform.localToGlobal(point, output: output); /// Convert local coordinates of a point [point] inside the component /// into the parent's coordinate space. diff --git a/packages/flame/test/components/mixins/gesture_hitboxes_test.dart b/packages/flame/test/components/mixins/gesture_hitboxes_test.dart index 680b1c137d7..f72fcee032d 100644 --- a/packages/flame/test/components/mixins/gesture_hitboxes_test.dart +++ b/packages/flame/test/components/mixins/gesture_hitboxes_test.dart @@ -47,6 +47,49 @@ void main() { expect(component.containsPoint(point), isTrue); }); + testWithFlameGame('CircleHitbox is displaced within the parent component', + (game) async { + final component = _HitboxComponent(); + component.position.setAll(10); + component.size.setValues(2.0, 2.0); + + final hitbox = CircleHitbox( + position: Vector2(1.0, 1.5), + radius: 0.5, + anchor: Anchor.center, + ); + + component.add(hitbox); + await game.ensureAdd(component); + + final point = component.position + hitbox.position; + expect(component.containsPoint(point), isTrue); + final outsidePoint = component.position + Vector2(1.0, 0.99); + expect(component.containsPoint(outsidePoint), isFalse); + }); + + testWithFlameGame( + 'RectangleHitbox is displaced within the parent component', + (game) async { + final component = _HitboxComponent(); + component.position.setAll(10); + component.size.setValues(2.0, 2.0); + + final hitbox = RectangleHitbox( + position: Vector2(1.0, 1.5), + size: Vector2.all(1.0), + anchor: Anchor.center, + ); + + component.add(hitbox); + await game.ensureAdd(component); + + final point = component.position + hitbox.position; + expect(component.containsPoint(point), isTrue); + final outsidePoint = component.position + Vector2(1.0, 0.99); + expect(component.containsPoint(outsidePoint), isFalse); + }); + testWithFlameGame('get component hitboxes', (game) async { final component = _HitboxComponent(); component.position.setValues(1.0, 1.0);