【python】我用python的tkinter开发了一个文字冒险rpg回合制游戏--我之传说

WordRpg --- 文字角色扮演游戏技术介绍

github源码下载:源码链接

游戏展示

商店和对话移动角色 "我" 进行探险,会触发回合制战斗

概述

WordRpg 是一款基于 Python 3.14 标准库开发的桌面端文字 RPG 游戏,采用 tkinter 构建图形界面,无任何外部依赖。游戏以中文叙事、像素风格字符地图为核心体验,融合了回合制战斗、任务系统、装备系统、NPC 交互等经典 RPG 要素。

技术栈

技术 用途
Python 3.14 运行时环境
tkinter GUI 框架,所有视图均为 tk.Frame 子类
dataclasses 数据建模(角色、技能、敌人、任务、商品等)
random 遇敌判定、伤害浮动、逃跑概率、随机敌人选取

项目架构

分层设计

复制代码
main.py                         ← 入口
  └─ Engine                     ← 中枢调度(场景、战斗、对话、商店)
       ├─ game/                 ← 纯逻辑层(无 GUI 导入)
       │   ├─ player.py         ← 玩家模型 / 背包 / 任务进度 / 升级
       │   ├─ combat.py         ← 回合制战斗引擎
       │   ├─ classes.py        ← 职业 & 技能数据
       │   ├─ enemy.py          ← 敌人 & Boss 模板 / 随机生成
       │   ├─ quest.py          ← 任务数据 & 目标
       │   ├─ shop.py           ← 商店数据
       │   ├─ npc.py            ← NPC 数据 & 对话状态机
       │   ├─ map_.py           ← 单张地图(瓦片网格、可达性、传送门)
       │   └─ map_manager.py    ← 多地图管理(传送、解锁、遇敌、Boss)
       └─ ui/                   ← 表现层(tkinter 视图)
           ├─ main_window.py    ← 根窗口 + 场景切换
           ├─ title_screen.py   ← 标题 & 职业选择
           ├─ game_view.py      ← 主游戏画面(地图 + 信息面板)
           ├─ combat_view.py    ← 战斗 UI
           ├─ dialog_view.py    ← NPC 对话 & 任务 UI
           └─ shop_view.py      ← 商店 UI

场景切换(Scene-Based MVC)

引擎维护一个 scenes 字典,存储所有场景帧。MainWindow.switch_to() 负责销毁当前场景并展示目标场景,每个场景在切入时触发 on_enter() 生命周期钩子。

复制代码
TitleScreen  →  GameView  ↔  CombatView
                          ↔  DialogView
                          ↔  ShopView

核心设计模式

1. 数据驱动

游戏内容以声明式字典和 dataclass 定义,与逻辑解耦:

  • 职业属性、技能效果 → CLASS_DATAclasses.py
  • 敌人属性、掉落 → ENEMY_TEMPLATES / BOSS_TEMPLATESenemy.py
  • 任务链条件与奖励 → QUEST_DATAquest.py
  • 商店商品 → SHOP_DATAshop.py
  • NPC 对话状态机 → NPC_DATAnpc.py
  • 瓦片属性(行走性、颜色、遇敌率)→ TILE_PROPERTIESconfig.py

2. 任务状态机

每个任务有四个状态:unavailable → active → done → completed。NPC 对话根据当前任务状态动态切换文本,并控制任务接受/交付的交互逻辑。

3. Buff / 冷却系统

战斗中使用字典维护玩家与敌人的临时状态:

  • player_buffs / enemy_buffs:存储 Buff 名称与剩余回合数,每回合递减
  • skill_cooldowns:跟踪技能剩余冷却回合数,每回合递减

4. 装备聚合

玩家属性(攻击、防御等)为其基础属性与装备加成的总和,通过 total_atktotal_def 等属性实时计算。

地图系统

  • 7 张地图:村庄、绿地、森林、沙漠、湖泊、冰原、遗迹
  • 自定义 .map 格式:22行 × 35列,单中文字符表示瓦片类型
  • 瓦片属性:草地(可行走/遇敌)、树木(不可行走)、门(传送)、泉(恢复)等
  • 双向传送 :通过 PORTAL_MAP 字典实现跨地图传送
  • 渐进解锁 :通过 MAP_UNLOCKS 控制,击败特定 Boss 后解锁新区

战斗系统

复制代码
玩家回合:
  攻击    → 伤害 = max(1, atk - enemy.def/2 + random(-2~+2))
  技能    → 消耗 MP,触发特效(治疗、加攻、加防、闪避、减速),有冷却
  防御    → 本回合获得 defend_up Buff
  逃跑    → 概率 = player.spd / (player.spd + enemy.spd)

敌人回合:
  反击    → 同等伤害公式

入口文件 main.py

python 复制代码
import sys, os
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))

from config import *
from ui.main_window import MainWindow
from game.engine import Engine

def main():
    root = MainWindow()
    engine = Engine(root)
    root.engine = engine
    engine.build_scenes()
    root.switch_to("title")
    root.mainloop()

if __name__ == "__main__":
    main()

main.py 是整个应用的启动入口,职责纯粹:

  • 路径注入 :将项目根目录加入 sys.path,确保后续 import 正确解析
  • 对象组装 :创建 MainWindow(tkinter 根窗口)→ 创建 Engine(逻辑中枢)→ 双向绑定 → 构建所有场景
  • 启动循环:默认切换到标题画面,进入 tkinter 事件主循环

整个初始化链仅 7 行有效代码,体现了清晰的依赖注入与组合模式。

全局配置 config.py

python 复制代码
# 窗口
WINDOW_WIDTH = 1100
WINDOW_HEIGHT = 720
TITLE = "文字RPG - 我之传说"

# 瓦片属性字典------数据驱动的核心
TILE_PROPERTIES = {
    "·": {"walkable": True,  "color": "#7ec850", "name": "草地", "encounter_rate": 0.08},
    "木": {"walkable": False, "color": "#2d6a2d", "name": "树木"},
    # ... 共 11 种瓦片
}

# 升级公式
EXP_PER_LEVEL = 30
HP_PER_LEVEL = 5
MP_PER_LEVEL = 3
ATK_PER_LEVEL = 2
# ...

# 字体
FONT_TITLE = ("Microsoft YaHei", 28, "bold")

config.py 是项目的单一配置源,所有可调参数集中管理:

配置类别 内容
窗口 宽高、标题
地图 瓦片尺寸(24px)、行列数(35×22)、地图目录
颜色 17 种主题色(深色背景 + 高亮点缀)
瓦片属性 11 种瓦片的行走性、颜色、中文名、遇敌率
升级公式 每级所需经验、HP/MP/ATK/DEF/SPD 成长值
字体 5 级字号,统一使用微软雅黑

这种设计使得调整游戏平衡性(遇敌率、成长曲线)或更换视觉主题只需修改 config.py,无需触碰任何逻辑代码。

地图文件目录 assets/maps/

复制代码
assets/maps/
├── village.map    # 村庄(安全区 / 枢纽)
├── greenland.map  # 绿地(Lv1-2 初级区域)
├── forest.map     # 森林(Lv3 中级区域)
├── desert.map     # 沙漠(Lv4-5 中级区域)
├── lake.map       # 湖畔(Lv4-5 中级区域)
├── ice.map        # 冰原(Lv6-8 高级区域)
└── ruin.map       # 遗迹(Lv8-12 最终区域)

每张地图为 22 行 × 35 列 的纯文本文件,使用单中文字符标记瓦片类型:

复制代码
墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙
墙·································墙
墙·································墙
墙··墙店墙····墙公墙····墙宿墙····墙药墙···泉···墙
墙··墙墙墙····墙墙墙····墙墙墙····墙墙墙·······墙
墙·································墙
墙···············路················墙
墙···············路················墙
墙···老······卫·····路路路路路路路路路门·······墙
墙···············路················墙
墙············门路路路·················墙
墙·································墙
墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙墙
  • · 草地(可行走,有遇敌率)
  • 墙壁(不可行走,边界)
  • 小路(可行走,低遇敌率)
  • 传送阵(跨地图传送)
  • 泉水(可行走,触发 HP/MP 全恢复)
  • 等环境瓦片
  • 地图中嵌入的 宿 等字符对应 NPC 和商店标记,由 map_manager.py 解析为交互点

地图加载流程:GameMap.load() 按行读取文件 → 构建字符二维数组 → 记录 NPC/传送门位置 → 由 MapManager 统一管理切换与解锁逻辑。

数据流

复制代码
用户输入(键盘/按钮)
       ↓
    Engine 调度
       ↓
   game/ 逻辑层  →  更新状态(Player / MapManager / Combat)
       ↓
   ui/ 视图层    →  重新渲染

视图层只读状态,通过 Engine 暴露的方法修改逻辑,实现表现与逻辑的分离。

运行方式

bash 复制代码
python main.py

无需安装任何依赖,Python 3.14+ 环境即可运行。

项目规模

  • 源码文件:17 个 .py 文件
  • 地图文件:7 个 .map 文件
  • 源码行数:约 2,400 行
  • 外部依赖:0

特色亮点

  • 纯标准库:零外部依赖,开箱即用
  • 全中文:界面、叙事、数据全部中文化
  • 像素风字符界面:利用 tkinter Canvas 绘制 tile-based 地图
  • 紧凑的场景管理:60 行实现完整的场景路由与生命周期
  • 丰富的游戏内容:3 职业 × 3 技能、12 种敌人 + 3 个 Boss、5 个主线性任务、7 个 NPC、3 个商店

扩展方向

  • 引入 pyproject.toml 与虚拟环境管理
  • 添加单元测试(unittest / pytest
  • 增加存档/读档功能(json / shelve
  • 扩展地图编辑器或支持更多瓦片类型
  • 添加音效与动画增强