C++单文件迷宫游戏:TauriCPP 开发全记录

正文

做了个迷宫游戏,本来只是控制台里打印字符画来着。某天觉得不过瘾,干脆一路做到了炸弹人------吃宝箱得炸弹、2 秒引信、十字爆炸、炸怪物,没躲开连自己一起送走 。最终产物是一个 666KB 的单文件 exe,双击即玩,没有任何外部依赖。

这篇聊聊它是怎么搭起来的。

一句话架构

C++ 负责规则,Web 负责好看。

  • C++ 后端(MSVC 编译):迷宫生成、BFS 最短路径、炸弹引信、怪物游走、碰撞判定,跑一个 120ms 的主循环,每帧把全量状态推给前端;
  • Web 前端(Canvas 2D):墙体、金币、宝箱、怪物、炸弹、爆炸火焰全部手绘,帧间插值动画,移动丝滑;
  • 中间是自研框架 TauriCPP(C++/Win32/WebView2):Bridge 双向通信(invoke 命令 + Emit 事件),前端资源编译期打包进 exe 的 rc,运行时从内存 VirtualFS 加载------不落临时文件,用户看到的只有一个 exe。

几个做得挺舒服的点

1. 游戏逻辑全部在 C++,且可单测。

移动、放弹、爆炸杀伤、误伤、复活这些规则都写成了纯函数(DoMove / TryPlaceBomb / GameTick),配了一个 game_test,连跑多种子回归。改玩法先写测试,心里不慌。

2. 前端不存权威状态。

所有规则以后端为准,前端只做渲染和输入。每次 move 拿回全量快照直接覆盖渲染目标------状态同步想出错都难。

3. 怪物移动"不瞬移"。

后端 0.8 秒走一格,前端拿到新坐标后按 70ms 时间常数做指数插值,看起来就是在"游荡"。怪物还有稳定 id,被炸死/复活后动画表自动增删。炸弹引信越短,脉冲抖动越快------压迫感是渲染出来的,不是规则。

4. 音效也是程序生成的。

没有引入任何音频文件:背景伴奏是 Am-F-C-G 四小节循环(三角波琶音 + 高通噪声打击),吃币、开箱、放弹、爆炸、阵亡全部用 Web Audio Oscillator 现场合成。exe 体积零增长。

踩过的坑(最有价值的部分)

坑一:吃个金币,整个游戏白了。

上线"金币"功能后,一吃金币画面永久空白。最后的现场证据是一行报错:

复制代码
Failed to execute 'arc' on 'CanvasRenderingContext2D':
The radius provided (-14.292) is negative.

两个错误叠在一起:拾取特效用了两套时钟(performance.now() 绝对时间 vs rAF 的相对时间),算出的特效半径为负;而 WebView2 对负半径会抛异常,普通 Chromium 只会静默忽略 ------所以我在 Chrome 里怎么点都复现不出来。异常跳出 rAF 回调后 requestAnimationFrame(loop) 再也不会执行,画布停在 clear 之后的纯色上。

修复:统一时钟基准 + 半径 clamp + 每帧快照兜底(draw 抛异常就恢复上一帧)。结论:WebView2 和 Chrome 的容错不一样,别拿 Chrome 当免测金牌。

坑二:缺失一个 DOM 元素,游戏从开局就白屏。

改版时删了个统计节点,忘了删 JS 里的引用,null.textContent 抛错 → newGame 的 Promise reject → init() 提前终止 → 渲染循环从未启动。一帧都没画过。

坑三:SendKeys 自动化把测试输出发到了我的微信里。

一开始想用 SendKeys 驱动 GUI 测试,结果游戏窗口被微信盖住,按键全发进了聊天框......羞愧。后来换成 CDP 直连 :WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS=--remote-debugging-port=9222 一指,playwright connectOverCDP 上来就能截图、派发真实键盘事件、读页面状态------不抢焦点、不打扰桌面、还能抓 console。上面两个白屏 bug 都是这么逮到的。

数据

指标 值
exe 体积 666 KB(图标占了 93KB)
难度 21×11 ~ 51×29 四档
怪物 1~4 只 / 局
主题 7 套,CSS 变量 + Canvas 双路切换
游戏循环 120ms tick
音频文件 0

仓库

Windows + VS2022 一把梭:git clone 下来跑 .\build.ps1。踩坑经验都写在 README 和提交历史里了,欢迎来交流。

#C++ #WebView2 #桌面开发 #游戏开发 #TauriCPP

相关推荐
Antruly1 小时前
C++ Web 开发选型漫谈:从 Drogon 到 libuvcpp + uvp,八个项目的定位、兼容性与务实排名
开发语言·前端·c++
EnCi Zheng1 小时前
AI Agent工具调用防护层怎么写-一份能直接跑的Python四层拦截实现
大数据·开发语言·python
香蕉大香蕉(06敬畏市场)1 小时前
高频八股 · Java 并发编程(10):异步、ThreadLocal 与虚拟线程(收官)
java·开发语言·网络·jvm·python·ai·实习
念何架构之路1 小时前
Go reflect包值操作 Value 的读写、可设置性与 interface 布局
开发语言·后端·golang
云中飞鸿1 小时前
.Net和C#有什么关系?(从C++视角观察)
开发语言·c#·.net
another heaven1 小时前
【C/C++ C++ 新特性中的那些内存优化的特性】
c语言·开发语言·c++
Wang's Blog2 小时前
Java 项目实战: 交友项目 - 查询推荐动态
java·开发语言·交友
jaysee-sjc2 小时前
【苍穹外卖】Day10:定时任务与 WebSocket 实时提醒实战
java·开发语言·javascript·数据库·vue.js·websocket·网络协议
ysu_03142 小时前
【C++ 进阶之路】(二)从内联函数到类与对象:深挖内存对齐、this 指针与三大默认成员函数
开发语言·数据结构·c++·笔记·面向对象·this