Skip to content

Commit

Permalink
fix: PolygonComponent.containsLocalPoint to use anchor (#2953)
Browse files Browse the repository at this point in the history
Apparently `PolygonComponent.containsLocalPoint` has to take the anchor
into consideration, I have no idea how nobody noticed this before...
  • Loading branch information
spydon committed Jan 4, 2024
1 parent 4f58329 commit 7969321
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 20 deletions.
28 changes: 14 additions & 14 deletions packages/flame/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,28 @@ import 'package:flame/game.dart';
import 'package:flame/palette.dart';
import 'package:flutter/material.dart';

/// This example simply adds a rotating white square on the screen.
/// If you press on a square, it will be removed.
/// If you press anywhere else, another square will be added.
void main() {
runApp(
GameWidget(
game: MyGame(),
game: FlameGame(world: MyWorld()),
),
);
}

/// This example simply adds a rotating white square on the screen.
/// If you press on a square, it will be removed.
/// If you press anywhere else, another square will be added.
class MyGame extends FlameGame with TapCallbacks {
class MyWorld extends World with TapCallbacks {
@override
Future<void> onLoad() async {
add(Square(size / 2));
add(Square(Vector2.zero()));
}

@override
void onTapDown(TapDownEvent event) {
super.onTapDown(event);
if (!event.handled) {
final touchPoint = event.canvasPosition;
final touchPoint = event.localPosition;
add(Square(touchPoint));
}
}
Expand All @@ -48,13 +48,6 @@ class Square extends RectangleComponent with TapCallbacks {
anchor: Anchor.center,
);

@override
void update(double dt) {
super.update(dt);
angle += speed * dt;
angle %= 2 * math.pi;
}

@override
Future<void> onLoad() async {
super.onLoad();
Expand All @@ -74,6 +67,13 @@ class Square extends RectangleComponent with TapCallbacks {
);
}

@override
void update(double dt) {
super.update(dt);
angle += speed * dt;
angle %= 2 * math.pi;
}

@override
void onTapDown(TapDownEvent event) {
removeFromParent();
Expand Down
8 changes: 5 additions & 3 deletions packages/flame/lib/src/anchor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,14 @@ class Anchor {
Vector2 toOtherAnchorPosition(
Vector2 position,
Anchor otherAnchor,
Vector2 size,
) {
Vector2 size, {
Vector2? out,
}) {
if (this == otherAnchor) {
return position;
} else {
return Vector2(otherAnchor.x - x, otherAnchor.y - y)
return (out ?? Vector2.zero())
..setValues(otherAnchor.x - x, otherAnchor.y - y)
..multiply(size)
..add(position);
}
Expand Down
10 changes: 7 additions & 3 deletions packages/flame/lib/src/geometry/polygon_component.dart
Original file line number Diff line number Diff line change
Expand Up @@ -226,14 +226,18 @@ class PolygonComponent extends ShapeComponent {

@override
bool containsLocalPoint(Vector2 point) {
// Take anchor into consideration.
final localPoint =
anchor.toOtherAnchorPosition(point, Anchor.topLeft, size);
if (size.x == 0 || size.y == 0) {
return false;
}
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) -
(point.x - edge.from.x) * (edge.to.y - edge.from.y) >
0;
final isOutside =
(edge.to.x - edge.from.x) * (localPoint.y - edge.from.y) -
(localPoint.x - edge.from.x) * (edge.to.y - edge.from.y) >
0;
if (isOutside) {
return false;
}
Expand Down
27 changes: 27 additions & 0 deletions packages/flame/test/components/shape_component_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,33 @@ void main() {
expect(polygon.containsLocalPoint(Vector2(0.75, 0.75)), isTrue);
});

test('rectangle contains point in local with anchor', () {
final rectangle = RectangleComponent(
position: Vector2.zero(),
size: Vector2.all(10),
anchor: Anchor.center,
);
expect(rectangle.containsLocalPoint(Vector2.zero()), isTrue);
expect(rectangle.containsLocalPoint(Vector2.all(5)), isTrue);
expect(rectangle.containsLocalPoint(Vector2.all(10)), isTrue);
expect(rectangle.containsLocalPoint(Vector2(10, 0)), isTrue);
expect(rectangle.containsLocalPoint(Vector2(0, 10)), isTrue);
});

test('angled rectangle contains point in local with anchor', () {
final rectangle = RectangleComponent(
position: Vector2.zero(),
size: Vector2.all(10),
angle: pi / 4,
anchor: Anchor.center,
);
expect(rectangle.containsLocalPoint(Vector2.zero()), isTrue);
expect(rectangle.containsLocalPoint(Vector2.all(5)), isTrue);
expect(rectangle.containsLocalPoint(Vector2.all(10)), isTrue);
expect(rectangle.containsLocalPoint(Vector2(10, 0)), isTrue);
expect(rectangle.containsLocalPoint(Vector2(0, 10)), isTrue);
});

test('rotated circle does not contain point', () {
final component = CircleComponent(
radius: 1.0,
Expand Down

0 comments on commit 7969321

Please sign in to comment.