今天突然有一个想法,突然想做一个文字恐怖游戏,然后游戏的走向和结局都需要根据玩家的想法控制。有不同的胜利解决和死亡解决。这里我配合使用vibe coding的一些工具来使用WordFunney 基于命令行的文字生存恐怖游戏。 采用 数据驱动 模式——所有剧情、选项、状态变化均从 JSON 配置文件读取,引擎代码不包含任何硬编码内容。
核心设计原则
| |
|---|
| 数据驱动 | |
| 单向流程 | |
| 纯标准库 | 零外部依赖(仅json , dataclasses , os) |
| 节点类型化 | |
项目结构
wordfunney/│├── story.json # 剧情配置(唯一数据入口)├── main.py # 启动入口│├── engine/│ ├── __init__.py│ ├── models.py # 数据模型 dataclass│ ├── loader.py # JSON 加载与校验│ ├── state.py # 游戏状态管理 & effect 解析│ └── core.py # 游戏主循环 & 节点派发│└── renderer/ ├── __init__.py └── cli.py # CLI 渲染(文本输出 + 输入处理)
模块职责
| |
| 初始化 GameState、加载 story、启动 engine |
| StoryNode, Option, GameState dataclass |
engine/loader.py | 读 story.json,校验 next_id 引用完整性 → dict[str, StoryNode] |
engine/state.py | StateManager 管理 health/sanity/flags/inventory 解析 condition & effect |
engine/core.py | GameEngine:主循环 run(),按 node.type 派发处理器 |
renderer/cli.py | CliRenderer:show_text(),how_options(), prompt(), show_status() |
数据模型
@dataclassclass GameState: health: int = 100 # 生命值,归零即死亡 sanity: int = 100 # 理智值,归零即疯狂 inventory: list[str] # 道具列表 flags: dict[str, bool] # 剧情标记 current_node: str # 当前所在节点 ID visited: set[str] # 已访问节点@dataclassclass StoryNode: id: str # 唯一标识 text: str # 展示文本 type: str # normal / win / lose / check options: list[Option] # 可选分支 effects: dict | None # 进入节点时触发@dataclassclass Option: text: str # 选项文本 next_id: str # 指向的下一个节点 condition: dict | None # 显示条件 effects: dict | None # 选择后触发
节点类型
| |
|---|
| |
| |
| |
| 无玩家交互,根据 condition 自动跳转 true_next / false_next |
{ "meta": { "title": "深渊回响", "start_node": "start" }, "nodes": [ { "id": "start", "text": "你从一张冰冷的铁床上醒来。\n四周是无尽的黑暗...", "type": "normal", "effects": { "sanity": -5 }, "options": [ { "text": "摸索四周的墙壁", "next_id": "explore_wall" }, { "text": "大声呼救", "next_id": "shout", "effects": { "sanity": -10 } } ] } ]}
condition 语法
{"stat":{"health":{">":0}}}{"flag":{"name":"knows_truth","value":true}}{"inventory":{"has":"flashlight"}}{"visited":"cellar_dark"}
effects 语法
{"health":-15,"sanity":10}{"inventory":{"add":"rusty_key"}}{"inventory":{"remove":"flashlight"}}{"flags":{"knows_truth":true}}
游戏主循环
main.py
state = GameState() nodes = load_story("story.json") engine = GameEngine(state, nodes) engine.run()
engine/core.py
while running: node = nodes[state.current_node] state_manager.apply(node.effects) if game_over := check_game_over(): handle_ending(game_over) break match node.type: "normal" → handle_normal(node) "win" → handle_win(node) "lose" → handle_lose(node) "check" → handle_check(node) state.visited.add(node.id)
渲染器设计
show_intro(meta) → 显示游戏标题show_text(text) → 打印文本 + 分隔线show_status(state) → 显示 [生命: 100 ❤ | 理智: 95 🌙 | 道具: 手电筒]show_options(options) → 打印编号列表prompt(options) → 读取 1-n 或 q 退出,返回 Optionshow_ending(type) → 显示游戏结束画面
数据统计
| |
|---|
| 总节点数 | 54 |
| |
| |
| |
| |
| 5(flashlight / rusty_key / scalpel / battery / keycard) |
| |
| |
道具一览
扩展指南
| |
|---|
| |
| models.py 加类型 → core.py加 handler |
| |
| |
| |
| |
如果想要修改游戏内容,或者改为自己的剧情创作,可以直接修改story.json,这里面是游戏所有关卡和选项,这是我给每位小伙伴做的拓展,后续可能会开发一个story的工具,让创作更加方便。

喜欢本片文章就收藏起来吧!!!感谢每位读者!!!小码会经常更新有趣的文章!!

