# 开发步骤文档 > 基于设计文档 v2.0 生成的完整开发指南 > 项目:文字冒险游戏 (uni-app + Vue 3 + Pinia) --- ## 文档说明 本文档将设计文档转化为可执行的开发步骤,每个Phase都包含: - **目标描述**:明确本阶段要实现的功能 - **前置依赖**:需要先完成的条件 - **详细任务清单**:包含具体文件路径和代码要点 - **验收标准**:可测试的功能点 - **预估文件列表**:本阶段将创建/修改的文件 --- ## Phase 1: 基础框架搭建 ### 目标描述 建立项目目录结构,安装核心依赖(Pinia),配置全局样式变量,创建暗色主题基础。 ### 前置依赖 - uni-app项目已创建 - Node.js环境已配置 ### 详细任务清单 #### 1.1 创建目录结构 ``` d:\uniapp\app_test\wwa3\ ├── components/ │ ├── common/ # 通用组件 │ ├── layout/ # 布局组件 │ ├── panels/ # 面板组件 │ └── drawers/ # 抽屉组件 ├── store/ # Pinia状态管理 ├── config/ # 游戏配置文件 ├── utils/ # 工具函数 └── types/ # 类型定义(可选) ``` **操作步骤**: 1. 在项目根目录执行: ```bash mkdir -p components/common components/layout components/panels components/drawers mkdir -p store config utils types ``` #### 1.2 安装 Pinia ```bash npm install pinia ``` **预期输出**:package.json 中增加 `"pinia": "^2.x.x"` #### 1.3 修改 main.js 引入 Pinia **文件路径**:`d:\uniapp\app_test\wwa3\main.js` **代码要点**: ```javascript import { createSSRApp } from 'vue' import { createPinia } from 'pinia' import App from './App.vue' export function createApp() { const app = createSSRApp(App) const pinia = createPinia() app.use(pinia) return { app, pinia } } ``` #### 1.4 修改 uni.scss 添加颜色变量 **文件路径**:`d:\uniapp\app_test\wwa3\uni.scss` **代码要点**: ```scss /* 背景色 */ $bg-primary: #0a0a0f; $bg-secondary: #1a1a2e; $bg-tertiary: #252542; /* 文字色 */ $text-primary: #e0e0e0; $text-secondary: #808080; $text-muted: #4a4a4a; /* 强调色 */ $accent: #4ecdc4; $danger: #ff6b6b; $warning: #ffe66d; $success: #4ade80; /* 品质颜色 */ $quality-trash: #808080; $quality-common: #ffffff; $quality-good: #4ade80; $quality-rare: #60a5fa; $quality-epic: #a855f7; $quality-legend: #f97316; /* 边框色 */ $border-color: #2a2a3e; $border-active: #4ecdc4; ``` #### 1.5 修改 App.vue 添加全局样式 **文件路径**:`d:\uniapp\app_test\wwa3\App.vue` **代码要点**: ```vue ``` ### 验收标准 - [ ] 项目可正常运行(`npm run dev:mp-weixin` 或其他平台) - [ ] 浏览器控制台无错误 - [ ] uni.scss 中的变量可以在组件中正常使用 - [ ] 页面背景显示为深色(#0a0a0f) ### 预估文件列表 | 文件路径 | 操作 | 说明 | |---------|------|------| | `components/common/` | 创建 | 目录 | | `components/layout/` | 创建 | 目录 | | `components/panels/` | 创建 | 目录 | | `components/drawers/` | 创建 | 目录 | | `store/` | 创建 | 目录 | | `config/` | 创建 | 目录 | | `utils/` | 创建 | 目录 | | `main.js` | 修改 | 引入Pinia | | `uni.scss` | 修改 | 添加颜色变量 | | `App.vue` | 修改 | 添加全局样式 | | `package.json` | 修改 | 增加pinia依赖 | --- ## Phase 2: Pinia Store 结构设计 ### 目标描述 创建完整的 Pinia Store 结构,包括玩家状态、游戏状态、以及配置文件的框架。 ### 前置依赖 - Phase 1 完成 - Pinia 已安装 ### 详细任务清单 #### 2.1 创建玩家状态 Store **文件路径**:`d:\uniapp\app_test\wwa3\store\player.js` **代码要点**: ```javascript import { defineStore } from 'pinia' import { ref, computed } from 'vue' export const usePlayerStore = defineStore('player', () => { // 基础属性 const baseStats = ref({ strength: 10, // 力量 agility: 8, // 敏捷 dexterity: 8, // 灵巧 intuition: 10, // 智力 vitality: 10 // 体质(影响HP) }) // 当前资源 const currentStats = ref({ health: 100, maxHealth: 100, stamina: 100, maxStamina: 100, sanity: 100, maxSanity: 100 }) // 主等级 const level = ref({ current: 1, exp: 0, maxExp: 100 }) // 技能 const skills = ref({}) // 装备 const equipment = ref({ weapon: null, armor: null, shield: null, accessory: null }) // 背包 const inventory = ref([]) // 货币(以铜币为单位) const currency = ref({ copper: 0 }) // 当前位置 const currentLocation = ref('camp') // 计算属性:总货币 const totalCurrency = computed(() => { return { gold: Math.floor(currency.value.copper / 10000), silver: Math.floor((currency.value.copper % 10000) / 100), copper: currency.value.copper % 100 } }) // 重置玩家数据 function resetPlayer() { // 重置逻辑 } return { baseStats, currentStats, level, skills, equipment, inventory, currency, totalCurrency, currentLocation, resetPlayer } }) ``` #### 2.2 创建游戏状态 Store **文件路径**:`d:\uniapp\app_test\wwa3\store\game.js` **代码要点**: ```javascript import { defineStore } from 'pinia' import { ref } from 'vue' export const useGameStore = defineStore('game', () => { // 当前标签页 const currentTab = ref('status') // 抽屉状态 const drawerState = ref({ inventory: false, event: false }) // 日志 const logs = ref([]) // 游戏时间 const gameTime = ref({ day: 1, hour: 8, minute: 0, totalMinutes: 480 }) // 战斗状态 const inCombat = ref(false) const combatState = ref(null) // 活动任务 const activeTasks = ref([]) // 负面状态 const negativeStatus = ref([]) // 市场价格 const marketPrices = ref({ lastRefreshDay: 1, prices: {} }) // 添加日志 function addLog(message, type = 'info') { const time = `${String(gameTime.value.hour).padStart(2, '0')}:${String(gameTime.value.minute).padStart(2, '0')}` logs.value.push({ id: Date.now(), time, message, type }) // 限制日志数量 if (logs.value.length > 200) { logs.value.shift() } } // 重置游戏状态 function resetGame() { // 重置逻辑 } return { currentTab, drawerState, logs, gameTime, inCombat, combatState, activeTasks, negativeStatus, marketPrices, addLog, resetGame } }) ``` #### 2.3 创建配置文件框架 **文件路径**:`d:\uniapp\app_test\wwa3\config\constants.js` ```javascript // 游戏数值常量 export const GAME_CONSTANTS = { // 时间流速:现实1秒 = 游戏时间5分钟 TIME_SCALE: 5, // 离线收益时间(小时) OFFLINE_HOURS_BASE: 0.5, OFFLINE_HOURS_AD: 2.5, // 耐力相关 STAMINA_FULL_EFFECT: 50, // 耐力高于此值时无惩罚 STAMINA_EMPTY_PENALTY: 0.5, // 耐力耗尽时效率减半 // 经验倍率 EXP_PARTIAL_SUCCESS: 0.5, // 部分成功时经验比例 // 品质等级 QUALITY_LEVELS: { 1: { name: '垃圾', color: '#808080', range: [0, 49], multiplier: 1.0 }, 2: { name: '普通', color: '#ffffff', range: [50, 99], multiplier: 1.0 }, 3: { name: '优秀', color: '#4ade80', range: [100, 129], multiplier: 1.1 }, 4: { name: '稀有', color: '#60a5fa', range: [130, 159], multiplier: 1.3 }, 5: { name: '史诗', color: '#a855f7', range: [160, 199], multiplier: 1.6 }, 6: { name: '传说', color: '#f97316', range: [200, 250], multiplier: 2.0 } } } ``` #### 2.4 创建技能配置框架 **文件路径**:`d:\uniapp\app_test\wwa3\config\skills.js` ```javascript // 技能配置 export const SKILL_CONFIG = { // 战斗技能 stick_mastery: { id: 'stick_mastery', name: '木棍精通', type: 'combat', category: 'weapon', icon: '', maxLevel: 20, expPerLevel: (level) => level * 100, milestones: { 5: { desc: '所有武器暴击率+2%', effect: { critRate: 2 } }, 10: { desc: '所有武器攻击力+5%', effect: { attackBonus: 5 } }, 15: { desc: '武器熟练度获取速度+20%', effect: { expRate: 1.2 } }, 20: { desc: '所有武器暴击伤害+0.3', effect: { critMult: 0.3 } } }, unlockCondition: null, // 初始解锁 unlockItem: 'wooden_stick' }, reading: { id: 'reading', name: '阅读', type: 'life', category: 'reading', icon: '', maxLevel: 20, expPerLevel: (level) => level * 50, milestones: { 3: { desc: '所有技能经验获取+5%', effect: { globalExpRate: 5 } }, 5: { desc: '阅读速度+50%', effect: { readingSpeed: 1.5 } }, 10: { desc: '完成书籍给予额外主经验+100', effect: { bookExpBonus: 100 } } }, unlockCondition: null, unlockItem: 'old_book' }, night_vision: { id: 'night_vision', name: '夜视', type: 'passive', category: 'environment', icon: '', maxLevel: 10, expPerLevel: (level) => level * 30, milestones: { 5: { desc: '黑暗惩罚-10%', effect: { darkPenaltyReduce: 10 } }, 10: { desc: '黑暗惩罚-25%', effect: { darkPenaltyReduce: 25 } } }, unlockCondition: { location: 'basement' } } } ``` #### 2.5 创建物品配置框架 **文件路径**:`d:\uniapp\app_test\wwa3\config\items.js` ```javascript // 物品配置 export const ITEM_CONFIG = { // 武器 wooden_stick: { id: 'wooden_stick', name: '木棍', type: 'weapon', subtype: 'one_handed', icon: '', baseValue: 10, // 基础价值(铜币) baseDamage: 5, attackSpeed: 1.0, quality: 100, // 默认品质 unlockSkill: 'stick_mastery', description: '一根粗糙的木棍,至少比空手强。' }, // 消耗品 bread: { id: 'bread', name: '面包', type: 'consumable', subtype: 'food', icon: '', baseValue: 10, effect: { stamina: 20 }, description: '普通的面包,可以恢复耐力。', stackable: true, maxStack: 99 }, healing_herb: { id: 'healing_herb', name: '草药', type: 'consumable', subtype: 'medicine', icon: '', baseValue: 15, effect: { health: 15 }, description: '常见的治疗草药,可以恢复生命值。', stackable: true, maxStack: 99 }, // 书籍 old_book: { id: 'old_book', name: '破旧书籍', type: 'book', icon: '', baseValue: 50, readingTime: 60, // 秒 expReward: { reading: 10 }, completionBonus: null, description: '一本破旧的书籍,记录着一些基础知识。', consumable: false // 书籍不消耗 }, // 素材 dog_skin: { id: 'dog_skin', name: '狗皮', type: 'material', icon: '', baseValue: 5, description: '野狗的皮毛,可以用来制作简单装备。', stackable: true, maxStack: 99 }, // 关键道具 basement_key: { id: 'basement_key', name: '地下室钥匙', type: 'key', icon: '', baseValue: 0, description: '一把生锈的钥匙,上面刻着「B」字母。', stackable: false } } ``` #### 2.6 创建区域配置框架 **文件路径**:`d:\uniapp\app_test\wwa3\config\locations.js` ```javascript // 区域配置 export const LOCATION_CONFIG = { camp: { id: 'camp', name: '测试营地', type: 'safe', environment: 'normal', description: '一个临时的幸存者营地,相对安全。', connections: ['market', 'blackmarket', 'wild1'], npcs: ['injured_adventurer'], activities: ['rest', 'talk'] }, market: { id: 'market', name: '测试市场', type: 'safe', environment: 'normal', description: '商人老张在这里摆摊。', connections: ['camp'], npcs: ['merchant_zhang'], activities: ['trade'] }, blackmarket: { id: 'blackmarket', name: '测试黑市', type: 'safe', environment: 'normal', description: '神秘人偶尔会在这里出现。', connections: ['camp'], npcs: ['mysterious_man'], activities: ['trade'] }, wild1: { id: 'wild1', name: '测试野外1', type: 'danger', environment: 'normal', description: '野狗经常出没的区域。', connections: ['camp', 'boss_lair'], enemies: ['wild_dog'], activities: ['explore', 'combat'] }, boss_lair: { id: 'boss_lair', name: '测试Boss巢', type: 'danger', environment: 'normal', description: '强大的野兽盘踞在这里。', connections: ['wild1', 'basement'], enemies: ['test_boss'], unlockCondition: { type: 'kill', target: 'wild_dog', count: 5 }, activities: ['combat'] }, basement: { id: 'basement', name: '地下室', type: 'dungeon', environment: 'dark', description: '黑暗潮湿的地下室,需要照明。', connections: ['boss_lair'], unlockCondition: { type: 'item', item: 'basement_key' }, activities: ['explore', 'read'] } } ``` #### 2.7 创建敌人配置框架 **文件路径**:`d:\uniapp\app_test\wwa3\config\enemies.js` ```javascript // 敌人配置 export const ENEMY_CONFIG = { wild_dog: { id: 'wild_dog', name: '野狗', level: 1, baseStats: { health: 30, attack: 8, defense: 2, speed: 1.0 }, derivedStats: { ap: 10, // 攻击点数 ep: 8 // 闪避点数 }, expReward: 15, drops: [ { item: 'dog_skin', chance: 0.8, min: 1, max: 1 }, { item: 'copper', chance: 1.0, min: 5, max: 15 } ] }, test_boss: { id: 'test_boss', name: '测试Boss', level: 5, baseStats: { health: 200, attack: 25, defense: 10, speed: 0.8 }, derivedStats: { ap: 25, ep: 15 }, expReward: 150, drops: [ { item: 'basement_key', chance: 1.0, min: 1, max: 1 }, { item: 'copper', chance: 1.0, min: 50, max: 100 } ], isBoss: true } } ``` #### 2.8 创建NPC配置框架 **文件路径**:`d:\uniapp\app_test\wwa3\config\npcs.js` ```javascript // NPC配置 export const NPC_CONFIG = { injured_adventurer: { id: 'injured_adventurer', name: '受伤的冒险者', location: 'camp', dialogue: { first: { text: '你终于醒了...这里是营地,暂时安全。外面的世界很危险,带上这根木棍防身吧。', choices: [ { text: '谢谢', next: 'thanks' }, { text: '这是什么地方?', next: 'explain' } ] }, thanks: { text: '小心野狗,它们通常成群出现。如果你能击败五只野狗,或许能找到通往深处的路。', choices: [ { text: '明白了', next: null, action: 'give_stick' } ] }, explain: { text: '这是末世后的世界...具体细节我也记不清了。总之,活下去是第一要务。', choices: [ { text: '我会的', next: 'thanks', action: 'give_stick' } ] } } }, merchant_zhang: { id: 'merchant_zhang', name: '商人老张', location: 'market', dialogue: { first: { text: '欢迎光临!看看有什么需要的?', choices: [ { text: '查看商品', next: null, action: 'open_shop' }, { text: '离开', next: null } ] } } } } ``` ### 验收标准 - [ ] Store 文件可以正常导入 - [ ] usePlayerStore 和 useGameStore 可以在组件中使用 - [ ] 配置文件结构完整,无语法错误 - [ ] 游戏常量可以正确访问 ### 预估文件列表 | 文件路径 | 操作 | 说明 | |---------|------|------| | `store/player.js` | 创建 | 玩家状态Store | | `store/game.js` | 创建 | 游戏状态Store | | `config/constants.js` | 创建 | 游戏常量 | | `config/skills.js` | 创建 | 技能配置 | | `config/items.js` | 创建 | 物品配置 | | `config/locations.js` | 创建 | 区域配置 | | `config/enemies.js` | 创建 | 敌人配置 | | `config/npcs.js` | 创建 | NPC配置 | --- ## Phase 3: 通用UI组件开发 ### 目标描述 开发所有基础UI组件,包括进度条、属性显示、按钮、折叠面板、标签组、底部导航和抽屉。 ### 前置依赖 - Phase 1 完成 - Phase 2 完成(Store可用) ### 详细任务清单 #### 3.1 创建进度条组件 **文件路径**:`d:\uniapp\app_test\wwa3\components\common\ProgressBar.vue` **Props规范**: | Prop | Type | Default | Description | |------|------|---------|-------------| | value | Number | 0 | 当前值 | | max | Number | 100 | 最大值 | | color | String | '$accent' | 进度条颜色 | | showText | Boolean | true | 显示数值文本 | | height | String | '16rpx' | 进度条高度 | **代码要点**: ```vue ``` #### 3.2 创建属性显示行组件 **文件路径**:`d:\uniapp\app_test\wwa3\components\common\StatItem.vue` **Props规范**: | Prop | Type | Default | Description | |------|------|---------|-------------| | label | String | '' | 属性名称 | | value | Number,String | '' | 属性值 | | icon | String | '' | 图标(可选) | | color | String | '$text-primary' | 文字颜色 | **代码要点**: ```vue ``` #### 3.3 创建文字按钮组件 **文件路径**:`d:\uniapp\app_test\wwa3\components\common\TextButton.vue` **Props规范**: | Prop | Type | Default | Description | |------|------|---------|-------------| | text | String | '' | 按钮文字 | | type | String | 'default' | 类型:default/danger/warning | | disabled | Boolean | false | 是否禁用 | **代码要点**: ```vue ``` #### 3.4 创建折叠面板组件 **文件路径**:`d:\uniapp\app_test\wwa3\components\common\Collapse.vue` **Props规范**: | Prop | Type | Default | Description | |------|------|---------|-------------| | title | String | '' | 折叠标题 | | expanded | Boolean | false | 是否展开 | **代码要点**: ```vue ``` #### 3.5 创建筛选标签组组件 **文件路径**:`d:\uniapp\app_test\wwa3\components\common\FilterTabs.vue` **Props规范**: | Prop | Type | Default | Description | |------|------|---------|-------------| | tabs | Array | [] | 标签列表 [{id, label}] | | modelValue | String | '' | 当前选中ID | **代码要点**: ```vue ``` #### 3.6 创建底部导航栏组件 **文件路径**:`d:\uniapp\app_test\wwa3\components\layout\TabBar.vue` **Props规范**: | Prop | Type | Default | Description | |------|------|---------|-------------| | tabs | Array | [] | 导航项 [{id, label, icon}] | | modelValue | String | '' | 当前选中ID | **代码要点**: ```vue ``` #### 3.7 创建右侧抽屉组件 **文件路径**:`d:\uniapp\app_test\wwa3\components\layout\Drawer.vue` **Props规范**: | Prop | Type | Default | Description | |------|------|---------|-------------| | visible | Boolean | false | 是否显示 | | width | String | '600rpx' | 抽屉宽度 | **代码要点**: ```vue ``` ### 验收标准 - [ ] ProgressBar 可以正确显示进度百分比 - [ ] StatItem 可以正确显示属性值 - [ ] TextButton 点击时有反馈 - [ ] Collapse 可以展开/收起 - [ ] FilterTabs 可以切换选中状态 - [ ] TabBar 可以切换并高亮当前项 - [ ] Drawer 可以从右侧滑入,点击遮罩关闭 ### 预估文件列表 | 文件路径 | 操作 | 说明 | |---------|------|------| | `components/common/ProgressBar.vue` | 创建 | 进度条组件 | | `components/common/StatItem.vue` | 创建 | 属性显示组件 | | `components/common/TextButton.vue` | 创建 | 文字按钮组件 | | `components/common/Collapse.vue` | 创建 | 折叠面板组件 | | `components/common/FilterTabs.vue` | 创建 | 筛选标签组件 | | `components/layout/TabBar.vue` | 创建 | 底部导航组件 | | `components/layout/Drawer.vue` | 创建 | 右侧抽屉组件 | --- ## Phase 4: 核心面板组件开发 ### 目标描述 开发三大主面板(状态面板、地图面板、日志面板)和主页面容器。 ### 前置依赖 - Phase 1 完成 - Phase 2 完成(Store可用) - Phase 3 完成(通用组件可用) ### 详细任务清单 #### 4.1 创建状态面板组件 **文件路径**:`d:\uniapp\app_test\wwa3\components\panels\StatusPanel.vue` **功能要点**: - 上区:HP/耐力/精神进度条 - 主属性摘要 - 货币显示 - Collapse展开更多属性 - FilterTabs技能筛选 - 技能列表scroll-view **代码结构**: ```vue ``` #### 4.2 创建地图面板组件 **文件路径**:`d:\uniapp\app_test\wwa3\components\panels\MapPanel.vue` **功能要点**: - 顶部当前位置显示 - 战斗状态区(战斗时显示) - 区域列表scroll-view - 活动按钮组 - 背包按钮唤起抽屉 **代码结构**: ```vue ``` #### 4.3 创建日志面板组件 **文件路径**:`d:\uniapp\app_test\wwa3\components\panels\LogPanel.vue` **功能要点**: - scroll-view显示日志 - 自动滚动到底部 - 不同类型日志的样式区分 **代码结构**: ```vue ``` #### 4.4 重构主页面容器 **文件路径**:`d:\uniapp\app_test\wwa3\pages\index\index.vue` **功能要点**: - 顶部标题栏(显示游戏时间) - v-show 面板切换 - TabBar 集成 - Drawer 集成 **代码结构**: ```vue ``` ### 验收标准 - [ ] 三个Tab可正常切换 - [ ] 状态面板显示基础属性 - [ ] 地图面板显示区域列表 - [ ] 日志面板显示日志消息 - [ ] 顶部显示游戏时间 ### 预估文件列表 | 文件路径 | 操作 | 说明 | |---------|------|------| | `components/panels/StatusPanel.vue` | 创建 | 状态面板 | | `components/panels/MapPanel.vue` | 创建 | 地图面板 | | `components/panels/LogPanel.vue` | 创建 | 日志面板 | | `pages/index/index.vue` | 修改 | 主页面容器 | --- ## Phase 5: 抽屉组件开发 ### 目标描述 开发背包抽屉和事件对话抽屉。 ### 前置依赖 - Phase 1-4 完成 ### 详细任务清单 #### 5.1 创建背包抽屉组件 **文件路径**:`d:\uniapp\app_test\wwa3\components\drawers\InventoryDrawer.vue` **功能要点**: - FilterTabs 分类筛选 - 物品列表显示 - 物品详情弹窗 - 使用/装备/出售操作 **代码结构**: ```vue ``` #### 5.2 创建事件对话抽屉组件 **文件路径**:`d:\uniapp\app_test\wwa3\components\drawers\EventDrawer.vue` **功能要点**: - NPC信息区(名称、头像) - 对话文本区(支持滚动) - 选项按钮区 **代码结构**: ```vue ``` ### 验收标准 - [ ] 地图面板「背包」按钮可打开抽屉 - [ ] 抽屉动画流畅 - [ ] 物品列表正常显示 - [ ] 事件对话可显示 ### 预估文件列表 | 文件路径 | 操作 | 说明 | |---------|------|------| | `components/drawers/InventoryDrawer.vue` | 创建 | 背包抽屉 | | `components/drawers/EventDrawer.vue` | 创建 | 事件抽屉 | --- ## Phase 6: 核心系统实现 ### 目标描述 实现技能系统、战斗系统、物品系统、任务系统、事件系统、环境系统的核心逻辑。 ### 前置依赖 - Phase 1-5 完成 ### 详细任务清单 #### 6.1 技能系统工具 **文件路径**:`d:\uniapp\app_test\wwa3\utils\skillSystem.js` **功能要点**: - 经验添加 - 升级判定 - 里程碑检测 - 父技能同步 **代码结构**: ```javascript import { SKILL_CONFIG } from '@/config/skills.js' /** * 添加技能经验 * @param {Object} playerStore - 玩家Store * @param {String} skillId - 技能ID * @param {Number} amount - 经验值 */ export function addSkillExp(playerStore, skillId, amount) { const skill = playerStore.skills[skillId] if (!skill || !skill.unlocked) return skill.exp += amount // 检查升级 const config = SKILL_CONFIG[skillId] while (skill.level < config.maxLevel && skill.exp >= getNextLevelExp(skillId, skill.level)) { levelUpSkill(playerStore, skillId) } } /** * 获取下一级所需经验 */ export function getNextLevelExp(skillId, currentLevel) { const config = SKILL_CONFIG[skillId] return config.expPerLevel(currentLevel + 1) } /** * 技能升级 */ export function levelUpSkill(playerStore, skillId) { const skill = playerStore.skills[skillId] const config = SKILL_CONFIG[skillId] skill.level++ skill.exp -= config.expPerLevel(skill.level) // 检查里程碑奖励 if (config.milestones[skill.level]) { applyMilestoneBonus(playerStore, skillId, skill.level) } // 更新父技能等级 updateParentSkill(playerStore, skillId) } /** * 应用里程碑奖励 */ export function applyMilestoneBonus(playerStore, skillId, level) { const config = SKILL_CONFIG[skillId] const milestone = config.milestones[level] if (!milestone) return // 应用全局奖励 // TODO: 实现奖励效果 } /** * 更新父技能等级 */ export function updateParentSkill(playerStore, skillId) { // TODO: 父技能逻辑 } /** * 解锁技能 */ export function unlockSkill(playerStore, skillId) { if (!playerStore.skills[skillId]) { playerStore.skills[skillId] = { level: 0, exp: 0, unlocked: true } } } ``` #### 6.2 战斗系统工具 **文件路径**:`d:\uniapp\app_test\wwa3\utils\combatSystem.js` **功能要点**: - AP/EP命中计算 - 三层防御(闪避/护盾/防御) - 战斗tick处理 - 战斗日志输出 **代码结构**: ```javascript /** * 计算AP(攻击点数) * AP = 灵巧 + 智力*0.2 + 技能加成 + 装备加成 + 姿态加成 - 敌人数惩罚 */ export function calculateAP(player, stance, enemyCount, environment) { let ap = player.baseStats.dexterity + player.baseStats.intuition * 0.2 // 姿态加成 if (stance === 'attack') ap *= 1.1 if (stance === 'defense') ap *= 0.9 // 环境惩罚 if (environment === 'dark') ap *= 0.8 // 多敌人惩罚 ap *= (1 - Math.min(0.3, (enemyCount - 1) * 0.05)) return Math.floor(ap) } /** * 计算EP(闪避点数) * EP = 敏捷 + 智力*0.2 + 技能加成 + 装备加成 + 姿态加成 - 环境惩罚 */ export function calculateEP(player, stance, environment) { let ep = player.baseStats.agility + player.baseStats.intuition * 0.2 // 姿态加成 if (stance === 'defense') ep *= 1.2 if (stance === 'attack') ep *= 0.8 // 环境惩罚 if (environment === 'dark') ep *= 0.8 return Math.floor(ep) } /** * 计算命中概率 * @param {Number} ap - 攻击点数 * @param {Number} ep - 闪避点数 * @returns {Number} 命中概率 (0-1) */ export function calculateHitRate(ap, ep) { const ratio = ap / (ep + 1) // 非线性计算 if (ratio >= 5) return 0.98 if (ratio >= 2) return 0.8 if (ratio >= 1) return 0.5 if (ratio >= 0.5) return 0.24 return 0.05 } /** * 处理攻击 * @returns {Object} { hit, damage, crit, evaded, blocked } */ export function processAttack(attacker, defender, stance, environment) { const ap = calculateAP(attacker, stance, 1, environment) const ep = calculateEP(defender, 'balance', environment) const hitRate = calculateHitRate(ap, ep) // 闪避判定 const roll = Math.random() if (roll > hitRate) { return { hit: false, evaded: true, damage: 0 } } // 计算基础伤害 let damage = attacker.baseStats.attack || 0 // 暴击判定 const critRate = 0.05 + (attacker.baseStats.dexterity / 100) const crit = Math.random() < critRate if (crit) { damage *= 1.5 } // 防御力减免 const defense = defender.baseStats.defense || 0 damage = Math.max(1, damage - defense) damage = Math.max(damage * 0.1, damage) // 最小10%伤害 return { hit: true, damage: Math.floor(damage), crit, evaded: false } } /** * 处理战斗tick */ export function combatTick(gameStore, playerStore, combatState) { // 玩家攻击 const playerAttack = processAttack( playerStore, combatState.enemy, combatState.stance, combatState.environment ) if (playerAttack.hit) { combatState.enemy.hp -= playerAttack.damage const log = playerAttack.crit ? '暴击!' : '' gameStore.addLog(`你攻击${combatState.enemy.name},造成${playerAttack.damage}点伤害 ${log}`, 'combat') } else { gameStore.addLog(`你攻击${combatState.enemy.name},未命中`, 'combat') } // 检查敌人是否死亡 if (combatState.enemy.hp <= 0) { return { victory: true } } // 敌人攻击 const enemyAttack = processAttack( combatState.enemy, playerStore, 'balance', combatState.environment ) if (enemyAttack.hit) { playerStore.currentStats.health -= enemyAttack.damage gameStore.addLog(`${combatState.enemy.name}攻击你,造成${enemyAttack.damage}点伤害`, 'combat') } else { gameStore.addLog(`${combatState.enemy.name}攻击你,你闪避了!`, 'combat') } // 检查玩家是否死亡 if (playerStore.currentStats.health <= 0) { return { defeat: true } } return { continue: true } } ``` #### 6.3 物品系统工具 **文件路径**:`d:\uniapp\app_test\wwa3\utils\itemSystem.js` **功能要点**: - 使用物品 - 装备/卸下 - 品质属性计算 **代码结构**: ```javascript import { ITEM_CONFIG } from '@/config/items.js' import { GAME_CONSTANTS } from '@/config/constants.js' /** * 计算装备品质后的属性 */ export function calculateItemStats(itemId, quality = 100) { const config = ITEM_CONFIG[itemId] if (!config) return null const qualityLevel = getQualityLevel(quality) const qualityMultiplier = qualityLevel.multiplier const stats = { ...config } // 应用品质百分比 if (config.baseDamage) { stats.finalDamage = Math.floor(config.baseDamage * (quality / 100) * qualityMultiplier) } if (config.baseDefense) { stats.finalDefense = Math.floor(config.baseDefense * (quality / 100) * qualityMultiplier) } // 计算价值 stats.finalValue = Math.floor(config.baseValue * (quality / 100) * qualityMultiplier) stats.quality = quality stats.qualityLevel = qualityLevel return stats } /** * 获取品质等级 */ export function getQualityLevel(quality) { for (const [level, data] of Object.entries(GAME_CONSTANTS.QUALITY_LEVELS)) { if (quality >= data.range[0] && quality <= data.range[1]) { return { level: parseInt(level), ...data } } } return GAME_CONSTANTS.QUALITY_LEVELS[1] } /** * 使用物品 */ export function useItem(playerStore, gameStore, itemId) { const config = ITEM_CONFIG[itemId] if (!config) return { success: false, message: '物品不存在' } // 消耗品 if (config.type === 'consumable') { const item = playerStore.inventory.find(i => i.id === itemId) if (!item || item.count <= 0) { return { success: false, message: '物品数量不足' } } // 应用效果 if (config.effect.health) { playerStore.currentStats.health = Math.min( playerStore.currentStats.maxHealth, playerStore.currentStats.health + config.effect.health ) } if (config.effect.stamina) { playerStore.currentStats.stamina = Math.min( playerStore.currentStats.maxStamina, playerStore.currentStats.stamina + config.effect.stamina ) } // 消耗物品 item.count-- if (item.count <= 0) { playerStore.inventory = playerStore.inventory.filter(i => i.id !== itemId) } gameStore.addLog(`使用了 ${config.name}`, 'info') return { success: true } } return { success: false, message: '该物品无法使用' } } /** * 装备物品 */ export function equipItem(playerStore, gameStore, itemId) { const config = ITEM_CONFIG[itemId] if (!config) return { success: false } const item = playerStore.inventory.find(i => i.id === itemId && i.equipped === false) if (!item) return { success: false, message: '物品不存在或已装备' } // 卸下当前装备 const slot = config.type === 'weapon' ? 'weapon' : config.type if (playerStore.equipment[slot]) { unequipItem(playerStore, gameStore, slot) } // 装备新物品 playerStore.equipment[slot] = item item.equipped = true gameStore.addLog(`装备了 ${config.name}`, 'info') return { success: true } } /** * 卸下装备 */ export function unequipItem(playerStore, gameStore, slot) { const equipped = playerStore.equipment[slot] if (!equipped) return { success: false } equipped.equipped = false playerStore.equipment[slot] = null gameStore.addLog(`卸下了 ${equipped.name}`, 'info') return { success: true } } ``` #### 6.4 任务系统工具 **文件路径**:`d:\uniapp\app_test\wwa3\utils\taskSystem.js` **功能要点**: - 挂机任务管理 - 互斥检测 **代码结构**: ```javascript /** * 开始任务 */ export function startTask(gameStore, playerStore, taskType, taskData) { // 检查互斥 if (!canStartTask(gameStore, playerStore, taskType)) { return { success: false, message: '任务互斥' } } const task = { id: Date.now(), type: taskType, data: taskData, startTime: Date.now() } gameStore.activeTasks.push(task) return { success: true } } /** * 检查是否可以开始任务 */ export function canStartTask(gameStore, playerStore, taskType) { // 战斗互斥 if (gameStore.inCombat && taskType !== 'combat') { return false } // 检查是否已有相同类型任务 const existingTask = gameStore.activeTasks.find(t => t.type === taskType) if (existingTask) { return false } return true } /** * 结束任务 */ export function endTask(gameStore, taskId) { gameStore.activeTasks = gameStore.activeTasks.filter(t => t.id !== taskId) } /** * 处理任务tick(每秒调用) */ export function processTaskTick(gameStore, playerStore) { for (const task of gameStore.activeTasks) { switch (task.type) { case 'reading': processReadingTask(gameStore, playerStore, task) break case 'resting': processRestingTask(gameStore, playerStore, task) break } } } /** * 处理阅读任务 */ export function processReadingTask(gameStore, playerStore, task) { // 阅读获得经验 // TODO: 实现 } /** * 处理休息任务 */ export function processRestingTask(gameStore, playerStore, task) { // 恢复耐力 if (playerStore.currentStats.stamina < playerStore.currentStats.maxStamina) { playerStore.currentStats.stamina = Math.min( playerStore.currentStats.maxStamina, playerStore.currentStats.stamina + 5 ) } } ``` #### 6.5 事件系统工具 **文件路径**:`d:\uniapp\app_test\wwa3\utils\eventSystem.js` **功能要点**: - 事件触发检测 - 对话管理 **代码结构**: ```javascript import { NPC_CONFIG } from '@/config/npcs.js' import { EVENT_CONFIG } from '@/config/events.js' /** * 检查并触发事件 */ export function checkAndTriggerEvent(gameStore, playerStore) { // 检查首次进入事件 if (!playerStore.flags?.introTriggered) { triggerEvent(gameStore, 'intro') playerStore.flags = playerStore.flags || {} playerStore.flags.introTriggered = true return } // 检查位置事件 // TODO: 实现 } /** * 触发事件 */ export function triggerEvent(gameStore, eventId) { const config = EVENT_CONFIG[eventId] if (!config) return gameStore.currentEvent = { id: eventId, ...config } gameStore.drawerState.event = true } /** * 处理NPC对话 */ export function startNPCDialogue(gameStore, npcId, dialogueKey = 'first') { const npc = NPC_CONFIG[npcId] if (!npc) return const dialogue = npc.dialogue[dialogueKey] if (!dialogue) return gameStore.currentEvent = { type: 'dialogue', npc: npc, text: dialogue.text, choices: dialogue.choices, currentDialogue: dialogueKey } gameStore.drawerState.event = true } /** * 处理对话选择 */ export function handleDialogueChoice(gameStore, playerStore, choice) { if (choice.action) { processDialogueAction(gameStore, playerStore, choice.action) } if (choice.next === null) { gameStore.drawerState.event = false } else if (choice.next) { startNPCDialogue(gameStore, gameStore.currentEvent.npc.id, choice.next) } } /** * 处理对话动作 */ export function processDialogueAction(gameStore, playerStore, action) { switch (action) { case 'give_stick': // 给予木棍 // TODO: 实现 break case 'open_shop': // 打开商店 gameStore.drawerState.event = false // TODO: 打开商店抽屉 break } } ``` #### 6.6 环境系统工具 **文件路径**:`d:\uniapp\app_test\wwa3\utils\environmentSystem.js` **功能要点**: - 环境惩罚计算 - 被动技能获取 **代码结构**: ```javascript /** * 获取当前环境惩罚 */ export function getEnvironmentPenalty(locationId, playerStore) { // TODO: 从配置读取 const penalties = { basement: { ap: 0.8, ep: 0.8, reading: 0.5 } } return penalties[locationId] || { ap: 1, ep: 1, reading: 1 } } /** * 处理环境被动经验 */ export function processEnvironmentExp(gameStore, playerStore, locationId) { // 黑暗区域获得夜视经验 if (locationId === 'basement') { // 检查是否已解锁夜视 if (playerStore.skills.night_vision?.unlocked) { // 添加夜视经验 // TODO: 调用技能系统 } } } ``` ### 验收标准 - [ ] 技能可以添加经验并升级 - [ ] 战斗可以计算命中/闪避 - [ ] 物品可以使用和装备 - [ ] 任务可以开始和结束 - [ ] 事件可以触发和选择 ### 预估文件列表 | 文件路径 | 操作 | 说明 | |---------|------|------| | `utils/skillSystem.js` | 创建 | 技能系统 | | `utils/combatSystem.js` | 创建 | 战斗系统 | | `utils/itemSystem.js` | 创建 | 物品系统 | | `utils/taskSystem.js` | 创建 | 任务系统 | | `utils/eventSystem.js` | 创建 | 事件系统 | | `utils/environmentSystem.js` | 创建 | 环境系统 | | `config/events.js` | 创建 | 事件配置 | --- ## Phase 7: 游戏循环和存档系统 ### 目标描述 实现游戏主循环、数据持久化、离线收益计算。 ### 前置依赖 - Phase 1-6 完成 ### 详细任务清单 #### 7.1 游戏主循环 **文件路径**:`d:\uniapp\app_test\wwa3\utils\gameLoop.js` **功能要点**: - 每秒tick - 时间推进 - 战斗处理 - 任务经验 - 耐力恢复 **代码结构**: ```javascript import { GAME_CONSTANTS } from '@/config/constants.js' import { combatTick } from './combatSystem.js' import { processTaskTick } from './taskSystem.js' import { processEnvironmentExp } from './environmentSystem.js' let gameTimer = null let lastTickTime = 0 /** * 启动游戏循环 */ export function startGameLoop(gameStore, playerStore) { if (gameTimer) { stopGameLoop() } lastTickTime = Date.now() gameTimer = setInterval(() => { gameTick(gameStore, playerStore) }, 1000) // 每秒执行一次 } /** * 停止游戏循环 */ export function stopGameLoop() { if (gameTimer) { clearInterval(gameTimer) gameTimer = null } } /** * 游戏主tick */ export function gameTick(gameStore, playerStore) { // 更新游戏时间 updateGameTime(gameStore) // 处理战斗 if (gameStore.inCombat) { const result = combatTick(gameStore, playerStore, gameStore.combatState) if (result.victory) { handleCombatVictory(gameStore, playerStore) } else if (result.defeat) { handleCombatDefeat(gameStore, playerStore) } } // 处理任务 processTaskTick(gameStore, playerStore) // 处理环境被动经验 processEnvironmentExp(gameStore, playerStore, playerStore.currentLocation) // 自动保存(每30秒) if (gameStore.gameTime.totalMinutes % 30 === 0) { saveGame(gameStore, playerStore) } } /** * 更新游戏时间 * 现实1秒 = 游戏时间5分钟 */ export function updateGameTime(gameStore) { const time = gameStore.gameTime time.totalMinutes += GAME_CONSTANTS.TIME_SCALE // 计算天时分 const totalDayMinutes = time.totalMinutes % (24 * 60) // 一天内的分钟数 time.day = Math.floor(time.totalMinutes / (24 * 60)) + 1 time.hour = Math.floor(totalDayMinutes / 60) time.minute = totalDayMinutes % 60 // 刷新市场价格(每天0点) if (time.hour === 0 && time.minute === 0) { refreshMarketPrices(gameStore) } } /** * 处理战斗胜利 */ export function handleCombatVictory(gameStore, playerStore) { const combat = gameStore.combatState const enemy = combat.enemy gameStore.addLog(`${enemy.name} 被击败了!`, 'system') // 获得经验 playerStore.level.exp += enemy.expReward // 处理掉落 for (const drop of enemy.drops) { if (Math.random() < drop.chance) { if (drop.item === 'copper') { const amount = Math.floor(Math.random() * (drop.max - drop.min + 1)) + drop.min playerStore.currency.copper += amount gameStore.addLog(`获得 ${amount} 铜币`, 'reward') } else { // 添加物品到背包 // TODO: 实现 } } } // 结束战斗 gameStore.inCombat = false gameStore.combatState = null } /** * 处理战斗失败 */ export function handleCombatDefeat(gameStore, playerStore) { gameStore.addLog('你被击败了...', 'danger') // 返回营地 playerStore.currentLocation = 'camp' playerStore.currentStats.health = Math.floor(playerStore.currentStats.maxHealth * 0.5) gameStore.inCombat = false gameStore.combatState = null } /** * 刷新市场价格 */ export function refreshMarketPrices(gameStore) { gameStore.marketPrices.lastRefreshDay = gameStore.gameTime.day // TODO: 实现价格随机波动 } ``` #### 7.2 存储系统 **文件路径**:`d:\uniapp\app_test\wwa3\utils\storage.js` **功能要点**: - saveGame() - loadGame() - resetGame() - logs[]不持久化 **代码结构**: ```javascript const SAVE_KEY = 'game_save_v1' /** * 保存游戏 */ export function saveGame(gameStore, playerStore) { try { const saveData = { version: 1, timestamp: Date.now(), // 玩家数据 player: { baseStats: playerStore.baseStats, currentStats: playerStore.currentStats, level: playerStore.level, skills: playerStore.skills, equipment: playerStore.equipment, inventory: playerStore.inventory, currency: playerStore.currency, currentLocation: playerStore.currentLocation }, // 游戏数据 game: { gameTime: gameStore.gameTime, marketPrices: gameStore.marketPrices, // 不保存logs和临时状态 } } uni.setStorageSync(SAVE_KEY, JSON.stringify(saveData)) return { success: true } } catch (e) { console.error('保存失败', e) return { success: false, error: e.message } } } /** * 加载游戏 */ export function loadGame() { try { const saveDataStr = uni.getStorageSync(SAVE_KEY) if (!saveDataStr) { return { success: false, exists: false } } const saveData = JSON.parse(saveDataStr) // 检查版本兼容性 if (saveData.version !== 1) { return { success: false, error: '存档版本不兼容' } } return { success: true, data: saveData } } catch (e) { console.error('加载失败', e) return { success: false, error: e.message } } } /** * 重置游戏 */ export function resetGame(gameStore, playerStore) { uni.removeStorageSync(SAVE_KEY) // 重置Store playerStore.resetPlayer() gameStore.resetGame() return { success: true } } /** * 应用存档数据到Store */ export function applySaveData(gameStore, playerStore, saveData) { // 应用玩家数据 Object.assign(playerStore.baseStats, saveData.player.baseStats) Object.assign(playerStore.currentStats, saveData.player.currentStats) Object.assign(playerStore.level, saveData.player.level) playerStore.skills = saveData.player.skills playerStore.equipment = saveData.player.equipment playerStore.inventory = saveData.player.inventory playerStore.currency = saveData.player.currency playerStore.currentLocation = saveData.player.currentLocation // 应用游戏数据 gameStore.gameTime = saveData.game.gameTime gameStore.marketPrices = saveData.game.marketPrices } ``` #### 7.3 修改App.vue **文件路径**:`d:\uniapp\app_test\wwa3\App.vue` **功能要点**: - onLaunch: 加载存档 + 启动循环 - onHide: 自动保存 **代码修改**: ```vue ``` ### 验收标准 - [ ] 游戏时间正常流逝 - [ ] 关闭后重开数据保留 - [ ] 战斗可自动进行 - [ ] 存档可以正常读取和保存 ### 预估文件列表 | 文件路径 | 操作 | 说明 | |---------|------|------| | `utils/gameLoop.js` | 创建 | 游戏主循环 | | `utils/storage.js` | 创建 | 存储系统 | | `App.vue` | 修改 | 集成存档和循环 | --- ## Phase 8: 测试验证 ### 目标描述 按测试清单验证所有功能,确保数值平衡性。 ### 前置依赖 - Phase 1-7 完成 ### 详细任务清单 #### 8.1 新游戏流程测试 **测试步骤**: 1. 清除存档(uni.removeStorageSync) 2. 重新启动应用 3. 验证初始剧情触发 **预期结果**: - [ ] 初始属性正确(力量10、敏捷8等) - [ ] 货币为0 - [ ] EventDrawer自动弹出,显示初始对话 - [ ] 对话完成后获得木棍 #### 8.2 交易系统测试 **测试步骤**: 1. 前往测试市场 2. 查看商品列表 3. 购买面包 4. 出售素材 **预期结果**: - [ ] 商人售价约为200%基础价格 - [ ] 商人收购价约为30%基础价格 - [ ] 购买后货币正确扣除 - [ ] 物品正确加入背包 #### 8.3 战斗系统测试 **测试步骤**: 1. 前往测试野外1 2. 触发战斗 3. 观察AP/EP计算 4. 切换战斗姿态 **预期结果**: - [ ] 战斗自动进行 - [ ] 命中概率符合AP/EP比例 - [ ] 姿态切换影响战斗 - [ ] 击败敌人获得经验和物品 - [ ] HP、耐力正确消耗 #### 8.4 技能系统测试 **测试步骤**: 1. 进行战斗获取武器技能经验 2. 阅读书籍获取阅读经验 3. 升级技能 4. 检查里程碑奖励 **预期结果**: - [ ] 技能经验正常积累 - [ ] 技能可以升级 - [ ] 里程碑奖励正确应用 - [ ] 技能上限受玩家等级限制 #### 8.5 环境系统测试 **测试步骤**: 1. 解锁地下室 2. 进入地下室 3. 检查黑暗惩罚 4. 观察夜视经验获取 **预期结果**: - [ ] 黑暗区域AP/EP降低20% - [ ] 阅读效率降低50% - [ ] 夜视技能被动获得经验 - [ ] 夜视技能升级后惩罚减少 #### 8.6 Boss战测试 **测试步骤**: 1. 击杀5只野狗 2. 解锁Boss巢 3. 挑战测试Boss 4. 击败Boss **预期结果**: - [ ] 击杀5只野狗后解锁Boss巢 - [ ] Boss战难度较高 - [ ] 击败Boss掉落地下室钥匙 - [ ] 解锁地下室区域 #### 8.7 存档系统测试 **测试步骤**: 1. 进行游戏操作(获得物品、提升技能) 2. 关闭应用 3. 重新打开 **预期结果**: - [ ] 数据正确保留 - [ ] 货币数量一致 - [ ] 技能等级一致 - [ ] 物品数量一致 #### 8.8 数值平衡测试 **测试重点**: **AP/EP计算验证**: | 场景 | 预期AP | 预期EP | 预期命中率 | |------|--------|--------|------------| | 初始属性 vs 野狗 | ~10 | ~8 | ~50% | | 攻击姿态 | +10% | -20% | ~60% | | 防御姿态 | -10% | +20% | ~40% | | 黑暗环境 | -20% | -20% | ~50%(同比例) | **技能升级速度验证**: | 技能 | 升到Lv.1 | 升到Lv.5 | 升到Lv.10 | |------|----------|----------|-----------| | 木棍精通 | ~10次攻击 | ~150次攻击 | ~600次攻击 | | 阅读 | 1本书 | 5本书 | 15本书 | **经济平衡验证**: | 场景 | 预期收益 | 预期耗时 | |------|----------|----------| | 击杀野狗 | 5-15铜币 | ~10秒 | | 出售狗皮 | 3.5铜币(70%) | - | | 购买面包 | -20铜币 | - | ### 验收标准 - [ ] 所有测试项通过 - [ ] 无严重BUG - [ ] 数值基本平衡 --- ## 附录:文件清单总览 ### 目录结构 ``` d:\uniapp\app_test\wwa3\ ├── components/ │ ��── common/ │ │ ├── ProgressBar.vue # 进度条 │ │ ├── StatItem.vue # 属性显示 │ │ ├── TextButton.vue # 文字按钮 │ │ ├── Collapse.vue # 折叠面板 │ │ └── FilterTabs.vue # 筛选标签 │ ├── layout/ │ │ ├── TabBar.vue # 底部导航 │ │ └── Drawer.vue # 抽屉容器 │ ├── panels/ │ │ ├── StatusPanel.vue # 状态面板 │ │ ├── MapPanel.vue # 地图面板 │ │ └── LogPanel.vue # 日志面板 │ └── drawers/ │ ├── InventoryDrawer.vue # 背包抽屉 │ └── EventDrawer.vue # 事件抽屉 ├── store/ │ ├── player.js # 玩家状态 │ └── game.js # 游戏状态 ├── config/ │ ├── constants.js # 游戏常量 │ ├── skills.js # 技能配置 │ ├── items.js # 物品配置 │ ├── locations.js # 区域配置 │ ├── enemies.js # 敌人配置 │ ├── npcs.js # NPC配置 │ └── events.js # 事件配置 ├── utils/ │ ├── skillSystem.js # 技能系统 │ ├── combatSystem.js # 战斗系统 │ ├── itemSystem.js # 物品系统 │ ├── taskSystem.js # 任务系统 │ ├── eventSystem.js # 事件系统 │ ├── environmentSystem.js # 环境系统 │ ├── gameLoop.js # 游戏循环 │ └── storage.js # 存储系统 ├── pages/ │ └── index/ │ └── index.vue # 主页面 ├── App.vue # 应用入口 ├── main.js # 主入口 ├── uni.scss # 全局样式 └── package.json # 依赖配置 ``` ### 创建文件总计 | 类别 | 文件数量 | |------|----------| | 组件 | 12 | | Store | 2 | | 配置 | 7 | | 工具 | 8 | | 页面 | 1 | | 其他 | 3 | | **总计** | **33** | --- ## 开发时间估算 | Phase | 预估时间 | 说明 | |-------|----------|------| | Phase 1 | 2小时 | 基础配置 | | Phase 2 | 3小时 | Store + 配置 | | Phase 3 | 4小时 | 7个组件 | | Phase 4 | 4小时 | 3个面板 + 主页面 | | Phase 5 | 2小时 | 2个抽屉 | | Phase 6 | 6小时 | 核心系统 | | Phase 7 | 3小时 | 循环 + 存储 | | Phase 8 | 4小时 | 测试修复 | | **总计** | **28小时** | 约3.5个工作日 | --- ## 注意事项 ### 开发规范 1. 所有组件使用 `