p5.js从draw外部调用redraw实现迷宫生成步骤逐帧渲染问题
解决方案
核心思路
你现在的问题是算法在初始化时就一次性执行完了所有生成逻辑,所以draw()只能渲染最终的完整迷宫。要实现分步渲染,需要把所有迷宫算法改造成可迭代的步进结构,每次只执行一步生成逻辑,再配合p5.js的draw()循环逐帧更新。
具体修改步骤
1. 统一算法接口标准
所有独立的迷宫算法类都遵循统一的接口规范,方便后续扩展新算法:
- 构造函数接收
Grid实例作为参数,初始化算法运行需要的状态(比如当前处理的单元格坐标、临时存储的路径集合等) - 提供
step()方法:每次调用只执行1步生成逻辑,返回布尔值,true代表迷宫生成完成,false代表还在生成中 - 可选暴露
currentCell等属性,用于后续给处理中的单元格上色标记
以Sidewinder算法为例,sidewinder.js的示例代码:
class Sidewinder { constructor(grid) { this.grid = grid; // 初始化算法状态:当前处理的行、列 this.currentRow = 0; this.currentCol = 0; this.runSet = []; // Sidewinder算法需要的临时运行集合 } step() { // 已经处理完所有行,生成结束 if (this.currentRow >= this.grid.rows) return true; const cell = this.grid.cells[this.currentRow][this.currentCol]; this.runSet.push(cell); this.currentCell = cell; // 暴露当前处理的单元格,用于渲染标记 const atEastBoundary = (this.currentCol === this.grid.columns - 1); const atNorthBoundary = (this.currentRow === 0); const shouldCloseRun = atEastBoundary || (!atNorthBoundary && random() < 0.5); if (shouldCloseRun) { // 关闭当前run,随机选一个单元格打通北侧 const member = this.runSet[Math.floor(random(this.runSet.length))]; if (member.north) member.link(member.north); this.runSet = []; } else { // 打通和东侧单元格的墙 cell.link(cell.east); } // 移动到下一个单元格 this.currentCol++; if (this.currentCol >= this.grid.columns) { this.currentCol = 0; this.currentRow++; } return false; } }
2. 修改主入口sketch.js
全局存储当前运行的算法实例,每帧先执行一步算法再渲染:
let grid; let currentAlgorithm; function setup() { createCanvas(800, 800); frameRate(20); // 可以调整这个值控制生成速度 grid = new Grid(50, 50); // 初始化选中的算法,后续切换其他算法只要替换这里的实例即可 currentAlgorithm = new Sidewinder(grid); } function draw() { background(51); // 执行一步算法逻辑 const isFinished = currentAlgorithm.step(); // 渲染当前网格状态 grid.toCanvas(width); // 可选:给当前处理的单元格上色 if (!isFinished) { const cellSize = width / grid.rows; const cell = currentAlgorithm.currentCell; fill(255, 0, 0); noStroke(); rect(cell.pos.x * cellSize, cell.pos.y * cellSize, cellSize, cellSize); } else { noLoop(); // 生成完成后停止循环,节省性能 } }
3. 修正HTML的js引入顺序
在你的index.html中按依赖顺序引入所有文件,确保先加载依赖、再加载主逻辑:
<script src="p5.min.js"></script> <script src="grid.js"></script> <script src="sidewinder.js"></script> <!-- 后续新增其他算法文件也在这里按顺序引入 --> <script src="sketch.js"></script>
其他说明
- 你原代码中
Sindewinder是拼写错误,注意和类名Sidewinder保持一致 - 后续新增其他迷宫算法,只要符合
step()的接口规范,不用修改主渲染逻辑,直接替换currentAlgorithm的实例即可 - 可以通过调整
frameRate()的参数控制生成动画的快慢
内容的提问来源于stack exchange,提问作者Remaori
相关产品推荐
相关产品推荐

