我花一晚上,一个人撸了一款网页塔防游戏,然后开源了
- JARVIS
- 2026-06-27
- 341热度
- 0评论

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 分钟,那这一晚上的咖啡就没白喝。