diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3cbf7da3..52c5186e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
### Fixed
- Fixed issue with input mapper where `keyboard.wasPressed(...)` did not fire
+- Fixed issue where the ex.Line graphics bounds were incorrect causing erroneous offscreen culling
### Updates
diff --git a/sandbox/tests/linebounds/index.html b/sandbox/tests/linebounds/index.html
new file mode 100644
index 00000000..97ac7263
--- /dev/null
+++ b/sandbox/tests/linebounds/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+ Line Bounds
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sandbox/tests/linebounds/index.ts b/sandbox/tests/linebounds/index.ts
new file mode 100644
index 00000000..ee03909b
--- /dev/null
+++ b/sandbox/tests/linebounds/index.ts
@@ -0,0 +1,82 @@
+var game = new ex.Engine({
+ width: 1200,
+ height: 400,
+ canvasElementId: "game",
+ pixelRatio: 1
+});
+
+game.debug.entity.showName = true;
+game.toggleDebug()
+
+var actor = new ex.Actor({
+ pos: new ex.Vector(100, 100),
+ width: 50,
+ height: 50,
+ color: ex.Color.Red
+});
+
+class Beam extends ex.Actor {
+ public length;
+
+ constructor(options, length) {
+ super(options);
+ this.graphics.anchor = ex.Vector.Zero;
+ this.length = length;
+ const longLine = new ex.Line({
+ start: ex.vec(0, 0),
+ end: ex.vec(this.length, 0),
+ thickness: 26,
+ color: ex.Color.White
+ });
+ // longLine.height = 26;
+ console.log(longLine.width, longLine.height);
+ console.log(this.graphics.localBounds);
+
+ this.graphics.use(longLine);
+ }
+
+ onPreUpdate() {
+
+ }
+}
+
+var shortBeam = new Beam(
+ {
+ name: "shortBeam",
+ pos: new ex.Vector(200, 200)
+ },
+ 100
+);
+
+var longBeam = new Beam(
+ {
+ name: "longBeam",
+ pos: new ex.Vector(200, 300)
+ },
+ 1001
+);
+
+longBeam.vel.x = -100;
+
+var shortLine = new ex.Line({
+ start: ex.vec(0, 0),
+ end: ex.vec(10, 30),
+ thickness: 26,
+ color: ex.Color.Green
+});
+
+var longLine = new ex.Line({
+ start: ex.vec(0, 0),
+ end: ex.vec(4000, 0),
+ thickness: 26,
+ color: ex.Color.Yellow
+});
+
+actor.graphics.anchor = ex.Vector.Zero;
+actor.graphics.add(shortLine);
+actor.graphics.add(longLine);
+
+game.add(actor);
+game.add(shortBeam);
+game.add(longBeam);
+game.start();
diff --git a/src/engine/Graphics/Line.ts b/src/engine/Graphics/Line.ts
index 701d87c5..3317f113 100644
--- a/src/engine/Graphics/Line.ts
+++ b/src/engine/Graphics/Line.ts
@@ -15,6 +15,7 @@ export class Line extends Graphic {
readonly end: Vector;
color: Color = Color.Black;
thickness: number = 1;
+ private _localBounds: BoundingBox;
constructor(options: LineOptions) {
super();
const { start, end, color, thickness } = options;
@@ -22,11 +23,32 @@ export class Line extends Graphic {
this.end = end;
this.color = color ?? this.color;
this.thickness = thickness ?? this.thickness;
- const { width, height } = BoundingBox.fromPoints([start, end]);
+ this._localBounds = this._calculateBounds();
+ const { width, height } = this._localBounds;
+
this.width = width;
this.height = height;
}
+ public get localBounds() {
+ return this._localBounds;
+ }
+
+ private _calculateBounds(): BoundingBox {
+ const lineNormal = this.end.sub(this.start).normal();
+
+ const halfThickness = this.thickness / 2;
+
+ const points = [
+ this.start.add(lineNormal.scale(halfThickness)),
+ this.end.add(lineNormal.scale(halfThickness)),
+ this.end.add(lineNormal.scale(-halfThickness)),
+ this.start.add(lineNormal.scale(-halfThickness))
+ ];
+
+ return BoundingBox.fromPoints(points);
+ }
+
protected _drawImage(ctx: ExcaliburGraphicsContext, _x: number, _y: number): void {
ctx.drawLine(this.start, this.end, this.color, this.thickness);
}
diff --git a/src/spec/LineSpec.ts b/src/spec/LineSpec.ts
index ab5cc19b..c13dee25 100644
--- a/src/spec/LineSpec.ts
+++ b/src/spec/LineSpec.ts
@@ -41,13 +41,34 @@ describe('A Line', () => {
it('has correct local bounds', () => {
const sut = new ex.Line({
start: ex.vec(0, 0),
- end: ex.vec(50, 70),
+ end: ex.vec(50, 50),
color: ex.Color.Green,
thickness: 5
});
- expect(sut.width).toBe(50);
- expect(sut.height).toBe(70);
+ expect(sut.localBounds.left).toBeCloseTo(-1.767, 2);
+ expect(sut.localBounds.top).toBeCloseTo(-1.767, 2);
+ expect(sut.localBounds.bottom).toBeCloseTo(51.767, 2);
+ expect(sut.localBounds.right).toBeCloseTo(51.767, 2);
+
+ expect(sut.width).toBeCloseTo(53.535, 2);
+ expect(sut.height).toBeCloseTo(53.535, 2);
+ });
+
+ it('has correct bounds when horizontal', () => {
+ const sut = new ex.Line({
+ start: ex.vec(0, 0),
+ end: ex.vec(1000, 0),
+ thickness: 4
+ });
+
+ expect(sut.localBounds.left).toBe(0);
+ expect(sut.localBounds.top).toBe(-2);
+ expect(sut.localBounds.bottom).toBe(2);
+ expect(sut.localBounds.right).toBe(1000);
+
+ expect(sut.width).toBe(1000);
+ expect(sut.height).toBe(4);
});
it('can draw a line', async () => {