class Simulation {
constructor({ width, height, ctx, balls, bars, grid }) {
this.width = width || 800;
this.height = height || 800;
this.center = [this.width / 2, this.height / 2];
this.ctx = ctx || null;
this.maxRadius = d3.max(balls, (a) => a.radius);
this.quadtree = null;
this.balls = balls || [];
this.bars = bars || [];
this.grid = grid;
this.grid.forEach((cell) => {
cell.scored = false;
});
this.fillQueue = [];
this.button = null;
this.roundState = "running";
this.lives = 2;
this.totalScore = 0;
this.roundScore = 0;
this.level = 1;
this.areaCleared = 0;
this.fastDetectBallCollision = fastDetectBallCollision;
this.detectBallWallCollision = detectBallWallCollision;
this.detectBarWallCollision = detectBarWallCollision;
this.detectBallBarCollision = detectBallBarCollision;
this.detectBarToBarCollision = detectBarToBarCollision;
this.evaluateGrid = evaluateGrid;
this.endGame = endGame;
this.endRound = endRound;
}
clearCanvas() {
this.ctx.fillStyle = "#ffffff";
this.ctx.clearRect(0, 0, width, height);
}
tick(endState = false) {
if (endState) {
mutable areaCleared = this.areaCleared;
if (this.lives <= 0) {
this.endGame();
} else {
this.endRound();
}
return;
}
this.clearCanvas();
this.grid.forEach((cell) => {
cell.drawCell();
});
this.quadtree = d3
.quadtree()
.x((d) => d.x)
.y((d) => d.y)
.extent([-1, -1], [this.width + 1, this.height + 1])
.addAll(this.balls);
this.balls.forEach((ball) => {
this.detectBallBarCollision(ball);
this.detectBallWallCollision(ball);
this.fastDetectBallCollision(ball);
ball.tick();
ball.drawCircle();
});
this.bars = this.bars.filter((bar) => bar.remove === false);
this.bars.forEach((bar) => {
if (bar.active) {
this.detectBarWallCollision(bar);
this.detectBarToBarCollision(bar);
bar.tick();
}
bar.drawRect();
});
if (this.bars.filter((bar) => bar.active === true).length === 0) {
this.fillQueue.forEach((bar) => {
this.evaluateGrid(bar);
});
this.fillQueue = [];
}
}
}