import { ColliderComponent } from '@ud-viz/game_shared/src';
import { throttle } from '@ud-viz/utils_shared/src';
import { Box3, Vector3 } from 'three';
/** @class Canvas to visualize collision boundaries in a game context. */
export class DebugCollision {
constructor(gameContext) {
/** @type {import("@ud-viz/game_shared").Context} */
this.gameContext = gameContext;
/** @type {HTMLCanvasElement} */
this.domElement = document.createElement('canvas');
this.domElement.width = 512;
this.domElement.height = 512;
this.draw = throttle(() => {
const ctx = this.domElement.getContext('2d');
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, this.domElement.width, this.domElement.height);
const bb = new Box3();
this.gameContext.object3D.traverse((child) => {
const collider = child.getComponent(ColliderComponent.TYPE);
if (collider) {
collider.controller.shapeWrappers.forEach((wrapper) => {
if (wrapper.json.type == ColliderComponent.SHAPE_TYPE.CIRCLE) {
bb.expandByPoint(
new Vector3(
wrapper.shape.x + wrapper.shape.radius * wrapper.shape.scale,
wrapper.shape.y + wrapper.shape.radius * wrapper.shape.scale,
0
)
);
bb.expandByPoint(
new Vector3(
wrapper.shape.x - wrapper.shape.radius * wrapper.shape.scale,
wrapper.shape.y - wrapper.shape.radius * wrapper.shape.scale,
0
)
);
} else {
// TODO: check how to do the same thing without reading _coords
for (
let index = 0;
index < wrapper.shape._coords.length;
index += 2
) {
const x = wrapper.shape._coords[index];
const y = wrapper.shape._coords[index + 1];
bb.expandByPoint(new Vector3(x, y, 0));
}
}
});
}
});
const maxDim = Math.max(bb.max.x - bb.min.x, bb.max.y - bb.min.y);
const center = bb.getCenter(new Vector3());
ctx.save();
ctx.translate(
(0.5 - center.x / maxDim) * this.domElement.width,
(0.5 + center.y / maxDim) * this.domElement.height
);
ctx.scale(
this.domElement.width / maxDim,
-this.domElement.height / maxDim
);
ctx.beginPath();
this.gameContext.collisions.drawBVH(ctx);
ctx.lineWidth = 1;
ctx.strokeStyle = 'red';
ctx.stroke();
ctx.beginPath();
this.gameContext.collisions.draw(ctx);
ctx.fillStyle = 'green';
ctx.fill();
ctx.restore();
}, 100);
}
}