从零开始:我用纯 Python
写了一个文字 RPG 游戏
零外部依赖 · 2400 行代码 · 7 张地图 · 5 个主线任务
Python 3.14tkinter零依赖回合制战斗数据驱动
📖 本文目录
一、缘起:为什么要用纯 Python 写游戏?
作为一个从小玩着《仙剑奇侠传》《轩辕剑》长大的一代,我一直对 RPG 游戏有着特殊的情结。那些仗剑走天涯的江湖梦、扣人心弦的剧情线、在迷宫中探索的紧张感——这些体验塑造了我对游戏的审美。
工作后,我成了一名 Python 开发者。某天深夜,一个念头突然冒了出来:能不能用 Python 标准库,从零写一个完整的 RPG?不用 Pygame,不用 Unity,不用任何第三方依赖——就用 Python 自带的 tkinter,能做成什么样?
这个项目的核心信条:零外部依赖,只靠 Python 标准库。不是做不到,而是想看看 Python 标准库的边界在哪里。
项目名称叫 WordRpg,中文名"我之传说"——既是"文字 RPG"的谐音,也寓意每个玩家在游戏中书写自己的传说。
0 外部依赖 | 2,400 源码行数 | 17 Python 文件 |
7 互联地图 | 12+3 敌人与 Boss | 5 主线任务 |
💡 技术选型:Python 3.14 + tkinter + dataclasses + random。仅此而已,四个标准库模块撑起一个完整 RPG。
✦ ✦ ✦
二、沉浸式剧情体验
RPG 的灵魂在于故事。WordRpg 设计了 7 个性格鲜明的 NPC,每个 NPC 拥有多段对话——根据玩家当前的任务进度动态切换。这种上下文感知的对话系统让游戏世界显得真实而生动。
▲ NPC对话界面—对话内容随任务进展动态变化
村庄中的 NPC 各司其职:老村长指引剧情方向、公会会长发布任务、铁匠和药铺提供装备与补给。当玩家完成某个任务后再去对话,NPC 的台词会自然过渡到下一阶段,营造出"世界在变化"的沉浸感。
对话状态机设计:每个 NPC 持有一组按 quest state 索引的对话段(unavailable / active / done / completed),引擎自动匹配当前最合适的对话。只需一份数据字典,无需 if-else 硬编码。
✦ ✦ ✦
三、游戏架构深度解析
分层设计——逻辑与界面彻底分离
很多人写 GUI 程序容易犯的一个错误是把界面代码和业务逻辑混在一起。WordRpg 从第一天起就严格执行分层架构:
wordRpg/
├── main.py
├── config.py
│
├── game/
│ ├── engine.py
│ ├── player.py
│ ├── combat.py
│ ├── classes.py
│ ├── enemy.py
│ ├── quest.py
│ ├── shop.py
│ ├── npc.py
│ ├── map_.py
│ └── map_manager.py
│
├── ui/
│ ├── main_window.py
│ ├── title_screen.py
│ ├── game_view.py
│ ├── combat_view.py
│ ├── dialog_view.py
│ └── shop_view.py
│
└── assets/maps/
关键约束:game/ 目录下不允许出现任何 import tkinter。这意味着整个游戏逻辑是纯 Python 数据结构,可以用单元测试直接验证,也可以在将来替换为其他 GUI 框架。
main.py——7 行代码的启动哲学
整个应用的入口只有极少的有效代码,却完成了从窗口创建到游戏启动的全部编排:
main.py (完整文件 20 行)
def main():
root = MainWindow()
engine = Engine(root)
root.engine = engine
engine.build_scenes()
root.switch_to("title")
root.mainloop()
这里运用了依赖注入和组合模式:Engine 不负责创建 MainWindow,MainWindow 也不负责创建 Engine——它们在 main() 中完成组装,彼此通过接口协作。
场景切换——60 行实现完整路由
游戏包含 5 个场景(标题、主游戏、战斗、对话、商店),切换逻辑精炼在一个方法中。每个场景是 tk.Frame 子类,拥有统一的 on_enter() 生命周期钩子。切换时引擎销毁当前场景、挂载目标场景、触发钩子——就像现代前端框架(Vue/React)的路由机制,只不过我们用的是 1999 年的 tkinter。
config.py——单一配置源的威力
把所有可调参数放进一个文件,是保持项目健康度的关键决策:
| |
|---|
| |
| |
| |
| 全部成长曲线(EXP/HP/MP/ATK/DEF/SPD) |
| |
设计师友好:想调整遇敌率?改一个数字。想换配色?改 17 行颜色值。想调升级曲线?改 5 个常量。一切都集中在一个文件中,无需翻找分散的逻辑代码。
✦ ✦ ✦
四、数据驱动设计——把游戏内容写成配置文件
WordRpg 最核心的设计思想是数据驱动。游戏中的每一个实体——职业、技能、敌人、任务、商品、NPC 对话——都是用 Python 字典或 dataclass 声明的纯粹数据,与运行逻辑完全分离。
- 添加新内容无需改代码:往字典里加一条数据即可
- 内容可以独立维护:策划人员可以独立编辑数据文件
- 逻辑可复用:一套战斗引擎,驱动所有敌人和技能
职业与技能
三个职业各自拥有 3 个专属技能,全部定义在一个字典中。添加新职业只需加一条数据条目。
敌人与 Boss
12 种普通敌人 + 3 个 Boss,属性、等级范围、所属地图全部声明式定义。战斗引擎读取数据结构驱动战斗逻辑。
对话状态机——NPC 的"记忆"
NPC 的对话不再是一成不变的复读机。每个 NPC 的 dialogues 按任务状态分组,随着玩家推进任务,对话自动升级。
数据驱动 vs. 硬编码:如果要用传统 if-else 方式实现同样的 NPC 对话逻辑,7 个 NPC x 5 个对话状态 x 分支条件,代码量将膨胀 3~5 倍。数据字典将复杂度从"控制流"降级为"查表"。
✦ ✦ ✦
五、回合制战斗系统
战斗是 RPG 的核心玩法之一。WordRpg 实现了完整的回合制战斗系统,支持攻击、技能、防御、逃跑四种行动,以及完整的 Buff 管理和技能冷却机制。
▲ 回合制战斗——HP 条、战斗日志、技能选择
战斗流程
玩家回合:
攻击 - 伤害 = max(1, atk - enemy.def/2 +/- random)
技能 - 消耗 MP,触发效果,有冷却
防御 - 获得 defend_up Buff
逃跑 - 概率 = player.spd / (player.spd + enemy.spd)
敌人回合:反击 - 同等伤害公式
回合结算:_tick_buffs() + tick_cooldowns()
3 个职业 x 3 个技能 = 9 种独特技能效果,通过统一的效果标识符调度,添加新技能无需新增分支逻辑。
设计心得:把"效果"抽象为字符串标识("attack_up"、"heal"),战斗引擎只负责解析效果标识并执行对应逻辑。添加一个新技能 = 定义效果标识 + 配数值。不开新分支,不写新函数。
✦ ✦ ✦
六、地图系统——从 txt 文件到开放世界
WordRpg 的地图系统可能是最有趣的部分——每张地图就是一个纯文本文件,用中文字符画出来的。
七大区域
用字符画地图
每张地图是一个 22 行 x 35 列的 .map 文件,使用单中文字符标记瓦片类型。
游戏瓦片图例子:
草地(遇敌率 8%) 墙壁 小路(遇敌率 2%) 传送阵 泉水(满血复活)
店 公 宿 药 老 卫 = NPC 和商店标记
✦ ✦ ✦
渐进解锁与传送网络
游戏世界不是一开始就全部开放的。玩家必须击败特定 Boss 才能解锁下一区域。地图之间通过传送阵实现双向传送,配置由 PORTAL_MAP 字典管理。
✦ ✦ ✦
七、技术实现亮点
数据流:单向绑定 视图层只读 Engine 的状态,所有修改通过 Engine 暴露的方法完成。UI 从不直接修改 Player/MapManager,状态变化可追踪可预测。 |
装备聚合模型 玩家属性 = 基础属性 + 装备加成。total_atk 等属性实时聚合,换装即生效。 |
加权随机遇敌 基于瓦片 encounter_rate + 敌人级别加权随机,不会出现新手区遇 Boss 的情况。 |
纯 Canvas 像素风渲染 tkinter Canvas 逐格绘制,24x24px 每格。颜色字体全部由 config.py 控制,换皮肤只需改颜色常量。 |
✦ ✦ ✦
八、完整游戏内容一览
游戏操作
✦ ✦ ✦
九、扩展与展望
存档/读档系统 使用 json 或 shelve 序列化玩家状态,支持多存档位。 |
单元测试覆盖 game/ 层是纯逻辑,非常适合用 pytest 做全面测试。 |
地图编辑器 可视化拖拽生成 .map 文件,现在全靠手写 :) |
音效与动画 增加音效反馈和战斗动画效果。 |
打包分发 PyInstaller 打包为单文件 exe,让不装 Python 的朋友也能玩。 |
Web 移植 game/ 层不含 GUI 代码,理论上可替换前端为 HTML5 Canvas。 |
✦ ✦ ✦
结语
写 WordRpg 这段经历让我重新认识了一个道理:限制往往是创造力的催化剂。
零外部依赖的约束,迫使我更深入地思考 Python 标准库的能力边界;不用 Pygame 等成熟框架,反而让我对游戏引擎的底层设计有了更深刻的理解——场景管理、状态机、数据驱动、事件路由,这些概念在任何规模的游戏中都是相通的。
如果你对这份代码感兴趣,不妨也试试用纯标准库做个什么项目。你可能会惊讶于 Python 标准库的强大——2400 行代码,零依赖,一个完整的 RPG 世界。
python main.p
如果你喜欢这篇文章,欢迎点赞、在看、转发
也欢迎在评论区交流你的纯 Python 项目经验
下载源码和游戏:搜索公众号 “码来的小朋友 ”,并且输入 “02我之传说”