html5 canvas instead of DOM
This commit is contained in:
+47
-21
@@ -1,45 +1,71 @@
|
||||
import { useRef } from "react";
|
||||
import { CanvasRenderer, type RenderState } from "./CanvasRenderer";
|
||||
|
||||
export type BoardData = {
|
||||
cols: number;
|
||||
rows: number;
|
||||
};
|
||||
|
||||
export function useBoard() {
|
||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||
export type UseBoardParams = {
|
||||
cellSize?: number;
|
||||
};
|
||||
|
||||
const renderBoard = (cols: number, rows: number) => {
|
||||
export function useBoard(params?: UseBoardParams) {
|
||||
const cellSize = params?.cellSize ?? 24;
|
||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||
const canvasRef = useRef<HTMLCanvasElement | null>(null);
|
||||
const rendererRef = useRef<CanvasRenderer | null>(null);
|
||||
const lastFrameTimeRef = useRef<number>(0);
|
||||
|
||||
function initCanvas(cols: number, rows: number) {
|
||||
const container = containerRef.current;
|
||||
if (!container) return;
|
||||
|
||||
container.innerHTML = "";
|
||||
|
||||
const board = document.createElement("div");
|
||||
board.id = "snake-board";
|
||||
board.className = "snake-board";
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.id = "snake-canvas";
|
||||
canvas.className = "snake-canvas";
|
||||
container.appendChild(canvas);
|
||||
canvasRef.current = canvas;
|
||||
|
||||
for (let r = 0; r < rows; r++) {
|
||||
const rowDiv = document.createElement("div");
|
||||
rowDiv.className = "snake-row";
|
||||
rowDiv.setAttribute("data-r", String(r));
|
||||
rendererRef.current = new CanvasRenderer(canvas, cols, rows, cellSize);
|
||||
lastFrameTimeRef.current = performance.now();
|
||||
}
|
||||
|
||||
for (let c = 0; c < cols; c++) {
|
||||
const cellDiv = document.createElement("div");
|
||||
cellDiv.className = "snake-cell";
|
||||
cellDiv.setAttribute("data-r", String(r));
|
||||
cellDiv.setAttribute("data-c", String(c));
|
||||
rowDiv.appendChild(cellDiv);
|
||||
}
|
||||
|
||||
board.appendChild(rowDiv);
|
||||
function renderBoard(cols: number, rows: number) {
|
||||
if (!canvasRef.current || !rendererRef.current) {
|
||||
initCanvas(cols, rows);
|
||||
} else {
|
||||
rendererRef.current.updateDimensions(cols, rows);
|
||||
}
|
||||
}
|
||||
|
||||
container.appendChild(board);
|
||||
};
|
||||
function renderFrame(state: RenderState) {
|
||||
if (!rendererRef.current) return;
|
||||
|
||||
const now = performance.now();
|
||||
const deltaTime = (now - lastFrameTimeRef.current) / 1000;
|
||||
lastFrameTimeRef.current = now;
|
||||
|
||||
rendererRef.current.render(state, deltaTime);
|
||||
}
|
||||
|
||||
function spawnFoodParticles(pos: { r: number; c: number }) {
|
||||
rendererRef.current?.spawnFoodParticles(pos);
|
||||
}
|
||||
|
||||
function getRenderer(): CanvasRenderer | null {
|
||||
return rendererRef.current;
|
||||
}
|
||||
|
||||
return {
|
||||
containerRef,
|
||||
canvasRef,
|
||||
renderBoard,
|
||||
renderFrame,
|
||||
spawnFoodParticles,
|
||||
getRenderer,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user