调试 Rust + WebAssembly 版康威生命游戏

1. 启用 Panic 日志

1.1 让 Panic 信息显示在浏览器控制台

如果 Rust 代码发生 panic!(),默认情况下不会在浏览器开发者工具中显示详细的错误信息。这使得排查问题变得困难。

我们可以使用 console_error_panic_hook 这个 Rust crate ,将 Panic 信息打印到 浏览器控制台

1.2 在 wasm-game-of-life/src/lib.rs 中修改 new 方法

rust 复制代码
pub fn new() -> Universe {
    utils::set_panic_hook();  // 让 Panic 信息出现在控制台

    // 其他初始化代码...
}

1.3 安装 console_error_panic_hook

如果 wasm-game-of-life/src/utils.rs 还没有 set_panic_hook() 方法,我们需要手动引入 console_error_panic_hook

rust 复制代码
pub fn set_panic_hook() {
    console_error_panic_hook::set_once();
}

这样,当 Rust 代码 崩溃(panic) 时,就能在 浏览器控制台 看到详细的错误信息,包括 Rust 堆栈回溯(stack trace)

2. 添加日志调试

2.1 使用 web_sys::console.log 记录日志

WebAssembly 代码无法直接使用 println!() ,但可以借助 web_sys 将日志输出到 浏览器控制台

首先,在 Cargo.toml 文件中启用 web-sys 依赖

toml 复制代码
[dependencies.web-sys]
version = "0.3"
features = ["console"]

然后,在 wasm-game-of-life/src/lib.rs 定义一个 log!(),用于在 Rust 代码中方便地输出调试信息:

rust 复制代码
extern crate web_sys;

// 定义 `log!()` 宏,类似 `println!()`,但输出到 `console.log`
macro_rules! log {
    ( $( $t:tt )* ) => {
        web_sys::console::log_1(&format!( $( $t )* ).into());
    }
}

2.2 在 tick() 方法中记录细胞状态

我们可以在 tick() 方法中 记录每个细胞的状态变化

rust 复制代码
impl Universe {
    pub fn tick(&mut self) {
        let mut next = self.cells.clone();

        for row in 0..self.height {
            for col in 0..self.width {
                let idx = self.get_index(row, col);
                let cell = self.cells[idx];
                let live_neighbors = self.live_neighbor_count(row, col);

                // 记录当前细胞的状态和活邻居数量
                log!(
                    "cell[{}, {}] is initially {:?} and has {} live neighbors",
                    row, col, cell, live_neighbors
                );

                let next_cell = match (cell, live_neighbors) {
                    (Cell::Alive, x) if x < 2 => Cell::Dead,  // 过少 -> 死亡
                    (Cell::Alive, 2) | (Cell::Alive, 3) => Cell::Alive,  // 繁衍 -> 存活
                    (Cell::Alive, x) if x > 3 => Cell::Dead,  // 过度拥挤 -> 死亡
                    (Cell::Dead, 3) => Cell::Alive,  // 复活
                    (otherwise, _) => otherwise,
                };

                // 记录细胞变化
                if next_cell != cell {
                    log!(
                        "    cell[{}, {}] transitioned from {:?} to {:?}",
                        row, col, cell, next_cell
                    );
                }

                next[idx] = next_cell;
            }
        }

        self.cells = next;
    }
}

3. 在 JavaScript 中使用 debugger 进行断点调试

3.1 在 renderLoop() 中设置断点

我们可以在 renderLoop()手动插入 debugger; 语句 ,让浏览器在每次 tick() 之前 暂停代码执行

js 复制代码
const renderLoop = () => {
  debugger;  // 断点调试,暂停执行

  universe.tick();
  drawGrid();
  drawCells();

  requestAnimationFrame(renderLoop);
};

3.2 调试步骤

  1. 打开开发者工具(F12 或右键 → Inspect)
  2. 进入 "Sources" 选项卡
  3. 执行 npm run start 运行游戏
  4. 游戏在 debugger; 处暂停 ,你可以:
    • 逐步执行代码(Step Over)
    • 观察变量的值
    • 查看 WebAssembly 内存状态

4. 练习

练习 1:记录状态变化

任务 :在 tick() 方法中,仅记录发生状态变化的细胞 (从 AliveDeadDeadAlive)。
实现

rust 复制代码
if next_cell != cell {
    log!(
        "cell[{}, {}] transitioned from {:?} to {:?}",
        row, col, cell, next_cell
    );
}

练习 2:手动触发 Panic**

任务 :在 new() 方法中 故意触发 panic ,观察不同情况下的 浏览器堆栈追踪
实现

rust 复制代码
pub fn new() -> Universe {
    utils::set_panic_hook();
    
    panic!("Intentional panic for debugging!");  // 触发崩溃
}

步骤

  1. 运行 npm run start
  2. 在控制台查看 panic!() 抛出的错误
  3. 尝试关闭 console_error_panic_hook 并重新测试
    • Cargo.toml 移除 console_error_panic_hook
    • 运行 wasm-pack build
    • 观察 错误信息变得难以理解,因为 Rust Panic 追踪信息消失了。

5. 总结

调试技巧 作用
console_error_panic_hook 让 Rust Panic 信息出现在浏览器控制台
log!() 在 Rust 代码中使用 console.log() 输出日志
记录状态变化 仅在细胞状态改变时记录日志,减少无用信息
debugger; 断点 让浏览器暂停在 tick() 之前,手动调试
手动 panic!() 观察 Panic 追踪信息,学习如何优化错误信息

6.下一步

  • 优化 WebAssembly 性能
    • 使用 位运算优化细胞存储(每个细胞只占 1 bit,而不是 1 byte)
    • 使用 Web Workers 进行并行计算
  • 增加交互
    • 让用户 手动绘制初始图案
    • 控制 tick() 速度

通过 Rust + WebAssembly ,我们可以在 浏览器中高效运行生命游戏 ,并通过 强大的调试工具 确保代码的正确性!🚀

相关推荐
yezipi耶不耶38 分钟前
Rust入门之并发编程基础(一)
开发语言·后端·rust
lizz6662 小时前
MAC软件游戏打开提示已损坏
游戏·macos
book_bbyuan2 小时前
MFC坦克大战游戏制作
游戏
哥谭市情歌王5 小时前
嵌入式编译工具链熟悉与游戏移植
游戏
Source.Liu6 小时前
【PhysUnits】15.5 引入P1后的标准化表示(standardization.rs)
rust
Swift社区8 小时前
AI 的早期萌芽?用 Swift 演绎约翰·康威的「生命游戏」
游戏·蓝桥杯·swift
一大Cpp15 小时前
Ubuntu下编译mininim游戏全攻略
linux·ubuntu·游戏
Kim Jackson15 小时前
我的世界Java版1.21.4的Fabric模组开发教程(十一)创建方块
java·游戏·fabric
无名之逆17 小时前
[特殊字符]For Speed Enthusiasts: The Ultimate Evolution of Rust HTTP Engines
开发语言·前端·后端·网络协议·http·rust
struggle20251 天前
OramaCore 是您 AI 项目、答案引擎、副驾驶和搜索所需的 AI 运行时。它包括一个成熟的全文搜索引擎、矢量数据库、LLM界面和更多实用程序
人工智能·python·rust