diff --git a/packages/flame/lib/src/collisions/hitboxes/circle_hitbox.dart b/packages/flame/lib/src/collisions/hitboxes/circle_hitbox.dart index 1e7d2021fc4..5c6205e92e9 100644 --- a/packages/flame/lib/src/collisions/hitboxes/circle_hitbox.dart +++ b/packages/flame/lib/src/collisions/hitboxes/circle_hitbox.dart @@ -28,8 +28,11 @@ class CircleHitbox extends CircleComponent with ShapeHitbox { required super.parentSize, super.angle, super.anchor, + bool isSolid = false, }) : shouldFillParent = false, - super.relative(); + super.relative() { + this.isSolid = isSolid; + } @override void fillParent() { diff --git a/packages/flame/lib/src/collisions/hitboxes/polygon_hitbox.dart b/packages/flame/lib/src/collisions/hitboxes/polygon_hitbox.dart index fc02c27a29e..4c4b4666d70 100644 --- a/packages/flame/lib/src/collisions/hitboxes/polygon_hitbox.dart +++ b/packages/flame/lib/src/collisions/hitboxes/polygon_hitbox.dart @@ -8,6 +8,7 @@ class PolygonHitbox extends PolygonComponent with ShapeHitbox, PolygonRayIntersection { PolygonHitbox( super.vertices, { + super.position, super.angle, super.anchor, bool isSolid = false, @@ -28,9 +29,12 @@ class PolygonHitbox extends PolygonComponent required super.parentSize, double super.angle = 0, super.anchor, + bool isSolid = false, }) : super.relative( shrinkToBounds: true, - ); + ) { + this.isSolid = isSolid; + } @override void fillParent() { diff --git a/packages/flame/lib/src/collisions/hitboxes/rectangle_hitbox.dart b/packages/flame/lib/src/collisions/hitboxes/rectangle_hitbox.dart index 49b05376972..142f2e3548d 100644 --- a/packages/flame/lib/src/collisions/hitboxes/rectangle_hitbox.dart +++ b/packages/flame/lib/src/collisions/hitboxes/rectangle_hitbox.dart @@ -31,10 +31,13 @@ class RectangleHitbox extends RectangleComponent required super.parentSize, super.angle, super.anchor, + bool isSolid = false, }) : shouldFillParent = false, super.relative( shrinkToBounds: true, - ); + ) { + this.isSolid = isSolid; + } @override void fillParent() { diff --git a/packages/flame/lib/src/geometry/polygon_component.dart b/packages/flame/lib/src/geometry/polygon_component.dart index 4afb99ed439..7b2b72f33d3 100644 --- a/packages/flame/lib/src/geometry/polygon_component.dart +++ b/packages/flame/lib/src/geometry/polygon_component.dart @@ -106,8 +106,7 @@ class PolygonComponent extends ShapeComponent { // Used to not create new Vector2 objects when calculating the top left of the // bounds of the polygon. - @internal - final topLeft = Vector2.zero(); + final _topLeft = Vector2.zero(); @protected void refreshVertices({required List newVertices}) { @@ -115,24 +114,24 @@ class PolygonComponent extends ShapeComponent { newVertices.length == _vertices.length, 'A polygon can not change their number of vertices', ); - topLeft.setFrom(newVertices[0]); + _topLeft.setFrom(newVertices[0]); newVertices.forEachIndexed((i, _) { final newVertex = newVertices[i]; _vertices[i].setFrom(newVertex); - topLeft.x = min(topLeft.x, newVertex.x); - topLeft.y = min(topLeft.y, newVertex.y); + _topLeft.x = min(_topLeft.x, newVertex.x); + _topLeft.y = min(_topLeft.y, newVertex.y); }); _path ..reset() ..addPolygon( - vertices.map((p) => (p - topLeft).toOffset()).toList(growable: false), + vertices.map((p) => (p - _topLeft).toOffset()).toList(growable: false), true, ); if (shrinkToBounds) { final bounds = _path.getBounds(); size.setValues(bounds.width, bounds.height); if (!manuallyPositioned) { - position = Anchor.topLeft.toOtherAnchorPosition(topLeft, anchor, size); + position = Anchor.topLeft.toOtherAnchorPosition(_topLeft, anchor, size); } } } @@ -151,7 +150,7 @@ class PolygonComponent extends ShapeComponent { vertices.forEachIndexed((i, vertex) { _globalVertices[i] ..setFrom(vertex) - ..sub(topLeft) + ..sub(_topLeft) ..multiply(scale) ..add(position) ..rotate(angle, center: position); @@ -213,8 +212,8 @@ class PolygonComponent extends ShapeComponent { for (var i = 0; i < _vertices.length; i++) { final edge = getEdge(i, vertices: vertices); final isOutside = (edge.to.x - edge.from.x) * - (point.y - edge.from.y + topLeft.y) - - (point.x - edge.from.x + topLeft.x) * (edge.to.y - edge.from.y) > + (point.y - edge.from.y + _topLeft.y) - + (point.x - edge.from.x + _topLeft.x) * (edge.to.y - edge.from.y) > 0; if (isOutside) { return false; diff --git a/packages/flame/test/components/position_component_test.dart b/packages/flame/test/components/position_component_test.dart index 51d67d14c29..4c7ab4c55d4 100644 --- a/packages/flame/test/components/position_component_test.dart +++ b/packages/flame/test/components/position_component_test.dart @@ -162,6 +162,54 @@ void main() { expect(component.containsPoint(point), true); }); + testWithFlameGame('component with hitbox with position contains point', + (game) async { + final component = _MyHitboxComponent(); + component.position.setValues(1.0, 1.0); + component.anchor = Anchor.topLeft; + component.size.setValues(2.0, 2.0); + final hitbox = PolygonHitbox( + [ + Vector2(1, 0), + Vector2(0, -1), + Vector2(-1, 0), + Vector2(0, 1), + ], + position: Vector2(5, 6), + ); + component.add(hitbox); + await game.ensureAdd(component); + + final point = + component.position + (component.size / 4) + hitbox.position; + expect(component.containsPoint(point), true); + }); + + testWithFlameGame('component with hitbox with position just misses point', + (game) async { + final component = _MyHitboxComponent(); + component.position.setValues(1.0, 1.0); + component.anchor = Anchor.topLeft; + component.size.setValues(2.0, 2.0); + final hitbox = PolygonHitbox( + [ + Vector2(1, 0), + Vector2(0, -1), + Vector2(-1, 0), + Vector2(0, 1), + ], + position: Vector2(5, 6), + ); + component.add(hitbox); + await game.ensureAdd(component); + + final point = component.position + + (component.size / 4) - + Vector2(0.01, 0) + + hitbox.position; + expect(component.containsPoint(point), false); + }); + testWithFlameGame( 'component with anchor topLeft contains point on edge', (game) async {