Skip to content

Commit

Permalink
fix: Vertices in PolygonComponent should subtract vertices position…
Browse files Browse the repository at this point in the history
…ing (#3040)

If the vertices in the `PolygonComponent` weren't starting at 0,0 they
got the wrong hitbox, but rendered correctly.
This PR fixes that.

Closes: #3031
  • Loading branch information
spydon committed Feb 16, 2024
1 parent 330862c commit 4f053ed
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 22 deletions.
37 changes: 16 additions & 21 deletions packages/flame/lib/src/geometry/polygon_component.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ class PolygonComponent extends ShapeComponent {
/// With this constructor you create your [PolygonComponent] from positions in
/// anywhere in the 2d-space. It will automatically calculate the [size] of
/// the Polygon (the bounding box) if no size it given.
/// NOTE: Always define your polygon in a counter-clockwise fashion (in the
/// screen coordinate system).
PolygonComponent(
this._vertices, {
super.position,
Expand Down Expand Up @@ -110,10 +108,6 @@ class PolygonComponent extends ShapeComponent {
.toList(growable: false);
}

// Used to not create new Vector2 objects when calculating the top left of the
// bounds of the polygon.
final _topLeft = Vector2.zero();

@protected
void refreshVertices({
required List<Vector2> newVertices,
Expand All @@ -128,24 +122,29 @@ class PolygonComponent extends ShapeComponent {
if (_isClockwise(newVertices)) {
newVertices.reverse();
}
_topLeft.setFrom(newVertices[0]);
newVertices.forEachIndexed((i, _) {
final topLeft = Vector2.zero();
topLeft.setFrom(newVertices[0]);
for (var i = 0; i < newVertices.length; 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);
}
for (var i = 0; i < newVertices.length; i++) {
final newVertex = newVertices[i];
_vertices[i].setFrom(newVertex - topLeft);
}
_path
..reset()
..addPolygon(
vertices.map((p) => (p - _topLeft).toOffset()).toList(growable: false),
_vertices.map((p) => p.toOffset()).toList(growable: false),
true,
);
if (shrinkToBoundsOverride ?? 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);
}
}
}
Expand All @@ -161,14 +160,14 @@ class PolygonComponent extends ShapeComponent {
scale,
angle,
])) {
vertices.forEachIndexed((i, vertex) {
for (var i = 0; i < _vertices.length; i++) {
final vertex = _vertices[i];
_globalVertices[i]
..setFrom(vertex)
..sub(_topLeft)
..multiply(scale)
..add(position)
..rotate(angle, center: position);
});
}
if (scale.y.isNegative || scale.x.isNegative) {
// Since the list will be clockwise we have to reverse it for it to
// become counterclockwise.
Expand Down Expand Up @@ -255,11 +254,7 @@ class PolygonComponent extends ShapeComponent {

@override
bool containsLocalPoint(Vector2 point) {
// Take anchor into consideration.
final localPoint =
anchor.toOtherAnchorPosition(point, Anchor.topLeft, size);

return _containsPoint(localPoint, _vertices);
return _containsPoint(point, _vertices);
}

/// Return all vertices as [LineSegment]s that intersect [rect], if [rect]
Expand Down
28 changes: 27 additions & 1 deletion packages/flame/test/components/shape_component_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,34 @@ void main() {
Vector2(1.5, 0.5),
],
);
expect(polygon.containsLocalPoint(Vector2(0.25, 0.25)), isFalse);
expect(polygon.containsLocalPoint(Vector2(0.0, 0.0)), isTrue);
expect(polygon.containsLocalPoint(Vector2(0.25, 0.25)), isTrue);
expect(polygon.containsLocalPoint(Vector2(0.75, 0.75)), isTrue);
expect(polygon.containsLocalPoint(Vector2(1.0, 1.0)), isTrue);
expect(polygon.containsLocalPoint(Vector2(1.0, 0.0)), isTrue);
expect(polygon.containsLocalPoint(Vector2(0.0, 1.0)), isTrue);
expect(polygon.containsLocalPoint(Vector2(0.0, 1.0001)), isFalse);
expect(polygon.containsLocalPoint(Vector2(-0.0001, 0.0)), isFalse);
});

test('polygon contains point in local with anchor', () {
final polygon = PolygonComponent(
[
Vector2(0.5, 0.5),
Vector2(0.5, 1.5),
Vector2(1.5, 1.5),
Vector2(1.5, 0.5),
],
anchor: Anchor.center,
);
expect(polygon.containsLocalPoint(Vector2(0.0, 0.0)), isTrue);
expect(polygon.containsLocalPoint(Vector2(0.25, 0.25)), isTrue);
expect(polygon.containsLocalPoint(Vector2(0.75, 0.75)), isTrue);
expect(polygon.containsLocalPoint(Vector2(1.0, 1.0)), isTrue);
expect(polygon.containsLocalPoint(Vector2(1.0, 0.0)), isTrue);
expect(polygon.containsLocalPoint(Vector2(0.0, 1.0)), isTrue);
expect(polygon.containsLocalPoint(Vector2(0.0, 1.0001)), isFalse);
expect(polygon.containsLocalPoint(Vector2(-0.0001, 0.0)), isFalse);
});

test('rectangle contains point in local with anchor', () {
Expand Down

0 comments on commit 4f053ed

Please sign in to comment.