Optimize Conway and generic grid rendering

Conway GOL: add executionTime tracking and display; switch to double-buffered read/write grids with structuredClone initialization; refactor life update logic (checkLifeRules, swapGrids) to avoid mutating the source while computing the next generation; adjust per-frame delay to account for execution time; increase MAX_GRID_SIZE from 100 to 200; fix grid binding to use readGrid so UI reflects internal state.

Generic grid: add backgroundColor input and use it to clear canvas each frame; only draw cells whose color differs from background and draw grid lines conditionally based on node size to reduce overdraw; adjust drawNode to only stroke borders for larger nodes.

Templates: set backgroundColor='lightgray' for Conway and Pathfinding grid usages; display execution time in Conway UI.

Misc: remove a debug console.log in sorting component. These changes improve rendering performance, reduce flicker, and surface per-frame timing for tuning the Game of Life simulation.
This commit is contained in:
lobo committed 2026-02-07 09:52:58 +01:00
1 parent 16cc8afd4a
commit 70ed047059
6 files changed
+100 -41

No files matched your search

@@ -21,6 +21,7 @@ export class GenericGridComponent implements AfterViewInit {
@Input() minGridSize: number = 5;
@Input() maxGridSize: number = 50;
@Input() drawNodeBorderColor: string = '#ccc';
@Input() backgroundColor: string = 'lightgray';
// Callbacks from parent component
@Input() createNodeFn!: (row: number, col: number) => any;
@@ -99,19 +100,70 @@ export class GenericGridComponent implements AfterViewInit {
}
drawGrid(): void {
this.ctx.clearRect(0, 0, this.canvas.nativeElement.width, this.canvas.nativeElement.height);
if (!this.ctx || !this.grid.length) return;
const width = this.canvas.nativeElement.width;
const height = this.canvas.nativeElement.height;
const size = this.nodeSize;
this.ctx.fillStyle = this.backgroundColor;
this.ctx.fillRect(0, 0, width, height);
this.ctx.fillStyle = 'black';
for (let row = 0; row < this.gridRows; row++) {
for (let col = 0; col < this.gridCols; col++) {
this.drawNode(this.grid[row][col]);
const node = this.grid[row][col];
const color = this.getNodeColorFn(node);
if (color !== this.backgroundColor) {
if (this.ctx.fillStyle !== color) {
this.ctx.fillStyle = color;
}
const x = col * this.nodeSize;
const y = row * this.nodeSize;
this.ctx.fillRect(x, y, this.nodeSize, this.nodeSize);
}
}
}
if (size > 2) {
this.drawGridLines(width, height);
}
}
private drawGridLines(width: number, height: number): void {
this.ctx.beginPath();
this.ctx.strokeStyle = this.drawNodeBorderColor;
this.ctx.lineWidth = 1;
for (let col = 0; col <= this.gridCols; col++) {
const x = col * this.nodeSize;
this.ctx.moveTo(x, 0);
this.ctx.lineTo(x, height);
}
for (let row = 0; row <= this.gridRows; row++) {
const y = row * this.nodeSize;
this.ctx.moveTo(0, y);
this.ctx.lineTo(width, y);
}
this.ctx.stroke();
}
drawNode(node: any): void {
this.ctx.fillStyle = this.getNodeColorFn(node);
this.ctx.fillRect(node.col * this.nodeSize, node.row * this.nodeSize, this.nodeSize, this.nodeSize);
this.ctx.strokeStyle = this.drawNodeBorderColor;
this.ctx.strokeRect(node.col * this.nodeSize, node.row * this.nodeSize, this.nodeSize, this.nodeSize);
if (this.nodeSize > 4) {
this.ctx.strokeStyle = this.drawNodeBorderColor;
this.ctx.strokeRect(node.col * this.nodeSize, node.row * this.nodeSize, this.nodeSize, this.nodeSize);
}
}
private getContextOrThrow(): CanvasRenderingContext2D {