diff --git a/README.md b/README.md index 3e6c1d8..24f1063 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,55 @@ whaleTown/ - **资源文件**: 图片、音频等资源存放在 `assets/` 目录 - **游戏数据**: 配置文件、关卡数据等存放在 `data/` 目录 +### 命名规范 + +本项目遵循统一的命名规范以保持代码一致性: + +**核心规则**: + +- **场景文件**:`下划线_scene.tscn` 或 `下划线_prefab.tscn` + - 示例:`main_scene.tscn`、`player_prefab.tscn` +- **脚本文件**:`PascalCase.gd`(大驼峰) + - 示例:`PlayerController.gd`、`UI_MainMenu.gd` +- **节点名称**:`camelCase`(小驼峰) + - 示例:`playerHpBar`、`startButton` +- **变量/函数**:`camelCase`(小驼峰) + - 示例:`var moveSpeed`、`func getPlayerPos()` +- **常量**:`UPPER_CASE`(全大写 + 下划线) + - 示例:`const MAX_HEALTH = 100` +- **资源文件**:`lower_case`(小写 + 下划线) + - 示例:`bg_main_menu.png`、`sound_jump.wav` + +📖 查看完整的 [命名规范文档](docs/naming_convention.md) + +### Git 提交规范 + +本项目遵循统一的 Git 提交信息格式:`<类型>:<描述>` + +**常用提交类型**: + +- `init`:项目初始化 +- `feat`:新增功能 +- `fix`:修复 Bug +- `docs`:文档更新 +- `scene`:场景文件相关 +- `asset`:资源文件相关 +- `ui`:UI 界面相关 +- `gameplay`:游戏玩法相关 +- `refactor`:代码重构 +- `perf`:性能优化 + +**提交示例**: + +```bash +git commit -m "init:项目初始化,搭建Godot文件结构" +git commit -m "feat:实现玩家角色的移动和跳跃" +git commit -m "fix:修复敌人穿墙的碰撞问题" +git commit -m "scene:创建战斗场景并配置相机" +``` + +📖 查看完整的 [Git 提交规范文档](docs/git_commit_guide.md) + ## 贡献 欢迎提交 Issue 和 Pull Request! diff --git a/docs/git_commit_guide.md b/docs/git_commit_guide.md new file mode 100644 index 0000000..084a5db --- /dev/null +++ b/docs/git_commit_guide.md @@ -0,0 +1,157 @@ +# Git 提交规范 + +本文档定义了项目的 Git 提交信息格式规范,以保持提交历史的清晰和一致性。 + +## 提交格式 + +``` +<类型>:<简短描述> + +[可选的详细描述] + +[可选的注释或关联 Issue] +``` + +## 提交类型 + +### 主要类型 + +| 类型 | 说明 | 示例 | +|------|------|------| +| `init` | 项目初始化 | `init:项目初始化,搭建Godot文件结构` | +| `feat` | 新增功能 | `feat:添加角色移动系统` | +| `fix` | 修复 Bug | `fix:修复角色跳跃时的碰撞检测问题` | +| `docs` | 文档更新 | `docs:更新 README 中的安装说明` | +| `style` | 代码格式调整(不影响功能) | `style:统一代码缩进格式` | +| `refactor` | 代码重构(不新增功能也不修复 Bug) | `refactor:重构敌人 AI 逻辑` | +| `perf` | 性能优化 | `perf:优化场景加载速度` | +| `test` | 添加或修改测试 | `test:添加角色控制器单元测试` | +| `chore` | 构建过程或辅助工具的变动 | `chore:更新 .gitignore 文件` | +| `revert` | 回滚之前的提交 | `revert:回滚 feat:添加角色移动系统` | + +### 场景和资源相关 + +| 类型 | 说明 | 示例 | +|------|------|------| +| `scene` | 场景文件相关 | `scene:创建主菜单场景` | +| `asset` | 资源文件相关 | `asset:添加角色精灵图和动画` | +| `ui` | UI 界面相关 | `ui:设计游戏暂停菜单` | +| `audio` | 音频相关 | `audio:添加背景音乐和音效` | + +### 游戏开发特定类型 + +| 类型 | 说明 | 示例 | +|------|------|------| +| `gameplay` | 游戏玩法相关 | `gameplay:实现敌人生成机制` | +| `level` | 关卡设计相关 | `level:完成第一关卡设计` | +| `config` | 配置文件相关 | `config:调整游戏难度参数` | +| `plugin` | 插件相关 | `plugin:集成对话系统插件` | + +## 提交示例 + +### 基础示例 + +```bash +# 项目初始化 +git commit -m "init:项目初始化,搭建Godot文件结构" + +# 新增功能 +git commit -m "feat:实现玩家角色的移动和跳跃" + +# 修复问题 +git commit -m "fix:修复敌人穿墙的碰撞问题" + +# 文档更新 +git commit -m "docs:添加 Git 提交规范文档" +``` + +### 带详细描述的示例 + +```bash +git commit -m "feat:添加存档系统 + +- 实现游戏进度保存功能 +- 支持多个存档槽位 +- 添加自动保存机制 + +关联 Issue #12" +``` + +### 场景和资源示例 + +```bash +# 场景相关 +git commit -m "scene:创建战斗场景并配置相机" + +# 资源相关 +git commit -m "asset:导入角色动画资源包" + +# UI 相关 +git commit -m "ui:完成主菜单界面设计" + +# 音频相关 +git commit -m "audio:添加脚步声和跳跃音效" +``` + +### 游戏开发示例 + +```bash +# 游戏玩法 +git commit -m "gameplay:实现道具拾取和使用系统" + +# 关卡设计 +git commit -m "level:设计并实现第三关卡" + +# 配置调整 +git commit -m "config:平衡敌人血量和伤害数值" + +# 插件集成 +git commit -m "plugin:添加粒子效果插件" +``` + +### 重构和优化示例 + +```bash +# 代码重构 +git commit -m "refactor:重构角色状态机逻辑" + +# 性能优化 +git commit -m "perf:优化大量敌人时的渲染性能" + +# 代码格式 +git commit -m "style:统一 GDScript 代码风格" +``` + +## 注意事项 + +1. **使用中文冒号**:类型后使用中文冒号 `:` 而非英文冒号 `:` +2. **简短明确**:描述应简洁明了,一般不超过 50 个字符 +3. **动词开头**:描述部分使用动词开头,如"添加"、"修复"、"更新"等 +4. **一次提交一个改动**:每次提交应该只包含一个逻辑改动 +5. **详细描述**:对于复杂的改动,应该添加详细描述说明改动的原因和影响 + +## 分支命名规范 + +```bash +# 功能分支 +feature/角色系统 +feature/存档功能 + +# 修复分支 +fix/碰撞检测 +fix/音频播放 + +# 开发分支 +dev +develop + +# 发布分支 +release/v1.0.0 +release/v1.1.0 +``` + +## 工具推荐 + +- **Commitizen**: 交互式提交信息生成工具 +- **Git Hooks**: 使用 pre-commit 钩子自动检查提交格式 +- **Conventional Commits**: 遵循约定式提交规范 diff --git a/docs/naming_convention.md b/docs/naming_convention.md new file mode 100644 index 0000000..2501812 --- /dev/null +++ b/docs/naming_convention.md @@ -0,0 +1,592 @@ +# Godot 项目命名规范 + +本文档定义了 whaleTown 项目的命名规范,以保持代码的一致性和可读性。 + +## 目录 + +- [场景文件](#场景文件) +- [脚本文件](#脚本文件) +- [节点命名](#节点命名) +- [变量命名](#变量命名) +- [函数命名](#函数命名) +- [常量命名](#常量命名) +- [资源文件](#资源文件) +- [目录结构](#目录结构) + +--- + +## 场景文件 + +**规则**:下划线分隔 + `_scene` 或 `_prefab` 后缀 + +### 场景类型 + +- **主场景**:`_scene` 后缀,表示完整的游戏场景 +- **预制体**:`_prefab` 后缀,表示可复用的场景组件 + +### 示例 + +``` +✅ 正确 +main_scene.tscn # 主场景 +battle_scene.tscn # 战斗场景 +menu_scene.tscn # 菜单场景 +player_prefab.tscn # 玩家预制体 +enemy_boss_prefab.tscn # Boss 敌人预制体 +ui_dialog_prefab.tscn # 对话框预制体 + +❌ 错误 +MainScene.tscn # 不使用大驼峰 +main.tscn # 缺少 _scene 后缀 +player.tscn # 预制体缺少 _prefab 后缀 +``` + +### 命名建议 + +- 场景名称应清晰表达场景用途 +- 多个单词使用下划线分隔 +- 避免使用缩写,除非是通用缩写(如 ui、hp) + +--- + +## 脚本文件 + +**规则**:大驼峰命名(PascalCase),`.gd` 扩展名 + +### 脚本类型 + +- **控制器脚本**:`Controller` 后缀 +- **管理器脚本**:`Manager` 后缀 +- **UI 脚本**:`UI_` 前缀 +- **数据类**:`Data` 后缀 +- **工具类**:`Utils` 或 `Helper` 后缀 + +### 示例 + +``` +✅ 正确 +PlayerController.gd # 玩家控制器 +EnemyAI.gd # 敌人 AI +GameManager.gd # 游戏管理器 +AudioManager.gd # 音频管理器 +UI_MainMenu.gd # 主菜单 UI +UI_HealthBar.gd # 血条 UI +PlayerData.gd # 玩家数据类 +SaveData.gd # 存档数据类 +MathUtils.gd # 数学工具类 +StringHelper.gd # 字符串辅助类 + +❌ 错误 +player_controller.gd # 不使用下划线 +playerController.gd # 不使用小驼峰 +player.gd # 缺少明确的类型后缀 +PLAYER.gd # 不使用全大写 +``` + +### 命名建议 + +- 脚本名称应与类名一致 +- 一个脚本文件只包含一个主要类 +- 使用清晰的后缀表明脚本用途 + +--- + +## 节点命名 + +**规则**:小驼峰命名(camelCase) + +### 节点类型 + +- **UI 节点**:描述性名称,如 `startButton`、`healthBar` +- **游戏对象**:对象名称,如 `player`、`enemy` +- **容器节点**:用途 + Container,如 `itemContainer` +- **特效节点**:效果 + Effect,如 `explosionEffect` + +### 示例 + +``` +✅ 正确 +player # 玩家节点 +enemy # 敌人节点 +mainCamera # 主相机 +playerHpBar # 玩家血条 +startButton # 开始按钮 +pauseMenu # 暂停菜单 +itemContainer # 物品容器 +backgroundMusic # 背景音乐 +explosionEffect # 爆炸特效 +collisionShape # 碰撞形状 + +❌ 错误 +Player # 不使用大驼峰 +player_hp_bar # 不使用下划线 +StartButton # 不使用大驼峰 +PLAYER # 不使用全大写 +btn_start # 避免缩写 +``` + +### 命名建议 + +- 节点名称应简洁明了 +- 同类型节点可以添加数字后缀,如 `enemy1`、`enemy2` +- 避免使用无意义的名称,如 `Node2D`、`Control` + +--- + +## 变量命名 + +**规则**:小驼峰命名(camelCase),可选类型前缀 + +### 变量类型前缀(可选) + +使用类型前缀可以提升代码可读性,但不是强制要求。 + +| 类型 | 前缀 | 示例 | +|------|------|------| +| 整数 | `i` | `iHealth`, `iScore` | +| 浮点数 | `f` | `fSpeed`, `fDamage` | +| 字符串 | `s` | `sPlayerName`, `sDialogText` | +| 布尔值 | `b` 或 `is/has` | `bIsAlive`, `isJumping`, `hasKey` | +| 数组 | `a` 或复数 | `aEnemies`, `enemies` | +| 字典 | `d` | `dPlayerStats` | +| 节点引用 | 无前缀 | `playerNode`, `healthBar` | + +### 示例 + +```gdscript +✅ 正确(带前缀) +var iHealth: int = 100 +var fSpeed: float = 5.0 +var sPlayerName: String = "Player" +var bIsAlive: bool = true +var aEnemies: Array = [] +var dInventory: Dictionary = {} + +✅ 正确(不带前缀) +var health: int = 100 +var speed: float = 5.0 +var playerName: String = "Player" +var isAlive: bool = true +var enemies: Array = [] +var inventory: Dictionary = {} + +✅ 正确(布尔值使用 is/has) +var isJumping: bool = false +var hasWeapon: bool = true +var canMove: bool = true + +❌ 错误 +var Health: int = 100 # 不使用大驼峰 +var player_name: String = "" # 不使用下划线 +var SPEED: float = 5.0 # 常量才使用全大写 +var i: int = 0 # 循环变量除外,其他避免单字母 +``` + +### 成员变量 + +```gdscript +# 导出变量(Inspector 可见) +@export var maxHealth: int = 100 +@export var moveSpeed: float = 200.0 +@export var playerName: String = "Player" + +# 私有变量(以下划线开头) +var _currentHealth: int +var _isInitialized: bool = false + +# 节点引用 +@onready var healthBar: ProgressBar = $HealthBar +@onready var animationPlayer: AnimationPlayer = $AnimationPlayer +``` + +### 命名建议 + +- 变量名应具有描述性 +- 布尔变量使用 `is`、`has`、`can` 等前缀 +- 私有变量以下划线 `_` 开头 +- 避免使用单字母变量名(循环变量 `i`、`j` 除外) + +--- + +## 函数命名 + +**规则**:小驼峰命名(camelCase),动词开头 + +### 函数类型 + +- **获取函数**:`get` 前缀 +- **设置函数**:`set` 前缀 +- **判断函数**:`is`、`has`、`can` 前缀,返回布尔值 +- **事件处理**:`on` 或 `_on` 前缀 +- **初始化函数**:`init` 或 `initialize` +- **更新函数**:`update` 前缀 +- **私有函数**:`_` 前缀 + +### 示例 + +```gdscript +✅ 正确 +func getPlayerPosition() -> Vector2: + return position + +func setHealth(value: int) -> void: + health = value + +func isAlive() -> bool: + return health > 0 + +func hasItem(itemName: String) -> bool: + return inventory.has(itemName) + +func canJump() -> bool: + return isOnFloor and not isJumping + +func onButtonPressed() -> void: + print("Button pressed") + +func _onTimerTimeout() -> void: + # 信号处理函数 + pass + +func initializePlayer() -> void: + health = maxHealth + position = startPosition + +func updateMovement(delta: float) -> void: + position += velocity * delta + +func _calculateDamage(baseDamage: int) -> int: + # 私有函数 + return baseDamage * damageMultiplier + +❌ 错误 +func GetPlayerPosition(): # 不使用大驼峰 +func get_player_position(): # 不使用下划线 +func PlayerPosition(): # 缺少动词 +func JUMP(): # 不使用全大写 +``` + +### 内置函数重写 + +```gdscript +# Godot 内置函数使用下划线命名(保持原样) +func _ready() -> void: + pass + +func _process(delta: float) -> void: + pass + +func _physics_process(delta: float) -> void: + pass + +func _input(event: InputEvent) -> void: + pass +``` + +### 命名建议 + +- 函数名应清晰表达功能 +- 使用动词开头,如 `get`、`set`、`update`、`calculate` +- 参数名称也使用小驼峰命名 +- 私有函数以下划线开头 + +--- + +## 常量命名 + +**规则**:全大写 + 下划线分隔 + +### 示例 + +```gdscript +✅ 正确 +const MAX_HEALTH: int = 100 +const DEFAULT_SPEED: float = 200.0 +const PLAYER_NAME: String = "Player" +const GRAVITY: float = 980.0 +const JUMP_FORCE: float = -400.0 +const MAX_ENEMIES: int = 10 +const SAVE_FILE_PATH: String = "user://save.dat" +const SCREEN_WIDTH: int = 1920 +const SCREEN_HEIGHT: int = 1080 + +❌ 错误 +const maxHealth: int = 100 # 不使用小驼峰 +const MaxHealth: int = 100 # 不使用大驼峰 +const max_health: int = 100 # 不使用小写 +``` + +### 枚举命名 + +```gdscript +# 枚举名使用大驼峰 +enum PlayerState { + IDLE, # 枚举值使用全大写 + WALKING, + RUNNING, + JUMPING, + ATTACKING +} + +enum EnemyType { + NORMAL, + ELITE, + BOSS +} + +# 使用 +var currentState: PlayerState = PlayerState.IDLE +``` + +### 命名建议 + +- 常量名应清晰表达含义 +- 使用全大写和下划线 +- 枚举类型名使用大驼峰,枚举值使用全大写 + +--- + +## 资源文件 + +**规则**:下划线分隔,小写字母 + +### 图片资源 + +``` +✅ 正确 +bg_main_menu.png # 背景图 +sprite_player_idle.png # 精灵图 +icon_sword.png # 图标 +ui_button_normal.png # UI 元素 +tile_grass_01.png # 瓦片图 + +❌ 错误 +BgMainMenu.png # 不使用大驼峰 +bg-main-menu.png # 不使用连字符 +BACKGROUND.png # 不使用全大写 +``` + +### 音频资源 + +``` +✅ 正确 +sound_jump.wav # 音效 +sound_explosion.wav +music_battle.ogg # 音乐 +music_menu.ogg +voice_npc_greeting.wav # 语音 + +❌ 错误 +Jump.wav +sound-jump.wav +SOUND_JUMP.wav +``` + +### 其他资源 + +``` +✅ 正确 +font_main.ttf # 字体 +shader_water.gdshader # 着色器 +material_metal.tres # 材质 +animation_walk.res # 动画 + +❌ 错误 +MainFont.ttf +font-main.ttf +FONT_MAIN.ttf +``` + +### 资源命名建议 + +- 使用类型前缀,如 `bg_`、`sprite_`、`sound_`、`music_` +- 多个单词使用下划线分隔 +- 全部使用小写字母 +- 同系列资源使用数字后缀,如 `tile_01.png`、`tile_02.png` + +--- + +## 目录结构 + +### 目录命名 + +**规则**:小写字母 + 下划线分隔 + +``` +✅ 正确 +scenes/ # 场景目录 +scripts/ # 脚本目录 +assets/ # 资源目录 + sprites/ # 精灵图 + sounds/ # 音效 + music/ # 音乐 + fonts/ # 字体 +data/ # 数据目录 + levels/ # 关卡数据 + configs/ # 配置文件 +addons/ # 插件目录 +tests/ # 测试目录 + +❌ 错误 +Scenes/ # 不使用大写 +Scripts/ +Assets/ +``` + +### 推荐的项目结构 + +``` +whaleTown/ +├── scenes/ +│ ├── main_scene.tscn +│ ├── battle_scene.tscn +│ └── prefabs/ +│ ├── player_prefab.tscn +│ └── enemy_prefab.tscn +├── scripts/ +│ ├── PlayerController.gd +│ ├── EnemyAI.gd +│ ├── GameManager.gd +│ └── ui/ +│ ├── UI_MainMenu.gd +│ └── UI_HealthBar.gd +├── assets/ +│ ├── sprites/ +│ │ ├── sprite_player_idle.png +│ │ └── sprite_enemy_walk.png +│ ├── sounds/ +│ │ ├── sound_jump.wav +│ │ └── sound_attack.wav +│ ├── music/ +│ │ └── music_battle.ogg +│ └── fonts/ +│ └── font_main.ttf +├── data/ +│ ├── levels/ +│ │ └── level_01.json +│ └── configs/ +│ └── game_config.json +└── addons/ + └── plugin_name/ +``` + +--- + +## 完整示例 + +### 场景文件:`player_prefab.tscn` + +``` +[节点树] +player # 根节点(小驼峰) +├── sprite # 精灵节点 +├── collisionShape # 碰撞形状 +├── animationPlayer # 动画播放器 +└── healthBar # 血条 +``` + +### 脚本文件:`PlayerController.gd` + +```gdscript +extends CharacterBody2D + +# 常量(全大写 + 下划线) +const MAX_HEALTH: int = 100 +const DEFAULT_SPEED: float = 200.0 +const JUMP_FORCE: float = -400.0 + +# 导出变量(小驼峰) +@export var moveSpeed: float = DEFAULT_SPEED +@export var maxHealth: int = MAX_HEALTH + +# 成员变量(小驼峰,可选类型前缀) +var currentHealth: int +var isJumping: bool = false +var hasDoubleJump: bool = false + +# 私有变量(下划线前缀) +var _velocity: Vector2 = Vector2.ZERO +var _isInitialized: bool = false + +# 节点引用 +@onready var sprite: Sprite2D = $sprite +@onready var animationPlayer: AnimationPlayer = $animationPlayer +@onready var healthBar: ProgressBar = $healthBar + +# 内置函数 +func _ready() -> void: + initializePlayer() + +func _physics_process(delta: float) -> void: + updateMovement(delta) + updateAnimation() + +# 公共函数(小驼峰,动词开头) +func initializePlayer() -> void: + currentHealth = maxHealth + updateHealthBar() + _isInitialized = true + +func takeDamage(damage: int) -> void: + currentHealth -= damage + if currentHealth <= 0: + die() + updateHealthBar() + +func heal(amount: int) -> void: + currentHealth = min(currentHealth + amount, maxHealth) + updateHealthBar() + +func isAlive() -> bool: + return currentHealth > 0 + +func canJump() -> bool: + return is_on_floor() or hasDoubleJump + +# 私有函数(下划线前缀) +func _calculateDamage(baseDamage: int) -> int: + return baseDamage * 2 + +func updateMovement(delta: float) -> void: + # 移动逻辑 + pass + +func updateAnimation() -> void: + # 动画逻辑 + pass + +func updateHealthBar() -> void: + if healthBar: + healthBar.value = float(currentHealth) / float(maxHealth) * 100.0 + +func die() -> void: + print("Player died") + queue_free() + +# 信号处理(_on 前缀) +func _onAreaEntered(area: Area2D) -> void: + print("Area entered: ", area.name) +``` + +--- + +## 总结 + +遵循统一的命名规范可以: + +- ✅ 提高代码可读性 +- ✅ 便于团队协作 +- ✅ 减少命名冲突 +- ✅ 方便代码维护 +- ✅ 提升开发效率 + +记住核心原则: + +1. **场景文件**:`下划线_scene/prefab` +2. **脚本文件**:`PascalCase.gd` +3. **节点名称**:`camelCase` +4. **变量/函数**:`camelCase` +5. **常量**:`UPPER_CASE` +6. **资源文件**:`lower_case` + +保持一致,代码更清晰!