# CubeCity 新手开发指南 🚀 欢迎加入 CubeCity 开发团队!这是一款基于 Three.js 和 Vue 3 的 2.5D 卡通城市模拟经营游戏。本指南将帮助你快速上手项目开发,成为一名优秀的 CubeCity 开发者。 --- ## 📋 目录 1. [项目概述](#项目概述) 2. [技术栈介绍](#技术栈介绍) 3. [开发环境搭建](#开发环境搭建) 4. [项目结构解析](#项目结构解析) 5. [核心概念理解](#核心概念理解) 6. [开发规范](#开发规范) 7. [常见开发任务](#常见开发任务) 8. [调试与测试](#调试与测试) 9. [部署与发布](#部署与发布) 10. [常见问题解答](#常见问题解答) --- ## 🎯 项目概述 ### 项目简介 CubeCity 是一款 2.5D 卡通风格的城市建设模拟游戏,玩家通过放置、管理各类建筑,经营并扩展属于自己的城市。 ### 核心特性 - 🏗️ **3D 城市建设**:基于 Three.js 的 3D 场景渲染 - 🎮 **模拟经营**:RCI & ESG 多维建筑体系 - 💾 **本地存储**:自动保存游戏进度 - 📱 **响应式设计**:支持桌面端和移动端 - 🌍 **国际化**:支持中英文切换 - 🎨 **现代化 UI**:基于 Vue 3 + Tailwind CSS ### 开发目标 - 提供流畅的 3D 城市建设体验 - 实现复杂的建筑相互作用系统 - 构建可扩展的游戏架构 - 保持代码的可维护性和可读性 --- ## 🛠️ 技术栈介绍 ### 核心技术 | 技术 | 版本 | 用途 | |------|------|------| | **Vue 3** | 3.x | 前端框架,负责 UI 层 | | **Three.js** | 0.172.0 | 3D 图形渲染引擎 | | **Vite** | 5.4.0 | 构建工具和开发服务器 | | **Pinia** | 3.0.3 | 状态管理 | | **Tailwind CSS** | 3.4.9 | CSS 框架 | ### 辅助技术 | 技术 | 用途 | |------|------| | **GSAP** | 动画库,用于 UI 和 3D 动画 | | **Cannon.js** | 物理引擎 | | **Mitt** | 事件总线,用于组件通信 | | **Vue I18n** | 国际化支持 | | **Tweakpane** | 调试面板 | ### 开发工具 | 工具 | 用途 | |------|------| | **ESLint** | 代码质量检查 | | **Prettier** | 代码格式化 | | **Playwright** | 端到端测试 | | **Husky** | Git hooks | | **Commitlint** | 提交信息规范 | --- ## 🚀 开发环境搭建 ### 1. 环境要求 - **Node.js**: >= 18.0.0 - **包管理器**: pnpm (推荐) 或 npm - **编辑器**: VS Code (推荐) - **浏览器**: Chrome/Edge (支持 WebGL) ### 2. 克隆项目 ```bash git clone https://github.com/your-username/CubeCity.git cd CubeCity ``` ### 3. 安装依赖 ```bash # 使用 pnpm (推荐) pnpm install # 或使用 npm npm install ``` ### 4. 启动开发服务器 ```bash pnpm dev # 或 npm run dev ``` 访问 `http://localhost:5173` 查看项目。 ### 5. 其他常用命令 ```bash # 构建生产版本 pnpm build # 预览生产版本 pnpm preview # 代码检查 pnpm lint # 代码格式化 pnpm lint:fix # 运行测试 pnpm test:chrome ``` --- ## 📁 项目结构解析 ``` CubeCity/ ├── docs/ # 项目文档 │ ├── PRD.md # 产品需求文档 │ ├── TD.md # 技术设计文档 │ └── 新手指南.md # 玩家指南 ├── public/ # 静态资源 │ ├── models/ # 3D 模型文件 │ ├── textures/ # 纹理文件 │ └── fonts/ # 字体文件 ├── src/ # 源代码 │ ├── components/ # Vue 组件 │ ├── js/ # Three.js 相关代码 │ │ ├── components/ # 3D 组件 │ │ ├── tools/ # 工具类 │ │ ├── utils/ # 工具函数 │ │ └── world/ # 世界管理 │ ├── shaders/ # GLSL 着色器 │ ├── stores/ # Pinia 状态管理 │ ├── assets/ # 资源文件 │ └── css/ # 样式文件 ├── tests/ # 测试文件 ├── package.json # 项目配置 └── vite.config.js # Vite 配置 ``` ### 核心文件说明 #### Vue 层 (src/components/) - `App.vue`: 主应用组件 - `GameCanvas.vue`: 游戏画布组件 - `BuildingSidebar.vue`: 建筑选择面板 - `BuildingDetail.vue`: 建筑详情面板 #### Three.js 层 (src/js/) - `experience.js`: 核心体验类,单例模式 - `camera.js`: 相机管理 - `renderer.js`: 渲染器管理 - `world.js`: 世界管理 - `components/`: 3D 组件 - `tiles/`: 地皮系统 - `buildings/`: 建筑系统 - `effects/`: 特效系统 #### 状态管理 (src/stores/) - `useGameState.js`: 游戏状态管理 --- ## 🧠 核心概念理解 ### 1. 架构设计模式 #### 单例模式 (Experience) ```javascript // src/js/experience.js export default class Experience { constructor() { if (Experience.instance) { return Experience.instance } Experience.instance = this // 初始化核心组件 this.scene = new THREE.Scene() this.camera = new Camera() this.renderer = new Renderer() // ... } } ``` #### 组件化设计 - **Vue 组件**: 负责 UI 交互和状态展示 - **Three.js 组件**: 负责 3D 场景渲染和逻辑 - **状态管理**: Pinia 统一管理游戏状态 ### 2. 通信机制 #### Vue ↔ Three.js 通信 ```javascript // 使用 mitt 事件总线 import emitter from './utils/event-bus.js' // Vue 组件发送事件 emitter.emit('ui:building-selected', { type: 'house' }) // Three.js 组件监听事件 emitter.on('ui:building-selected', (data) => { // 处理建筑选择逻辑 }) ``` #### 状态同步 ```javascript // 使用 Pinia 进行状态管理 import { useGameState } from '@/stores/useGameState.js' const gameState = useGameState() gameState.setMode('build') gameState.setSelectedBuilding({ type: 'house', level: 1 }) ``` ### 3. 资源管理 #### 资源加载 ```javascript // src/js/sources.js - 定义资源 export default [ { name: 'house', type: 'gltfModel', path: 'models/house_level1.glb' } ] // 使用资源 const houseModel = this.experience.resources.items.house ``` #### 着色器管理 ```javascript // src/shaders/ - GLSL 着色器 import fragmentShader from '@/shaders/fragment.glsl' import vertexShader from '@/shaders/vertex.glsl' const material = new THREE.ShaderMaterial({ vertexShader, fragmentShader, uniforms: { time: { value: 0 } } }) ``` --- ## 📝 开发规范 ### 1. 代码风格 #### JavaScript/TypeScript - 使用 ES6+ 语法 - 类名使用大驼峰命名 - 方法名使用小驼峰命名 - 常量使用大写下划线 - 必须添加中文注释 #### Vue 组件 - 组件名使用大驼峰命名 - 文件名与组件名一致 - 使用 Composition API - 样式使用 Tailwind CSS #### Three.js 组件 ```javascript export default class YourComponent { constructor() { // 获取 Experience 单例实例 this.experience = new Experience() // 获取需要的核心组件 this.scene = this.experience.scene this.resources = this.experience.resources this.debug = this.experience.debug // 初始化组件 this.init() } init() { // 组件初始化逻辑 } update() { // 更新逻辑 } resize() { // 响应式调整 } } ``` ### 2. 文件组织 #### 组件文件结构 ``` src/js/components/ ├── tiles/ # 地皮相关组件 ├── buildings/ # 建筑相关组件 ├── effects/ # 特效组件 └── ui/ # UI 相关组件 ``` #### 工具文件结构 ``` src/js/utils/ ├── debug.js # 调试工具 ├── event-bus.js # 事件总线 ├── resources.js # 资源管理 └── sizes.js # 尺寸管理 ``` ### 3. 命名规范 #### 文件命名 - 组件文件: `PascalCase.js` - 工具文件: `kebab-case.js` - 着色器文件: `kebab-case.glsl` #### 变量命名 ```javascript // 常量 const BUILDING_TYPES = ['house', 'factory', 'shop'] // 类名 class BuildingFactory {} // 方法名 function createBuilding() {} // 私有属性 this._privateProperty = value ``` ### 4. 注释规范 #### 中文注释要求 ```javascript /** * 建筑工厂类 * 负责创建和管理不同类型的建筑实例 */ export default class BuildingFactory { /** * 创建建筑实例 * @param {string} type - 建筑类型 * @param {number} level - 建筑等级 * @returns {Building} 建筑实例 */ createBuilding(type, level) { // 根据类型创建对应建筑 switch (type) { case 'house': return new House(level) case 'factory': return new Factory(level) default: throw new Error(`未知建筑类型: ${type}`) } } } ``` --- ## 🔧 常见开发任务 ### 1. 添加新建筑类型 #### 步骤 1: 定义建筑数据 ```javascript // src/constants/constants.js export const BUILDING_DATA = { newBuilding: { name: { zh: '新建筑', en: 'New Building' }, type: 'newBuilding', icon: '🏢', category: 'commercial', levels: { 1: { displayName: { zh: '基础新建筑', en: 'Basic New Building' }, cost: 500, coinOutput: 25, powerUsage: 10, pollution: 2, upgradeCost: 1000, nextLevel: 2, visible: true } } } } ``` #### 步骤 2: 创建 3D 组件 ```javascript // src/js/components/buildings/new-building.js import Building from './building.js' export default class NewBuilding extends Building { constructor(level = 1) { super('newBuilding', level) // 加载模型 this.model = this.resources.items.newBuilding this.scene.add(this.model) } // 重写特定方法 getCoinOutput() { return this.buildingData.coinOutput * this.level } } ``` #### 步骤 3: 添加模型资源 ```javascript // src/js/sources.js export default [ // ... 其他资源 { name: 'newBuilding', type: 'gltfModel', path: 'models/new-building.glb' } ] ``` #### 步骤 4: 更新 UI 组件 ```vue 🏢 {{ t('newBuilding.name') }} {{ getBuildingCost('newBuilding') }} ``` ### 2. 实现建筑相互作用 #### 步骤 1: 定义相互作用规则 ```javascript // src/constants/building-interactions.js export const BUILDING_INTERACTIONS = { house: { park: { distance: 1, effect: 'maxPopulation', multiplier: 0.1, // +10% description: '相邻公园增加人口容量' }, factory: { distance: 1, effect: 'maxPopulation', multiplier: -0.15, // -15% description: '相邻工厂减少人口容量' } } } ``` #### 步骤 2: 实现相互作用逻辑 ```javascript // src/js/components/buildings/building.js export default class Building { calculateInteractions() { const neighbors = this.getNeighborTiles() let bonus = 1.0 neighbors.forEach((tile) => { if (tile.building) { const interaction = BUILDING_INTERACTIONS[this.type]?.[tile.building.type] if (interaction) { bonus += interaction.multiplier } } }) return Math.max(0.5, bonus) // 最低 50% 效率 } } ``` ### 3. 添加新特效 #### 步骤 1: 创建着色器 ```glsl // src/shaders/effects/new-effect/fragment.glsl uniform float time; uniform vec3 color; varying vec2 vUv; void main() { vec2 uv = vUv; float wave = sin(uv.x * 10.0 + time) * 0.5 + 0.5; gl_FragColor = vec4(color * wave, 1.0); } ``` #### 步骤 2: 创建特效组件 ```javascript // src/js/components/effects/new-effect.js import fragmentShader from '@/shaders/effects/new-effect/fragment.glsl' import vertexShader from '@/shaders/effects/new-effect/vertex.glsl' export default class NewEffect { constructor() { this.material = new THREE.ShaderMaterial({ vertexShader, fragmentShader, uniforms: { time: { value: 0 }, color: { value: new THREE.Color(0x00FF00) } }, transparent: true }) } update() { this.material.uniforms.time.value += 0.01 } } ``` ### 4. 添加新 UI 功能 #### 步骤 1: 创建 Vue 组件 ```vue {{ title }} ``` #### 步骤 2: 集成到主应用 ```vue ``` --- ## 🐛 调试与测试 ### 1. 调试工具 #### 浏览器开发者工具 - **Console**: 查看日志和错误 - **Network**: 检查资源加载 - **Performance**: 分析性能问题 - **Application**: 查看本地存储 #### Three.js 调试 ```javascript // 启用调试面板 if (this.debug.active) { this.debugFolder = this.debug.ui.addFolder({ title: '组件名称', expanded: true }) this.debugFolder.addBinding(this.object, 'position', { label: '位置' }) } ``` #### Vue DevTools - 安装 Vue DevTools 浏览器扩展 - 查看组件状态和事件 - 调试 Pinia 状态管理 ### 2. 性能优化 #### 3D 场景优化 ```javascript // 使用对象池 class ObjectPool { constructor(createFn) { this.pool = [] this.createFn = createFn } get() { return this.pool.pop() || this.createFn() } release(obj) { this.pool.push(obj) } } // 使用 LOD (Level of Detail) const lod = new THREE.LOD() lod.addLevel(highDetailMesh, 0) lod.addLevel(mediumDetailMesh, 50) lod.addLevel(lowDetailMesh, 100) ``` #### 内存管理 ```javascript // 正确释放资源 dispose() { // 释放几何体 this.geometry.dispose() // 释放材质 this.material.dispose() // 从场景中移除 this.scene.remove(this.mesh) // 清空纹理 this.texture.dispose() } ``` ### 3. 测试 #### 单元测试 ```javascript import BuildingCard from '@/components/BuildingCard.vue' import { mount } from '@vue/test-utils' // tests/components.test.js import { describe, expect, it } from 'vitest' describe('BuildingCard', () => { it('显示正确的建筑信息', () => { const wrapper = mount(BuildingCard, { props: { building: { name: '住宅', cost: 300 } } }) expect(wrapper.text()).toContain('住宅') expect(wrapper.text()).toContain('300') }) }) ``` #### 端到端测试 ```javascript // tests/e2e/game.test.js import { expect, test } from '@playwright/test' test('建筑放置功能', async ({ page }) => { await page.goto('/') // 选择建筑 await page.click('[data-testid="building-house"]') // 点击地皮放置 await page.click('[data-testid="tile-0-0"]') // 验证建筑已放置 await expect(page.locator('[data-testid="building-instance"]')).toBeVisible() }) ``` --- ## 🚀 部署与发布 ### 1. 构建生产版本 ```bash # 构建 pnpm build # 预览构建结果 pnpm preview ``` ### 2. 部署配置 ```javascript // vite.config.js export default defineConfig({ build: { outDir: 'dist', assetsDir: 'assets', sourcemap: false, minify: 'terser', rollupOptions: { output: { manualChunks: { three: ['three'], vendor: ['vue', 'pinia'] } } } } }) ``` ### 3. 性能优化 - 启用 Gzip 压缩 - 使用 CDN 加速 - 配置缓存策略 - 优化图片和模型资源 --- ## ❓ 常见问题解答 ### Q1: 如何快速理解项目架构? A: 建议按以下顺序学习: 1. 阅读 `docs/PRD.md` 了解产品需求 2. 查看 `docs/TD.md` 理解技术设计 3. 从 `src/js/experience.js` 开始,理解核心架构 4. 查看 `src/components/App.vue` 了解 UI 结构 ### Q2: 如何添加新的建筑类型? A: 参考 [添加新建筑类型](#1-添加新建筑类型) 章节,需要: 1. 在 `constants.js` 中定义建筑数据 2. 创建对应的 3D 组件 3. 添加模型资源 4. 更新 UI 组件 ### Q3: 如何调试 3D 场景问题? A: 使用以下方法: 1. 启用调试面板查看对象属性 2. 使用浏览器开发者工具的 Console 3. 检查 Three.js 的 WebGL 错误 4. 使用 `console.log` 输出关键数据 ### Q4: 如何处理性能问题? A: 常见优化方法: 1. 使用对象池减少内存分配 2. 实现 LOD 系统 3. 合理使用纹理压缩 4. 优化渲染循环 ### Q5: 如何实现国际化? A: 使用 Vue I18n: 1. 在 `src/assets/i18n/` 中添加语言文件 2. 使用 `$t()` 函数包装文本 3. 通过 `useI18n()` 切换语言 ### Q6: 如何提交代码? A: 遵循项目规范: 1. 使用 `git add` 暂存更改 2. 使用 `git commit` 提交,遵循 commitizen 规范 3. 提交信息格式:`feat: 添加新建筑类型 (#issue)` --- ## 📚 学习资源 ### 官方文档 - [Vue 3 官方文档](https://vuejs.org/) - [Three.js 官方文档](https://threejs.org/docs/) - [Vite 官方文档](https://vitejs.dev/) - [Pinia 官方文档](https://pinia.vuejs.org/) ### 推荐阅读 - [Three.js 最佳实践](https://discoverthreejs.com/) - [Vue 3 组合式 API](https://vuejs.org/guide/extras/composition-api-faq.html) - [WebGL 基础](https://webglfundamentals.org/) ### 社区资源 - [Three.js 论坛](https://discourse.threejs.org/) - [Vue.js 社区](https://forum.vuejs.org/) - [GitHub Issues](https://github.com/your-username/CubeCity/issues) --- ## 🤝 贡献指南 ### 开发流程 1. Fork 项目到个人仓库 2. 创建功能分支:`git checkout -b feature/new-feature` 3. 提交更改:`git commit -m "feat: 添加新功能"` 4. 推送到分支:`git push origin feature/new-feature` 5. 创建 Pull Request ### 代码审查 - 所有代码变更需要经过审查 - 确保代码符合项目规范 - 添加必要的测试用例 - 更新相关文档 ### 问题反馈 - 使用 GitHub Issues 报告 Bug - 提供详细的复现步骤 - 包含环境信息和错误日志 - 建议解决方案 --- ## 📞 联系方式 - **项目地址**: [GitHub Repository](https://github.com/your-username/CubeCity) - **问题反馈**: [GitHub Issues](https://github.com/your-username/CubeCity/issues) - **讨论区**: [GitHub Discussions](https://github.com/your-username/CubeCity/discussions) --- ## 🎉 结语 恭喜你完成了 CubeCity 新手开发指南的学习!现在你已经具备了开始开发的基础知识。 记住: - 🎯 **保持学习心态**:技术栈在不断发展,持续学习新知识 - 🤝 **团队协作**:与团队成员保持良好的沟通和协作 - 📝 **文档优先**:及时更新文档,帮助其他开发者 - 🐛 **质量第一**:注重代码质量和用户体验 - 🚀 **勇于创新**:在现有基础上提出改进建议 祝你在 CubeCity 项目中开发愉快,创造出优秀的作品!🌟 --- *最后更新:2024年12月*