Skip to content

Commit

Permalink
fix: [#3205] Prevent degenerate PolygonColliders
Browse files Browse the repository at this point in the history
closes: #3205
  • Loading branch information
eonarheim committed Oct 5, 2024
1 parent aa8307b commit e4893a9
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ are doing mtv adjustments during precollision.

### Fixed

- Fixed issue where `ex.PolygonColliders` would get trapped in infinite loop for degenerate polygons (< 3 vertices)
- Fixed issue where certain devices that support large numbers of texture slots exhaust the maximum number of if statements (complexity) in the shader.
- Fixed issue where `ex.Label` where setting the opacity of caused a multiplicative opacity effect when actor opacity set
- Fixed issue where the `ex.Loader` would have a low res logo on small configured resolution sizes
Expand Down
6 changes: 5 additions & 1 deletion src/engine/Collision/Colliders/PolygonCollider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export interface PolygonColliderOptions {
offset?: Vector;
/**
* Points in the polygon in order around the perimeter in local coordinates. These are relative from the body transform position.
* **Must be at least 3 points**
*/
points: Vector[];

Expand Down Expand Up @@ -61,6 +62,9 @@ export class PolygonCollider extends Collider {
* Excalibur stores these in counter-clockwise order
*/
public set points(points: Vector[]) {
if (points.length < 3) {
throw new Error('PolygonCollider cannot be created with less that 3 points');
}
this._points = points;
this._checkAndUpdateWinding(this._points);
this._calculateNormals();
Expand Down Expand Up @@ -97,7 +101,7 @@ export class PolygonCollider extends Collider {
this.offset = options.offset ?? Vector.Zero;
this._transform.pos.x += this.offset.x;
this._transform.pos.y += this.offset.y;
this.points = options.points ?? [];
this.points = options.points;

if (!this.isConvex()) {
if (!options.suppressConvexWarning) {
Expand Down
15 changes: 12 additions & 3 deletions src/spec/CollisionShapeSpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -474,21 +474,30 @@ describe('Collision Shape', () => {

it('can be constructed with empty args', () => {
const poly = new ex.PolygonCollider({
points: [ex.Vector.One]
points: [ex.Vector.One, ex.Vector.Zero, ex.Vector.Right]
});
expect(poly).not.toBe(null);
});

it('does not allow degenerate polygons', () => {
const action = () => {
const poly = new ex.PolygonCollider({
points: [ex.Vector.One]
});
};
expect(action).toThrowError('PolygonCollider cannot be created with less that 3 points');
});

it('can be cloned', () => {
const actor1 = new ex.Actor({ x: 0, y: 0, width: 20, height: 20 });
const poly = actor1.collider.usePolygonCollider([ex.Vector.One, ex.Vector.Half], new ex.Vector(20, 25));
const poly = actor1.collider.usePolygonCollider([ex.Vector.One, ex.Vector.Half, ex.Vector.Right], new ex.Vector(20, 25));

const sut = poly.clone();

expect(sut).not.toBe(poly);
expect(sut.offset).toBeVector(poly.offset);
expect(sut.offset).not.toBe(poly.offset);
expect(sut.points.length).toBe(2);
expect(sut.points.length).toBe(3);
});

it('can be constructed with points', () => {
Expand Down

0 comments on commit e4893a9

Please sign in to comment.