You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 12:45:03