掼蛋卡牌游戏 (Guandan Card Game)
基于 Godot 4.6.3 开发的掼蛋卡牌游戏。训练模式已基本可用,联机与回放为后续阶段。
环境要求
- Godot 4.6.3+ (godotengine.org)
- 安装命令:
winget install GodotEngine.GodotEngine
快速开始
git clone <repo>
cd game-cards
# Godot 编辑器 → "导入" → 选择 project.godot → F5 运行
主场景: res://src/ui/scenes/main_menu.tscn
训练模式
进入"训练室"后由玩家(座位 0)对 3 个 L2 规则 AI,玩家始终是出牌方(AI 跟牌或过牌)。每局共 27 张/人,从 2 开始打。
玩法
- 鼠标点击手牌:选中(牌上抬 25px + 黄边高亮)
- 双击手牌:直接出该单张
出牌按钮:按当前选中提交牌型过牌按钮:本轮放权(领出者不能过)建议按钮:调 L2 AI 给出当前最优出法
牌型支持
单张 / 对子 / 三张 / 三带二 / 顺子(5+)/ 连对(6+ 双数)/ 钢板(6+ 3 整除)/ 同花顺 / 炸弹 / 火箭
UI 特性
- 手牌自动换行:
HandArea extends FlowContainer,27+ 张牌自动多行 - 按花色+点数排序: 渲染前
_sort_by_rank_and_suit统一顺序 - 出牌动画: ghost 节点从原位飞行 + 缩放至桌面中央(0.3s)
- 点评文字: 出牌方 + 牌型 + 张数 + 主阶,0.2s 淡入 → 0.6s 停留 → 0.3s 淡出
- 选中上抬: 选中时
position.y-25px tween(0.12s QUAD+EASE_OUT) - Hint 高亮: L2 AI 推荐的牌自动高亮(与选中共用
set_selected)
项目结构
game-cards/
├── src/
│ ├── core/ # 纯逻辑层(零 Godot 依赖)
│ │ ├── card.gd # Card 类(4 字节打包)
│ │ ├── deck.gd # Deck 与发牌
│ │ ├── game_state.gd # 牌局状态、Phase、Action 日志
│ │ ├── round.gd # 单轮出牌序列
│ │ ├── hand_evaluator.gd # 牌型判定(含主阶、是否纯炸弹)
│ │ ├── rule_engine.gd # 牌型比较与合法性
│ │ ├── move_generator.gd # 给定手牌生成所有合法出法
│ │ ├── actions.gd # Action 数据类
│ │ ├── rule_config.gd # 规则配置(主阶、级牌等)
│ │ └── constants.gd # 牌型枚举与常量
│ ├── ai/
│ │ ├── base_ai.gd # AI 抽象接口
│ │ ├── l1_basic_ai.gd # L1: 贪心最小牌
│ │ └── l2_rule_ai.gd # L2: 全枚举选最小压制
│ ├── game/
│ │ ├── game_controller.gd # 通用回合推进
│ │ ├── training_controller.gd # 训练模式:单玩家 vs 3 AI
│ │ └── replay_recorder.gd # Action 日志 → 重放
│ ├── autoload/
│ │ ├── config.gd # 规则与全局配置
│ │ ├── event_bus.gd # 全局信号总线
│ │ └── audio_manager.gd # 音效播放(未启用)
│ └── ui/
│ ├── scenes/
│ │ ├── main_menu.tscn # 主菜单
│ │ └── training_room.tscn # 训练室(1280×720)
│ └── components/
│ ├── hand_area.tscn # FlowContainer 手牌区
│ └── card_node.tscn # 单张卡牌(55×80)
├── tests/ # GUT 单元测试(占位)
├── docs/superpowers/ # 设计规格与实施计划
└── assets/ # 卡牌图片、UI 素材
关键架构决策
core/零 Godot 依赖 — 便于未来用 Rust 移植核心逻辑- Card 用 4 字节打包(suit+rank 占 1 字节,card_id 占 2 字节)— 减少内存与序列化成本
- GDScript 强类型 Array[Card] — 编译期类型检查;规避 Godot 4.6.3
Array.duplicate()丢类型 bug,统一用for c in src: dst.append(c)模式 - AI 三级 — L1 贪心 / L2 枚举 / L3 策略(待实现)
- 出牌动画用 ghost 节点 — 临时挂到
get_tree().root避免 FlowContainer 重排干扰
配置 Autoload
项目设置 → 自动加载 (Autoload):
| 名称 | 路径 |
|---|---|
| Config | res://src/autoload/config.gd |
| EventBus | res://src/autoload/event_bus.gd |
| AudioManager | res://src/autoload/audio_manager.gd |
运行测试
# GUT(推荐)
godot --headless -s addons/gut/gut_cmdln.gd -gdir=res://tests
当前
tests/仅有占位文件,无实际用例。
已知问题与限制
- 27+ 张牌的极端出牌(如 27 张单牌连出)
start_x可能为负,飞出左边界(实际不可能) - CommentaryLabel y=360-380 与 TableLabel 底部 10px 视觉重叠
- L3 策略 AI 尚未实现
- 联机 / 观战 / 回放 均为占位
开发计划
| 阶段 | 内容 | 状态 |
|---|---|---|
| 训练模式 | 核心 + L1/L2 AI + UI | 进行中 |
| L3 策略 AI | 配合/防守/控牌策略 | 待开发 |
| 完整对局 | 4 人完整出完一轮 | 待开发 |
| 联机 | Action 同步 + 房间 | 待开发 |
| 观战 / 回放 | Action 流式回放 | 待开发 |
设计文档
提交约定
- 单步可工作的 commit
- 类型前缀:
feat: / fix: / refactor: / docs: / chore: - 范围标注:
feat(ui): / fix(core):等 - 中英文皆可,遵循仓库历史风格(见
git log --oneline)
Description
Languages
GDScript
87.7%
Python
12.3%