React 中的生命游戏项目,尝试更改单击时的单元格颜色,但它不起作用;我真的不知道为什么不。堆栈溢出似乎希望我更具体,但我实际上不知道问题是什么;它引用我的数组坐标就好了(console.log 已确认),但它告诉我 y 轴 grid[x][y] 上存在类型错误,并且我不知道类型错误是否引用了该索引处的值或者是否尝试使用索引本身;我一直盯着它看,但我无法弄清楚。
我的画布组件(还没有开始将其拆分;还没有评论得很好)
import { useRef, useEffect } from "react";
export default function GameOfLifeCanvas() {
//! component wide variables
//! create reference to canvas
const canvasRef = useRef(null);
const resolution = 20;
const width = 400;
const height = 400;
const cellTypes = [
{
name: "standardCell",
liveRepresentation: 1,
color: "",
behavior: {},
},
];
//! cellTypeCount is the number of cell types; alive, x, y, z = 4;; + 1 for dead cell
const cellTypeCount = cellTypes.length + 1;
//! run when component mounts
useEffect(() => {
const columns = width / resolution;
const rows = height / resolution;
const canvas = canvasRef.current;
const context = canvas.getContext("2d");
let grid = () => {
//! start with empty array
const grd = [];
//! for every row
for (let i = 0; i < rows; i++) {
const row = [];
//! for every column
for (let ii = 0; ii < columns; ii++) {
//! push 0 to row
row.push(Math.floor(Math.random() * cellTypeCount));
}
//! push row to columns for every column
grd.push(row);
}
return grd;
};
function mouseClick(e) {
let mouseX, mouseY;
if (e.offsetX) {
mouseX = e.offsetX;
mouseY = e.offsetY;
} else if (e.layerX) {
mouseX = e.layerX;
mouseY = e.layerY;
}
let gridX = Math.floor(mouseX / resolution);
let gridY = Math.floor(mouseY / resolution);
console.log(gridX, gridY);
let xy = grid[gridX][gridY];
if (xy == 0) {
grid[gridX][gridY] = 1;
console.log("white");
} else if (xy === 1) {
grid[gridX][gridY] = 0;
console.log("black");
}
render(grid);
}
canvas.addEventListener("mousedown", mouseClick, false);
render(grid());
function render(grid) {
for (let col = 0; col < grid.length; col++) {
for (let row = 0; row < grid[col].length; row++) {
const cell = grid[col][row];
context.beginPath();
// context.rect(
// col * resolution,
// row * resolution,
// resolution,
// resolution
// );
//! truthy is black falsy is white
context.fillStyle = cell ? "black" : "white";
context.fillRect(
col * resolution,
row * resolution,
resolution,
resolution
);
context.stroke();
}
}
console.log(grid);
}
}, []);
return (
<>
<canvas ref={canvasRef} width={width} height={height}></canvas>
</>
);
}
为了将网格矩阵初始化为其初始状态,您创建了一个名为 grid 的函数。在第一次渲染中,该函数被调用,并将其返回值传递给渲染函数。
但是,每当用户单击画布并且需要更新网格时,您似乎都在修改函数而不是其返回值
grid[gridX][gridY] = 1;
相反,您应该将网格矩阵存储在变量中,并对其进行操作。
在下面的代码片段中,我将您的
grid
函数放置在全局 create_empty_grid
函数中。在组件的第一次渲染期间,调用此函数并将返回值存储在变量中。在 mousedown 事件中,我们修改变量并使用它重新渲染画布。
import { useRef, useEffect } from "react";
const resolution = 20;
const width = 400;
const height = 400;
const cellTypes = [
{
name: "standardCell",
liveRepresentation: 1,
color: "",
behavior: {},
},
];
const create_empty_grid = () => {
const columns = width / resolution;
const rows = height / resolution;
//! cellTypeCount is the number of cell types; alive, x, y, z = 4;; + 1 for dead cell
const cellTypeCount = cellTypes.length + 1;
//! start with empty array
const grd = [];
//! for every row
for (let i = 0; i < rows; i++) {
const row = [];
//! for every column
for (let ii = 0; ii < columns; ii++) {
//! push 0 to row
row.push(Math.floor(Math.random() * cellTypeCount));
}
//! push row to columns for every column
grd.push(row);
}
return grd;
};
export default function GameOfLifeCanvas() {
//! component wide variables
//! create reference to canvas
const canvasRef = useRef(null);
//! run when component mounts
useEffect(() => {
const canvas = canvasRef.current;
const context = canvas.getContext("2d");
let grid = create_empty_grid();
function mouseClick(e) {
let mouseX, mouseY;
if (e.offsetX) {
mouseX = e.offsetX;
mouseY = e.offsetY;
} else if (e.layerX) {
mouseX = e.layerX;
mouseY = e.layerY;
}
let gridX = Math.floor(mouseX / resolution);
let gridY = Math.floor(mouseY / resolution);
console.log(gridX, gridY);
let xy = grid[gridX][gridY];
if (xy == 0) {
grid[gridX][gridY] = 1;
console.log("white");
} else if (xy === 1) {
grid[gridX][gridY] = 0;
console.log("black");
}
render(grid);
}
canvas.addEventListener("mousedown", mouseClick, false);
render(grid);
function render(grid) {
for (let col = 0; col < grid.length; col++) {
for (let row = 0; row < grid[col].length; row++) {
const cell = grid[col][row];
context.beginPath();
//! truthy is black falsy is white
context.fillStyle = cell ? "black" : "white";
context.fillRect(
col * resolution,
row * resolution,
resolution,
resolution
);
context.stroke();
}
}
console.log(grid);
}
}, []);
return <canvas ref={canvasRef} width={width} height={height}></canvas>;
}