From 3a190abf37229d33be3eb5671a25fbb328770fb0 Mon Sep 17 00:00:00 2001 From: Andrii Kuchmenda Date: Mon, 6 Apr 2026 19:45:01 +0300 Subject: [PATCH 1/3] feat: add regular polygon constructors to PolygonComponent and PolygonHitbox --- .../collisions/hitboxes/polygon_hitbox.dart | 15 +++++++ .../lib/src/geometry/polygon_component.dart | 40 ++++++++++++++++++- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/packages/flame/lib/src/collisions/hitboxes/polygon_hitbox.dart b/packages/flame/lib/src/collisions/hitboxes/polygon_hitbox.dart index 878458de07e..302f81ee2f4 100644 --- a/packages/flame/lib/src/collisions/hitboxes/polygon_hitbox.dart +++ b/packages/flame/lib/src/collisions/hitboxes/polygon_hitbox.dart @@ -40,6 +40,21 @@ class PolygonHitbox extends PolygonComponent this.collisionType = collisionType; } + /// With this constructor you create a regular (equiangular and equilateral) + /// polygon hitbox from number of sides and radius. + PolygonHitbox.regularPolygon( + super.sides, + super.radius, { + super.position, + super.angle, + super.anchor, + bool isSolid = false, + CollisionType collisionType = CollisionType.active, + }) : super.regularPolygon() { + this.isSolid = isSolid; + this.collisionType = collisionType; + } + @override @protected void computeAabb(Aabb2 aabb) { diff --git a/packages/flame/lib/src/geometry/polygon_component.dart b/packages/flame/lib/src/geometry/polygon_component.dart index 7c528584e71..93734b50675 100644 --- a/packages/flame/lib/src/geometry/polygon_component.dart +++ b/packages/flame/lib/src/geometry/polygon_component.dart @@ -22,9 +22,9 @@ class PolygonComponent extends ShapeComponent { final _cachedGlobalVertices = ValueCache>(); - /// With this constructor you create your [PolygonComponent] from positions in + /// With this constructor you create your [PolygonComponent] from positions /// anywhere in the 2d-space. It will automatically calculate the [size] of - /// the Polygon (the bounding box) if no size it given. + /// the Polygon (the bounding box) if no size is given. PolygonComponent( this._vertices, { super.position, @@ -93,6 +93,42 @@ class PolygonComponent extends ShapeComponent { children: children, ); + /// With this constructor you create a regular (equiangular and equilateral) + /// polygon from number of sides and radius anywhere in the 2d-space. It will + /// automatically calculate the [size] of the Polygon (the bounding box) if no + /// size is given. + PolygonComponent.regularPolygon( + int sides, + double radius, { + Vector2? position, + Vector2? size, + Vector2? scale, + double? angle, + Anchor? anchor, + Iterable? children, + int? priority, + Paint? paint, + List? paintLayers, + ComponentKey? key, + bool? shrinkToBounds, + }) : this( + List.generate(sides, (i) { + final angle = 2 * pi * i / sides; + return Vector2(radius * cos(angle), radius * sin(angle)); + }, growable: false), + position: position, + size: size, + scale: scale, + angle: angle, + anchor: anchor, + children: children, + priority: priority, + paint: paint, + paintLayers: paintLayers, + key: key, + shrinkToBounds: shrinkToBounds, + ); + @internal static List normalsToVertices( List normals, From 32f963b089ab9c6566031951d23c4743807971ad Mon Sep 17 00:00:00 2001 From: Andrii Kuchmenda Date: Mon, 20 Apr 2026 16:51:23 +0300 Subject: [PATCH 2/3] feat: rename constructors for regular polygon hitboxes to improve clarity --- .../flame/lib/src/collisions/hitboxes/polygon_hitbox.dart | 4 ++-- packages/flame/lib/src/geometry/polygon_component.dart | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/flame/lib/src/collisions/hitboxes/polygon_hitbox.dart b/packages/flame/lib/src/collisions/hitboxes/polygon_hitbox.dart index 302f81ee2f4..90da4f6eb6e 100644 --- a/packages/flame/lib/src/collisions/hitboxes/polygon_hitbox.dart +++ b/packages/flame/lib/src/collisions/hitboxes/polygon_hitbox.dart @@ -42,7 +42,7 @@ class PolygonHitbox extends PolygonComponent /// With this constructor you create a regular (equiangular and equilateral) /// polygon hitbox from number of sides and radius. - PolygonHitbox.regularPolygon( + PolygonHitbox.regular( super.sides, super.radius, { super.position, @@ -50,7 +50,7 @@ class PolygonHitbox extends PolygonComponent super.anchor, bool isSolid = false, CollisionType collisionType = CollisionType.active, - }) : super.regularPolygon() { + }) : super.regular() { this.isSolid = isSolid; this.collisionType = collisionType; } diff --git a/packages/flame/lib/src/geometry/polygon_component.dart b/packages/flame/lib/src/geometry/polygon_component.dart index 93734b50675..5b5fd3de3c0 100644 --- a/packages/flame/lib/src/geometry/polygon_component.dart +++ b/packages/flame/lib/src/geometry/polygon_component.dart @@ -97,7 +97,7 @@ class PolygonComponent extends ShapeComponent { /// polygon from number of sides and radius anywhere in the 2d-space. It will /// automatically calculate the [size] of the Polygon (the bounding box) if no /// size is given. - PolygonComponent.regularPolygon( + PolygonComponent.regular( int sides, double radius, { Vector2? position, From bdc47d731d445a92e4959e4351d0d6666b3d8b5f Mon Sep 17 00:00:00 2001 From: Andrii Kuchmenda Date: Mon, 20 Apr 2026 17:03:33 +0300 Subject: [PATCH 3/3] feat: update regular constructors for PolygonHitbox and PolygonComponent to use named parameters --- .../collisions/hitboxes/polygon_hitbox.dart | 6 +-- .../lib/src/geometry/polygon_component.dart | 6 +-- ...lygon_hitbox_regular_constructor_test.dart | 48 +++++++++++++++++++ ...on_component_regular_constructor_test.dart | 47 ++++++++++++++++++ 4 files changed, 101 insertions(+), 6 deletions(-) create mode 100644 packages/flame/test/collisions/polygon_hitbox_regular_constructor_test.dart create mode 100644 packages/flame/test/geometry/polygon_component_regular_constructor_test.dart diff --git a/packages/flame/lib/src/collisions/hitboxes/polygon_hitbox.dart b/packages/flame/lib/src/collisions/hitboxes/polygon_hitbox.dart index 90da4f6eb6e..3bb172fdb71 100644 --- a/packages/flame/lib/src/collisions/hitboxes/polygon_hitbox.dart +++ b/packages/flame/lib/src/collisions/hitboxes/polygon_hitbox.dart @@ -42,9 +42,9 @@ class PolygonHitbox extends PolygonComponent /// With this constructor you create a regular (equiangular and equilateral) /// polygon hitbox from number of sides and radius. - PolygonHitbox.regular( - super.sides, - super.radius, { + PolygonHitbox.regular({ + required super.sides, + required super.radius, super.position, super.angle, super.anchor, diff --git a/packages/flame/lib/src/geometry/polygon_component.dart b/packages/flame/lib/src/geometry/polygon_component.dart index 5b5fd3de3c0..044283fb062 100644 --- a/packages/flame/lib/src/geometry/polygon_component.dart +++ b/packages/flame/lib/src/geometry/polygon_component.dart @@ -97,9 +97,9 @@ class PolygonComponent extends ShapeComponent { /// polygon from number of sides and radius anywhere in the 2d-space. It will /// automatically calculate the [size] of the Polygon (the bounding box) if no /// size is given. - PolygonComponent.regular( - int sides, - double radius, { + PolygonComponent.regular({ + required int sides, + required double radius, Vector2? position, Vector2? size, Vector2? scale, diff --git a/packages/flame/test/collisions/polygon_hitbox_regular_constructor_test.dart b/packages/flame/test/collisions/polygon_hitbox_regular_constructor_test.dart new file mode 100644 index 00000000000..391f99665db --- /dev/null +++ b/packages/flame/test/collisions/polygon_hitbox_regular_constructor_test.dart @@ -0,0 +1,48 @@ +import 'package:flame/collisions.dart'; +import 'package:flame/components.dart'; +import 'package:test/test.dart'; + +void main() { + group('PolygonHitbox.regular', () { + test('creates the expected number of vertices', () { + final hitbox = PolygonHitbox.regular(sides: 7, radius: 10); + + expect(hitbox.vertices, hasLength(7)); + }); + + test('places all vertices at the given radius from the center', () { + const radius = 12.5; + final hitbox = PolygonHitbox.regular(sides: 8, radius: radius); + + for (final vertex in hitbox.vertices) { + expect(vertex.length, closeTo(radius, 1e-10)); + } + }); + + test('uses center anchor by default', () { + final hitbox = PolygonHitbox.regular(sides: 5, radius: 10); + + expect(hitbox.anchor, Anchor.center); + }); + + test('supports custom position and anchor', () { + final hitbox = PolygonHitbox.regular( + sides: 6, + radius: 3, + position: Vector2(10, 20), + anchor: Anchor.topLeft, + ); + + expect(hitbox.position.x, closeTo(10, 1e-10)); + expect(hitbox.position.y, closeTo(20, 1e-10)); + expect(hitbox.anchor, Anchor.topLeft); + }); + + test('throws assertion error when sides are less than 3', () { + expect( + () => PolygonHitbox.regular(sides: 2, radius: 5), + throwsA(isA()), + ); + }); + }); +} diff --git a/packages/flame/test/geometry/polygon_component_regular_constructor_test.dart b/packages/flame/test/geometry/polygon_component_regular_constructor_test.dart new file mode 100644 index 00000000000..be4157bf56e --- /dev/null +++ b/packages/flame/test/geometry/polygon_component_regular_constructor_test.dart @@ -0,0 +1,47 @@ +import 'package:flame/components.dart'; +import 'package:test/test.dart'; + +void main() { + group('PolygonComponent.regular', () { + test('creates the expected number of vertices', () { + final component = PolygonComponent.regular(sides: 7, radius: 10); + + expect(component.vertices, hasLength(7)); + }); + + test('places all vertices at the given radius from the center', () { + const radius = 12.5; + final component = PolygonComponent.regular(sides: 8, radius: radius); + + for (final vertex in component.vertices) { + expect(vertex.length, closeTo(radius, 1e-10)); + } + }); + + test('uses center anchor by default', () { + final component = PolygonComponent.regular(sides: 5, radius: 10); + + expect(component.anchor, Anchor.center); + }); + + test('supports custom position and anchor', () { + final component = PolygonComponent.regular( + sides: 6, + radius: 3, + position: Vector2(10, 20), + anchor: Anchor.topLeft, + ); + + expect(component.position.x, closeTo(10, 1e-10)); + expect(component.position.y, closeTo(20, 1e-10)); + expect(component.anchor, Anchor.topLeft); + }); + + test('throws assertion error when sides are less than 3', () { + expect( + () => PolygonComponent.regular(sides: 2, radius: 5), + throwsA(isA()), + ); + }); + }); +}