2026-06-03 17:04:06 +08:00
2026-06-03 17:04:06 +08:00
2026-06-03 17:04:06 +08:00
2026-06-03 17:04:06 +08:00
2026-06-03 17:04:06 +08:00
2026-06-03 17:04:06 +08:00
2026-06-03 17:04:06 +08:00

Mana Pet World C++ 开放世界原型

这是独立的 C++/raylib 开放世界宠物收集游戏。当前方向是 A+B:在现有原型上继续扩展,同时尽量接入原项目 TMX 地图,做成更完整的开放世界宠物收集游戏。它尽量复用 Source of Mana 现成内容:

  • 地图:扫描 assets/maps/**/*.tmx,目前会把能解析的 40 张 TMX 建进世界地图列表。
  • 地图池:参考原项目 MapPool.gd,运行时缓存当前地图和可传送到的相邻 TMX,切图时优先复用缓存并清掉不再相邻的旧地图。
  • 地图拼接:读取原 Tiled assets/maps/tonori/Tonori.world 中的室外地图全局坐标,玩家越过当前地图边界时会按全局坐标尝试切到相邻 TMX;没有写进 .world 的其他 TMX 会放进隔离陈列区,仍会显示在世界总览和地图选择里。
  • 图块:读取 TMX/TSX 引用的 assets/tilesets/...
  • 图层:按 TMX 图层语义绘制,Ground 等普通层在实体下方,Fringe/Over 等遮挡层在玩家、NPC、怪物上方
  • 动态瓦片:读取 TSX 里的 <animation> 帧,水波、火把、发光柱等原素材会按持续时间切帧播放
  • NPC / 怪物出生点:读取 TMX Objects 图层里的 Spawn,NPC 和交互物位置按原 importer 语义使用矩形中心点
  • 保底野外宠物:原 TMX 没有 Monster Spawn 的野外/洞穴/船舱地图会按地图主题补少量可捕捉宠物,城镇、城堡和城墙通道保持无随机宠物
  • 触发范围:读取 Spawn 对象的 trigger_radius,没有显式半径时回退到 assets/presets/entities/*.tres_radius,NPC、线索、钥匙等交互半径会尽量按原 Godot 地图配置生效
  • 初始状态:读取 TMX Spawn 的 state,支持 sit / attack / idle 大小写归一,并优先播放原 sprite preset 中的 Sit*Attack* 动画
  • 脚本交互物:井、线索、钥匙、信件、宝箱等对象即使在 TMX 中标为 Npc,也会优先进入 C++ 的交互/收集系统
  • 地图切换:读取 TMX Warp/Port 对象里的 dest_map/dest_pos_x/dest_pos_y,并兼容部分旧地图使用的 warp + map/dest_x/dest_yauto_warp=false 的传送点会按原 Godot WarpGlobal.gd + Warp.gd 流程先显示入口选项,确认后才切图
  • 室内门触发:参考原 Tiled importer 生成 Warp Spawn 的方式,旧 Artis 室内门会读取 trigger_x/trigger_y,把 32x32 门点扩成原地图配置的触发区域;Tulimshar 旧 Indoor 目标不会再按旧坐标落回室外,而是别名到当前项目已有的 Tulimshar West Chamber TMXArtis 的 001-2-* 室内 TMX 未随当前素材提供时会显示门名和原目标 ID,例如 To Library (001-2-4),而不是反复切图失败
  • 港口:Port 对象会优先使用 sail_pos_x/sail_pos_y 作为上船落点,避免进入 Overworld/Ocean 时落到错误位置
  • 实体贴图和基础数值:优先从 assets/presets/entities/*.tres 解析原项目配置,缺贴图时再读取已有 assets/presets/entities/sprites/*.tscn
  • 实体动画:读取 assets/presets/entities/sprites/*.tscnhframes/vframesIdle*Walk*Sit*Attack* 帧序列,玩家移动会按原项目的上下左右行走帧切换,野外宠物也会使用原怪物帧表播放
  • 交互物显示:宝箱、旧宝箱等会优先使用 assets/presets/entities/*.tresassets/presets/entities/sprites/*.tscn 指向的原实体素材;钥匙等没有直接贴图的对象才回退到原 GUI 图标
  • 物品图标与元数据:扫描 assets/icon/items/...、原 GUI 素材和 assets/presets/cells/items/**/*.tres,背包会读取原 ItemCell 的图标、slot、usable、stackable、weight、description
  • NPC 对话:解析 assets/scripts/**/*.gd 里的 MesChatNarrateChoice("...", OnFunc)、简单函数跳转和 OnStart 里的任务状态分支,选项会按原脚本回调进入对应分支;对话函数中的 AddItem / RemoveItem / SetQuest 会按原物品名和原 ProgressCommons 任务状态生效,并用存档记录已执行奖励和原脚本任务状态
  • 宠物素材:使用 assets/sprites/monsters/...,缺 .tres 映射时会按 Spawn 名称和少量别名从现有怪物贴图中兜底查找
  • 宠物收集:图鉴目录会扫描所有 TMX Monster Spawn 和运行时兜底野怪;战斗捕捉优先加入 6 只出战队伍,队伍满后继续捕捉会送入宠物仓库,进入战斗会登记图鉴“已见”,捕捉成功会登记“已捕获”,这些记录会写入存档
  • UI:优先使用 assets/ui/... 里的窗口、按钮、地图、任务、背包等现成贴图;I 可打开背包/队伍窗口,道具页按宠物游戏语义分为全部、宠物蛋、捕捉、恢复、技能书,并显示原 ItemCell 图标和数量
  • 小地图:参考 sources/gui/Minimap.gd,优先加载 assets/minimap/... 里的原小地图图片,并使用原 orb.png 玩家指示点;M 世界地图面板会显示选中地图的原缩略图预览,还会把 Tonori.world 室外拼接关系和未放置 TMX 的隔离陈列区画成总览;找不到图片时才回退到 C++ 点阵概览
  • 背景音乐:读取 TMX 的 music 属性和原 assets/db/music.json,运行时播放 assets/music/*.ogg 中的对应曲目
  • 音效:扫描 assets/sounds/**/*.ogg,战斗命中、经验/升级、任务推进、宝箱打开等反馈会播放原项目音效
  • 地图氛围:参考原 importer 对 ambient / ambientintensity 的处理,读取 CloudCloudLightLighting 并在世界渲染后、UI 前绘制保守的光照/云层覆盖
  • Ambient 对象:解析 TMX <polyline>,并把 type="Ambient" 的 SandstormPolygon 作为半透明沙尘区域绘制到世界层中
  • 战斗状态条:参考 assets/presets/gui/HealthBar.tscnHP 条使用原 smallbar.png / smallbarprogress.png 九宫格素材,缺素材时才回退纯色条

实现上参考了原 Godot 项目的地图和 UI 结构:

  • sources/world/World.gd:Warp 后移出旧地图实体,再 Spawn 到新地图。
  • sources/map/Map.gd / MapPool.gd:当前地图加载、邻接地图预加载和超过上限后的旧地图清理。
  • addons/tiled_importer/tiled_map_reader.gd:Warp 对象导入为带触发区、目标地图和 auto_warp 的 Spawn。
  • assets/maps/tonori/Tonori.worldTiled 世界文件里的 Tonori 室外地图拼接位置。
  • sources/gui/Minimap.gd:按玩家坐标和地图边界计算小地图位置。
  • sources/system/FileSystem.gd:原项目从 assets/minimap/ 加载对应地图小地图。
  • sources/effects/Lighting.gdaddons/tiled_importer/tiled_map_reader.gd:原项目按地图 ambient 属性加载氛围节点并应用 ambientintensity
  • assets/presets/gui/HealthBar.tscn:原项目小型生命条使用 smallbar.pngsmallbarprogress.png
  • sources/gui/Inventory.gd / CellGrid.gd / CellTile.gd:原项目背包窗口的过滤标签、固定格子、选中框和装备槽布局。
  • assets/scripts/generic/WarpGlobal.gd / Warp.gd / PortGlobal.gd:自动传送直接切图,手动传送转成带目标地图名和取消项的确认交互。
  • assets/scripts/tonori/desertpit/Clue*.gd / ThiefsChest.gd / WaterPond*.gd:蛇坑线索、盗贼宝箱和水池按脚本路径执行轻量奖励逻辑。
  • assets/scripts/tonori/tulimshar/*.gdNPC 对话按 OnStartOnMainChoiceChoice(..., OnFunc) 这类原脚本结构组织。
  • sources/db/Instantiate.gdActorCommons.gdSpawn 的 direction / state 会成为实体初始朝向和默认状态。
  • assets/presets/entities/sprites/*.tscn:复用原项目 Sprite2D 的帧表和 AnimationPlayer 里的 Idle/Walk/Sit/Attack 动画。

构建

依赖:cmake >= 3.20、支持 C++20 的 g++pkg-configraylibpugixml

Ubuntu/Debian 示例:

sudo apt install cmake g++ pkg-config libraylib-dev libpugixml-dev

进入提交的 Loke 项目根目录后构建:

cmake -S . -B build
cmake --build build

提交版不包含 tests/ 目录;主程序和资源审计都由 mana_pet_world 可执行文件完成。

工程结构

  • src/app:程序入口。
  • src/assets:资源路径、原 Godot preset、图片、音乐、音效和动画解析。
  • src/battle:战斗资源、布局和战斗场景。
  • src/contentTonori 道具和内容表。
  • src/core:宠物成长、元素、物种目录和游戏核心数据。
  • src/dialogue:对话脚本、脚本交互和对话效果。
  • src/quest:任务定义和任务状态。
  • src/save:存档读写。
  • src/ui:背包、交互物视觉和 UI 数据模型。
  • src/world:TMX 地图、世界索引、地图池、传送、野怪和地图氛围。
  • assets:运行时所有素材,按 mapstilesetsspritesuiiconmusicsounds 等类型整理。

运行

从项目根目录运行:

./build/mana_pet_world

也可以直接使用项目根目录的脚本自动构建并运行:

./run.sh

也可以显式传入项目根目录:

./build/mana_pet_world .

如果从别的目录启动,则把 . 换成 Loke 文件夹路径。资源会从项目根目录下的 assets/ 读取,不需要复制到系统目录。

只检查原项目 TMX 世界接入情况,不启动游戏窗口。输出会同时列出手动确认传送和缺失室内传送数量,方便排查门口/室内入口:

./build/mana_pet_world --audit-world .

审计输出也会显示 任务目标地图小地图 覆盖数量,用于确认当前 Tonori 任务目标地图和原 minimap 素材覆盖情况。

操作

  • WASD:移动
  • E:靠近 NPC 时对话
  • NPC 对话中 1-9:选择原脚本里的对话选项
  • E:靠近宝箱、钥匙、信件、井、线索等交互物时拾取/触发
  • E:站在需要确认的传送点上时打开入口确认框
  • 入口确认中 1/Enter:进入目标地图
  • 入口确认中 2/Esc:取消传送
  • M:打开/关闭世界地图
  • 世界地图中 W/S 或 ↑/↓:选择地图
  • 世界地图中 PageUp/PageDown:快速滚动
  • 世界地图中 Enter:传送到选中 TMX 地图的默认入口
  • L:打开/关闭任务日志窗口
  • I:打开/关闭背包/宠物队伍窗口
  • 背包中 Tab:切换宠物、仓库、道具、制作页面
  • 背包道具页 Q/E:切换全部、宠物蛋、捕捉、恢复、技能书分类
  • 背包中 WASD 或 ↑/↓/←/→:选择物品格
  • F:朝当前面向方向投掷捕捉符,命中野外宠物后直接尝试捕捉
  • R:前方有野怪时投出首发宠物并进入战斗;没有目标时召唤/收回首发宠物跟随
  • P:打开/关闭宠物图鉴/收藏窗口
  • 图鉴中 WASD 或 ↑/↓/←/→:选择已见或已捕获物种
  • F5:保存当前进度到 savegame.txt
  • F9:读取 savegame.txt
  • 踩到已有地图 Warp 区域:切换到目标 TMX 地图
  • 碰到野外怪物:进入宠物战斗
  • 战斗中 1-4/方向键/鼠标:选择行动;进入道具后先选捕捉符或恢复药,再选择具体道具
  • 战斗中 C:直接打开捕捉符选择列表
  • 战斗中不能使用技能书和宠物蛋,这两类道具只在背包里使用
  • Esc:关闭对话/世界地图或逃跑

当前实现边界

多地图索引会扫描 assets/maps/**/*.tmx,并用每张地图的 properties.name 建立映射。世界地图面板会列出扫描到的地图、Spawn 数、Warp 数和地图尺寸,原 TMX Warp 可正常踩点传送;Tulimshar 里 8 个旧 Indoor 房门会作为别名处理到当前项目已有的 Tulimshar West Chamber,避免旧目标 (71,72) 把玩家送到 Tulimshar 室外画面。assets/maps/tonori 里没有普通民居室内 TMX,这个房间是 Tonori 现有地图中最接近的小型室内;Artis 的 001-2-* 旧室内 ID 也没有找到对应 TMX,会继续在世界图谱统计里按 legacy_numeric_indoor 分类记录为缺失室内传送;--audit-world 会完整打印这些旧门的对象名和落点坐标,方便后续补人工别名,但不阻塞玩家通过世界地图进入其他 TMX。

C++ 渲染层会按摄像机视口裁剪 TMX 瓦片绘制范围,大地图不会每帧遍历整张地图的所有瓦片。Tonori 室外区域还会读取原 .world 拼接坐标,支持从地图边界自然跨入另一个覆盖该全局位置的 TMX。没有原 .world 坐标的主项目 TMX 不会被丢弃,会在世界总览右侧按隔离网格排布,避免和 Tonori 边界误拼接。

HUD 会显示当前 TMX 地图池大小;任务面板标题为 任务,内容来自原项目 ProgressCommons 任务状态、assets/presets/quests/*.tres 任务文本和 C++ 宠物目标运行时。世界地图会把当前目标地图行标成绿色。右侧小地图会显示当前地图内容:蓝色是传送点,黄色是 NPC,红色是野外宠物,绿色是可交互物。世界地图面板右侧会同时显示选中地图的原小地图,以及完整 TMX 总览:原 Tonori.world 坐标保持原样,其他主项目 TMX 以隔离网格补齐,黄色框是当前地图,蓝色框是选中地图,红点是玩家位置。背包窗口会使用原背包背景、选中框、装备槽和物品 PNG 显示当前收集物,并在右侧显示分类、数量和宠物队伍生命条;队伍标题和 HUD 会同时显示总收藏、图鉴种类和仓库数量。宠物图鉴窗口会复用原 icon/glossary.png、背包背景、选择框和现有怪物 sprite,按目录物种汇总未见、已见和已捕获状态,以及已见次数、捕获次数、出战数量、仓库数量、最高等级和出没地图;未见物种会以更淡颜色显示,已见但未捕获的物种会以淡色显示。

任务系统现在复用原项目 ProgressCommons 任务状态和 assets/presets/quests/*.tres 任务文本。NPC 对话里的 SetQuest 会推进同一套 C++ 任务状态;捕捉、战斗、背包、地图访问和 NPC 对话会更新宠物捕捉目标。新游戏不会直接赠送固定宠物,玩家需要找出生点附近最近的 NPC 选择 Lulea、Piou 或 Fluffy 作为初始宠物。Kael 原脚本里的清怪进度在 C++ 运行时改为捕捉试炼:队伍里有初始宠物之外的野外宠物后,回去汇报才会推进到原 OnTaskComplete 奖励分支。C++ 运行时也会把 TMX 里的部分非 NPC/Monster Spawn 作为交互物处理,例如 ChestSandstormMineKeyLetter StashWellSnake Pit Clue。这些交互物会使用现有 GUI 物品/钥匙图标显示,并把获得的物品放入背包。Snake Pit 的五个 Clue*.gd 会拼出 Thief's KeyThiefsChest.gd 会消耗钥匙并给 Scimitar,干净/脏水池会按 WaterPond*.gd 区分处理。

战斗中击败野外宠物会给首发宠物经验,升级后提升最大生命和攻击;捕捉成功会加入出战队伍,队伍满 6 只后会自动送入宠物仓库,也会计入对应物种的清理目标。F5/F9 会保存和恢复当前地图、玩家坐标、出战宠物、仓库宠物、图鉴见过/捕获次数、宠物等级经验、背包物品、已发现地图、已收集交互物、已执行 NPC 对话奖励、原脚本任务状态和任务完成状态。后续可继续把原 Godot 脚本里的任务分支和更细的奖励条件逐步搬到 C++。

当前仍未覆盖 Tiled 的所有高级特性,也没有复刻完整 Godot 联网/账号/服务器系统。

S
Description
No description provided
Readme 55 MiB
Languages
C++ 83.2%
GDScript 16%
CMake 0.6%
Batchfile 0.2%