我花一晚上,一个人撸了一款网页塔防游戏,然后开源了

我花一晚上,一个人撸了一款网页塔防游戏,然后开源了

24 个关卡 / 8 种防御塔 / 13 种敌人 / 100 个成就
不用登录、点开就玩、还能 fork 改


家人们,我摊牌了。

银行打工人下班回家,煮了壶咖啡,从晚上 10 点写到凌晨 4 点,一个人撸了一款网页迷宫式塔防 —— PathForge TD,现在正式开源在 GitHub 上了。

写这篇不是凡尔赛,是想认真聊聊:

  • 一个非全职开发者,怎么一晚上从零撸到 24 关可玩的完整游戏
  • 为什么塔防这个老品类,到 2026 年还能让我上头
  • 如果你想 fork 我的代码继续做,门槛有多低

先上截图

封面就是开局那张 —— 8 种防御塔图鉴,一图看懂整个游戏。

箭塔(绿)/ 炮塔(橙)/ 冰塔(青)/ 雷塔(紫)/ 毒塔(深绿)/ 狙击塔(灰)/ 增益塔(黄)/ 兵营(棕),每种塔自带一张「使用说明书」,点哪个塔就告诉你:

  • 这个塔解决什么问题(定位)
  • 伤害类型 / 攻击目标 / 攻击范围
  • 什么时候必须放、什么时候千万别放

游戏里的塔不是「换个颜色的圆圈」,每种都有不可替代的角色。


我为什么又做塔防?

塔防是我玩了十几年都没腻的品类。

但 2026 年的网页 TD,体验好的真不多:

  • 多数要登录、要注册、要看 30 秒广告
  • 美术很精美,但新机制引入慢,前 10 关都在教你怎么玩
  • 攻略查不到,塔的作用解释全靠评论区

所以我做 PathForge TD 的时候,给自己立了三条规矩:

① 每种塔必须自带「使用说明书」
不是那种 攻击力 25、射程 3 的死参数,而是直接告诉你:

"炮塔是慢速高伤的溅射塔,敌人扎堆或被减速时收益最高,克制密集小怪和高护甲前的普通集群。"

玩家不需要去 wiki,不需要看视频,鼠标移上去 3 秒看懂。

② 放塔成功或失败,UI 必须保持稳定
这是我自己当产品经理的职业病。

很多塔防游戏放塔失败,HUD 闪一下、塔栏抖一下、选中状态莫名其妙丢了。PathForge 不会。

放塔失败 → 告诉你为什么失败("这条会完全堵死入口"),然后选中的塔、塔说明、HUD 金币、底部塔栏全部保留。

这个体验看起来简单,但写代码的时候,状态机的清理顺序我调了至少 5 个版本。

③ 路线塑形是核心乐趣,不是附属品
迷宫式 TD 的灵魂,就是玩家自己拉长敌人路径。

PathForge TD 的地面敌人实时 A* 寻路,你每放一座塔,下一波敌人就立刻走新路径。而且放塔之前系统会校验:如果这一放会完全堵死入口到核心的路径,直接拒绝放塔 + 解释原因。

不会让你试错,不会让你误判。所见即所得。


这游戏有多少东西?

来一份强迫症数字清单:

内容 数量
战役关卡 24 个(1-1 到 8-3,按章节递进)
防御塔 8 种(覆盖单体 / 范围 / 减速 / 对空 / 毒伤 / 狙杀 / 增益 / 控制)
敌人 13 种(含 3 个 Boss:森林巨兽、熔岩领主、天空暴君)
成就 100 个(通关、三星、章节征服、击杀里程碑、Boss 猎手、百万富翁)
测试文件 9 个(寻路、放塔合法性、投射物、敌人移动、UI 状态保持……)

关卡不是 24 个随机图 —— 第 1 章教你基础铺火力,第 2 章引入毒雾,第 3 章多入口双核心,第 8 章是终局外环 + 核心围城 + PathForge 终点三连。

难度曲线是拉过的,每次开新章节前必须通关上一章,不能跳级。


它怎么玩?

打开浏览器 → 选关卡 → 开干。

零登录、零注册、零下载(首屏后 Vite 拉一次静态资源)。

基础操作:

操作 说明
鼠标点塔卡 选塔
鼠标移地图 看作用范围和放置预览
鼠标点格子 放塔
鼠标点已有塔 升级 / 出售 / 调优先级
空格 建造阶段开始下一波;战斗阶段暂停/继续
Esc 暂停菜单
1-8 直接选 8 种塔
Q / W / E 1x / 2x / 3x 速度

Q/W/E 三档速度 是我这种 30+ 玩家最爱的功能 —— 后期波次长,加速 3x 看完一波 5 秒,搞研究很方便。


它对新人有多友好?

如果你想 fork 改一版自己的:

git clone https://github.com/itsVicOC/pathforge-td.git
cd pathforge-td
npm install
npm run dev      # 启动开发服务器
npm run test -- --run   # 跑测试
npm run build    # 构建生产版本

技术栈:TypeScript + Vite + Canvas 2D + Vitest。

零框架依赖,没有 React 没有 Vue 没有 Phaser,纯手写 Canvas。

代码组织也清晰:

src/
├── audio/      # 音频系统
├── config/     # 塔、敌人、关卡、波次、成就配置
├── core/       # Game、输入、事件、状态、资源加载
├── entities/   # Tower、Enemy、Projectile、Effect
├── renderer/   # Canvas 2D 渲染
├── systems/    # 寻路、网格、波次、经济、存档
├── types/      # 共享类型
└── ui/         # 战斗 UI 和菜单 UI

想加一个新塔? 改 src/config/towers.ts 一个文件,加完塔自动出现在底部塔栏、HUD 说明、成就统计里。

想加一个新关卡? 改 src/config/levels.ts + 在 waves.ts 里画网格 + 配波次。Level 3-1 到 8-3 我就是这么一行一行加的,复制粘贴改参数就行。

想加一个新敌人? 改 src/config/enemies.ts 一个文件。

我自己是产品经理不是专业前端,这个仓库的代码我自己读得懂、你也读得懂。


我踩过的三个坑(凌晨 4 点还在调的那种)

坑 1:路径预览和地图冲突

凌晨 2 点还在跑第一版,路径预览临时改变了地图格子的颜色。我自己测的时候还以为 feature 是"地形变化",当场笑出声。

最后定下来的规则是:地图格子坐标运行中不能移动;路径预览只能改变路线显示,不能改变关卡布局。

写进 docs/Development-Plan.md 里了,凌晨 3 点敲下这条规则的时候手都是抖的。

坑 2:放塔失败的 UI 抖动

最早期版本放塔失败会闪 HUD、抖塔栏、丢选中状态。调到我差点想砸键盘 —— 因为这是一个"看起来很细节、写起来很崩溃"的 bug。

最后是显式区分 "放塔校验失败" 和 "放塔成功" 两条状态路径,每条路径独立更新 UI 子模块,绝不共用 update()。

凌晨 3 点半调通那一刻,整个人瘫在椅子上。

坑 3:波次奖励规则要早写

我一开始只在 waves.ts 写 bonus: 50 这种数字,没写"奖励规则文档"。结果调平衡的时候完全不知道这数字怎么来的。

后来专门写了 docs/Balance-Notes.md,每次改塔/敌/波/关/经济,都要追加一条。这个习惯让我少走了很多回头路。


这三个坑,如果你也想一晚上撸塔防, 提前知道能省你至少 4 个小时。


为什么开源?

不是为了 star(虽然看到 star 还是会开心 3 秒 😄)。

是因为我做了 6 个版本塔防(个人项目不算这次),每次都因为「自己一个人调平衡调到怀疑人生」而烂尾。

这次的解法是:

  • 代码开源 → 你不满意某个塔的伤害,自己改
  • 文档开源 → GDD / 技术设计 / 平衡记录 / 发布清单,五件套全公开
  • 测试开源 → 9 个测试文件覆盖配置完整性、24 关流程、寻路、投射物、UI 状态

MIT 协议,商用也随便。

我自己保留继续做 PathForge 2 的权利(无尽模式、多人协作、移动端),但任何人都可以 fork 出去做自己的塔防,我双手支持。


现在就玩 / 现在就 fork

在线试玩:(README 里会更新部署地址,仓库自取)

https://github.com/itsVicOC/pathforge-td

仓库地址:

https://github.com/itsVicOC/pathforge-td

记得先给个 ⭐ 再走 —— 30+ 银行打工人业余写代码,每一个 star 都是我下次加班的动力。


我接下来想做什么?

如果社区反馈好,我会继续推进:

  • 无尽模式:24 关打完进无尽,每 10 波一个难度阶梯
  • 关卡编辑器:网页端可视化编辑器,导出 JSON 关卡配置
  • 多语言:先做英文,方便海外玩家
  • 移动端适配:Canvas 自动响应式

每条都写在 docs/Development-Plan.md 里,不是 PPT,是真的按优先级排。

如果你有想看的功能、想吐槽的体验、想贡献的代码,Issues 区随便开,我能回都会回。


最后说点心里话。

塔防这个品类,没有大作的光环,没有出圈的网红玩法,但就是有人默默做了十几年。

我从《植物大战僵尸》玩到《Kingdom Rush》,从《Desktop Tower Defense》玩到《Bloons TD 6》,每个版本都陪我度过了某个加班的深夜。

现在我做了自己的版本,希望它也能陪某个加班的深夜里的你。

哪怕只让你在 Q/W/E 三档加速里爽 5 分钟,那这一晚上的咖啡就没白喝。