更新记录

1.0.0(2026-07-08)

PROJECT INTRODUCTION 斗地主King 科技国风在线斗地主 — 集英雄技能、实时对战、程序化音效与语音播报于一体的完整卡牌游戏项目

TypeScript NestJS 微信小游戏 WebSocket Canvas MySQL Docker Overview 项目概述 斗地主King 是一款科技国风风格的在线斗地主卡牌游戏,采用前后端分离架构。 项目包含独立游戏引擎、NestJS 服务端、微信小游戏客户端、 Web 客户端以及完整的容器化部署方案。 游戏支持 3 人实时对战、12 位英雄技能系统、AI 自动补位、自定义房间、 以及程序化生成的音效与中文语音播报。

5 子项目模块 12 英雄角色 14 数据库表 MIT 开源协议 游戏引擎 (game-engine) 独立的 TypeScript npm 包,提供牌型识别、出牌校验、AI 策略、牌组管理等核心游戏逻辑,可被任意客户端复用。

服务端 (server) NestJS 框架,双协议 WebSocket(Socket.IO + 原生 WS),MySQL 持久化,JWT 认证,完整的房间匹配与游戏流程管理。

小游戏客户端 (minigame) 微信小游戏,纯 Canvas 渲染,零 DOM 依赖,包含自适应双行手牌、程序化音效合成、共振峰语音播报系统。

Web 客户端 (client) 独立 Web 版本,Canvas + 原生 JS,可脱离后端运行本地 AI 对战,也支持在线连接。

Architecture 系统架构 项目采用经典的分层架构,游戏引擎作为独立中间层解耦核心逻辑,服务端和客户端分别对接。


平台兼容性

uni-app(3.7.13)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
- - - - - - - - -
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
- - - - - - - - - - -

斗地主King 使用说明

目录


项目简介

斗地主King 是一款科技国风风格的在线斗地主卡牌游戏,支持 3 人实时对战、12 位英雄技能系统、AI 自动补位、自定义房间等功能。

技术栈:TypeScript + NestJS + Canvas + WebSocket + MySQL + Redis


环境要求

本地开发

依赖 版本要求 说明
Node.js >= 18.x 推荐 20.x LTS
npm >= 9.x 随 Node.js 安装
MySQL >= 8.0 用于数据持久化
Redis >= 7.0 用于缓存和排行榜

Docker 部署

依赖 版本要求
Docker >= 20.x
Docker Compose >= 2.x

项目结构

douzhu-king/
├── game-engine/          # 核心游戏引擎(独立 npm 包)
│   ├── src/              # TypeScript 源码
│   │   ├── types.ts      # 类型定义
│   │   ├── deck.ts       # 洗牌发牌
│   │   ├── card-analyzer.ts   # 牌型识别
│   │   ├── card-comparator.ts # 大小比较
│   │   ├── play-validator.ts  # 出牌校验
│   │   └── ai-player.ts       # AI 出牌策略
│   └── package.json
├── server/               # NestJS 服务端
│   ├── src/
│   │   ├── main.ts       # 启动入口
│   │   ├── ws-native.ts  # 原生 WebSocket 游戏服务
│   │   ├── hero/         # 英雄模块
│   │   ├── game/         # Socket.IO Gateway
│   │   ├── user/         # 用户模块
│   │   ├── auth/         # JWT 认证模块
│   │   ├── config/       # 配置文件
│   │   └── common/       # 公共设施
│   └── package.json
├── client/               # Web 客户端(纯静态)
│   ├── index.html        # 入口页面
│   ├── src/              # JS 源码
│   └── package.json
├── minigame/             # 微信小游戏客户端
│   ├── game.js           # 入口文件
│   ├── js/               # 核心逻辑
│   │   ├── game-core.js       # 游戏核心逻辑
│   │   ├── renderer.js       # Canvas 渲染器
│   │   ├── online-mode.js    # 在线模式控制器
│   │   ├── ws-client.js      # WebSocket 客户端
│   │   ├── animator.js       # 动画引擎
│   │   ├── audio.js          # 程序化音效
│   │   └── speech.js         # 语音播报
│   └── game.json         # 小游戏配置
├── database/             # 数据库脚本
│   ├── schema.sql        # MySQL 表结构(14 张表)
│   └── init-redis.lua    # Redis 缓存初始化
└── deploy/               # 部署配置
    ├── docker/           # Docker 相关
    │   ├── Dockerfile.server
    │   ├── docker-compose.yml
    │   └── nginx.conf
    └── scripts/           # 部署脚本
        ├── deploy.sh
        └── init-db.sh

快速开始

方式一:本地开发(推荐)

1. 克隆项目

git clone <仓库地址>
cd douzhu-king

2. 初始化数据库

# 创建数据库
mysql -u root -p -e "CREATE DATABASE IF NOT EXISTS douzhu_king DEFAULT CHARSET utf8mb4;"

# 导入表结构和初始数据
mysql -u root -p douzhu_king < database/schema.sql

或使用初始化脚本:

bash deploy/scripts/init-db.sh

脚本支持参数自定义:

bash deploy/scripts/init-db.sh <host> <port> <user> <password>
# 默认值:localhost 3306 root 123456

3. 启动 Redis

redis-server

4. 安装并启动游戏引擎

cd game-engine
npm install
npm run build

5. 安装并启动服务端

cd ../server
npm install
npm run build
npm run start:dev

启动成功后会看到:

🃏 斗地主之王 服务端已启动: http://localhost:3000
   API前缀: http://localhost:3000/api/v1
   原生WebSocket: ws://localhost:3000/game

服务端支持降级模式:即使 MySQL 不可用,HTTP 和 WebSocket 服务仍可启动(游戏房间在内存中运行)。

6. 启动 Web 客户端

cd ../client
npm install
npm run dev

浏览器访问 http://localhost:8080 即可进入游戏。

在连接面板中输入 WebSocket 地址 ws://localhost:3000/game,点击连接。

7.(可选)环境变量配置

server/ 目录下创建 .env 文件:

PORT=3000
DB_HOST=localhost
DB_PORT=3306
DB_USERNAME=root
DB_PASSWORD=123456
DB_DATABASE=douzhu_king
REDIS_HOST=localhost
REDIS_PORT=6379
# 跳过数据库连接(纯内存模式)
DB_SKIP=false

方式二:Docker 部署

一键启动

cd deploy/docker
docker compose up -d

这会启动 4 个服务:

服务 端口 说明
Nginx 80 Web 客户端 + API 反代
Server 3000 NestJS 服务端
MySQL 3306 数据库(密码:123456
Redis 6379 缓存

启动后浏览器访问 http://服务器IP 即可。

使用部署脚本

cd deploy/scripts

# 启动(自动构建、启动、健康检查)
bash deploy.sh start

# 停止
bash deploy.sh stop

# 重启
bash deploy.sh restart

# 查看状态
bash deploy.sh status

# 健康检查
bash deploy.sh health

# 仅构建镜像
bash deploy.sh build

# 数据库备份
bash deploy.sh backup

# 数据库回滚
bash deploy.sh rollback <备份文件路径>

各模块详细说明

游戏引擎 (game-engine)

独立的 TypeScript npm 包,提供斗地主核心逻辑,不依赖任何框架。

cd game-engine
npm install        # 安装依赖
npm run build      # 编译 TypeScript → dist/
npm run test       # 运行测试(Jest + 覆盖率)
npm run dev        # 监视模式编译

核心模块:

模块 功能
types.ts 类型定义(Suit, Card, CardType, Player, Room 等)
deck.ts 创建牌组、洗牌、发牌、排序
card-analyzer.ts 牌型识别(单张/对子/三条/顺子/连对/飞机/炸弹/火箭等)
card-comparator.ts 牌型大小比较、炸弹倍数计算
play-validator.ts 出牌合法性校验
ai-player.ts AI 出牌策略(自由出牌/跟牌)

服务端 (server)

基于 NestJS 框架,支持双协议 WebSocket。

cd server
npm install            # 安装依赖
npm run build          # 编译 TypeScript
npm run start:dev      # 开发模式(热重载)
npm run start:prod     # 生产模式
npm run lint           # ESLint 检查
npm run test           # 单元测试

端口配置:

服务 默认端口 配置方式
HTTP API 3000 环境变量 PORT
原生 WebSocket 3000 路径 /game
Socket.IO 3000 路径 /game

CORS 允许的来源:

  • localhost:3001
  • localhost:8080
  • localhost:5173
  • 127.0.0.1:8080

Web 客户端 (client)

纯静态 HTML + Canvas + 原生 JS,无需构建步骤。

cd client
npm install        # 安装 http-server
npm run dev        # 开发模式(禁用缓存,端口 8080)
npm run start      # 生产模式(有缓存,端口 8080)

支持两种游戏模式:

  1. 本地对战:无需服务端,与 AI 单机对战
  2. 在线对战:连接 WebSocket 服务器,与真人实时对战

微信小游戏客户端 (minigame)

微信小游戏项目,纯 Canvas 渲染,零 DOM 依赖。

配置文件 game.json

{
  "deviceOrientation": "portrait",    // 竖屏
  "showStatusBar": false,             // 隐藏状态栏
  "networkTimeout": {
    "request": 5000,                  // 请求超时 5 秒
    "connectSocket": 5000,             // WebSocket 连接超时 5 秒
    "uploadFile": 5000,
    "downloadFile": 5000
  }
}

使用微信开发者工具导入 minigame/ 目录即可运行。需要在代码中配置 WebSocket 服务器地址(通过 WSClient.connect(url) 传入)。

核心文件说明:

文件 行数 功能
game-core.js ~2260 游戏状态机、渲染调度、AI 逻辑、按钮/手牌交互
renderer.js ~970 Canvas 绘制(牌面/手牌/按钮/面板/特效)
online-mode.js ~1400 WebSocket 消息处理、在线流程控制
ws-client.js ~200 WebSocket 客户端(心跳/重连/消息队列)
animator.js ~150 Tween 动画引擎
audio.js ~870 程序化音效合成(Web Audio API)
speech.js ~900 中文语音播报(共振峰合成)

数据库配置

MySQL 表结构

14 张表database/schema.sql 包含完整的建表语句和初始数据。

表名 说明
t_user 用户表(用户名/昵称/金币/积分/等级/VIP)
t_game_record 对局记录(含回放数据 JSON)
t_hero 英雄配置(12 位英雄)
t_user_hero 用户英雄拥有情况
t_guild 公会表(最大 30 人)
t_guild_member 公会成员(会长/副会长/成员)
t_season 赛季配置(含奖励和排位规则 JSON)
t_season_user 赛季用户排位数据
t_skin 皮肤配置(6 套预置皮肤)
t_user_skin 用户皮肤拥有情况
t_ad_log 广告日志(视频/插屏/激励)
t_sign_record 签到记录(连续签到天数)
t_mail 邮件系统(系统/奖励/活动邮件)
t_daily_task 每日任务进度

默认测试账号:

用户名 密码
player1 123456
player2 123456
player3 123456

环境变量配置:

变量名 默认值 说明
DB_HOST localhost 数据库主机
DB_PORT 3306 数据库端口
DB_USERNAME root 用户名
DB_PASSWORD 123456 密码
DB_DATABASE douzhu_king 数据库名
DB_SKIP false 设为 true 跳过数据库连接

Redis 缓存说明

database/init-redis.lua 定义了 14 种缓存数据结构:

Key 模式 类型 说明
online:{userId} Hash 用户在线状态
matchmaking:queue List 匹配队列
room:{roomId} Hash 房间数据
cache:coins:{userId} String 金币缓存(TTL 1 小时)
cache:score:{userId} String 积分缓存(TTL 1 小时)
sign:{userId}:{date} Hash 每日签到
daily_task:{userId}:{date} Hash 每日任务进度
leaderboard:season:{seasonId} Sorted Set 赛季排行榜
leaderboard:guild Sorted Set 公会排行榜
ad:cd:{userId}:{adType} String 广告冷却
heartbeat:{roomType} Sorted Set 房间心跳检测
ratelimit:{userId}:{action} String 消息限流
mail:unread:{userId} String 未读邮件计数
lock:{resource} String 分布式锁

API 接口

所有 API 以 /api/v1 为前缀。

英雄模块

方法 路径 说明
GET /hero/list 获取全部英雄列表
GET /hero/:id 获取单个英雄详情
GET /hero/user/heroes 获取当前用户拥有的英雄
POST /hero/equip 装备英雄

认证模块

方法 路径 说明
POST /auth/register 用户注册
POST /auth/login 用户登录(返回 JWT)

健康检查

方法 路径 说明
GET /health 服务健康状态

WebSocket 消息协议

连接地址:ws://localhost:3000/game

消息格式:{ type: string, data: object }

客户端 → 服务端

type data 说明
join-match { heroId } 加入匹配队列
create-room { heroId } 创建自定义房间
join-room { roomNumber, heroId } 加入指定房间
leave-room - 离开房间
start-game - 房主开始游戏
bid { score: 0-3 } 叫地主(0=不叫)
play-cards { cards: [{id, suit, value}] } 出牌
pass - 不出(跳过)
use-skill - 使用英雄技能

服务端 → 客户端

type data 说明
match-success { roomId, players } 匹配成功
room-created { roomNumber, roomId } 房间创建成功
room-joined { roomId, players } 加入房间成功
player-joined { player } 有玩家加入房间
player-left { playerIdx } 有玩家离开
game-start { bottomCards, players, landlordIdx } 游戏开始
turn-start { currentPlayer } 回合开始
player-bid { playerIdx, score } 玩家叫分
landlord-decided { landlordIdx, bottomCards } 地主确定
cards-played { playerIdx, cards, remaining } 玩家出牌
player-passed { playerIdx, name } 玩家不出
play-invalid { error } 出牌无效
skill-used { playerIdx, skillName, remainingUses } 技能使用
game-over { winnerIdx, winnerName, isLandlordWin, multiplier } 游戏结束

英雄技能系统

共 12 位英雄,分 4 个稀有度和 7 种元素属性。

英雄列表

ID 名称 稀有度 元素 技能 类型 效果
1 烈焰战神 传说 烈焰印记 被动 炸弹倍数额外 +1
2 冰霜女王 传说 寒冰护盾 被动 被炸弹时积分损失减半
3 疾风剑豪 史诗 御风飞行 被动 出牌倒计时 +10 秒
4 雷神之子 史诗 雷霆一击 主动 随机查看对手一张手牌
5 大地守护者 史诗 坚如磐石 被动 不叫地主时积分损失减半
6 光影刺客 史诗 暗影突袭 主动 偷看一张底牌
7 圣光骑士 稀有 神圣庇护 被动 出顺子时积分 +10
8 花仙子 稀有 花之守护 主动 强制对手再出一次
9 铁拳武僧 稀有 铁拳破击 主动 下一手可出任意牌型
10 星际领航员 普通 星际导航 主动 查看对手剩余手牌数(每局 2 次)
11 龙吟剑客 普通 龙吟 被动 叫地主成功倍数 +1
12 月影舞者 普通 月影迷踪 主动 随机交换自己两张手牌

默认解锁英雄:星际领航员、龙吟剑客、月影舞者

技能使用规则

  • 被动技能:自动生效,无需手动使用
  • 主动技能:在出牌阶段点击技能按钮使用,每局限定使用次数
  • 技能按钮仅在轮到自己出牌时显示
  • 使用技能不会消耗出牌回合

部署管理

Nginx 反向代理规则

路径 代理目标 说明
/ 本地静态文件 Web 客户端
/api/ http://server:3000/api/ REST API
/ws http://server:3000/ws WebSocket(超时 3600 秒)
/health http://server:3000/health 健康检查

健康检查

Docker 配置了服务端健康检查:

wget --spider -q http://localhost:3000/health

使用部署脚本检查所有服务:

bash deploy/scripts/deploy.sh health

数据库备份与恢复

# 备份(输出到 /opt/douzhu-king/backups/)
bash deploy/scripts/deploy.sh backup

# 恢复
bash deploy/scripts/deploy.sh rollback /opt/douzhu-king/backups/douzhu_king_20260708.sql

常见问题

Q: 启动服务端报 MySQL 连接错误?

A: 服务端支持降级模式,数据库不可用时仍可运行。如果需要数据库功能:

  1. 确认 MySQL 已启动:systemctl status mysqldocker ps
  2. 确认数据库已创建:mysql -u root -p -e "SHOW DATABASES;"
  3. 设置环境变量 DB_SKIP=false(默认值)
  4. 或创建 .env 文件配置正确的数据库连接参数

Q: 匹配后只有自己一个人?

A: 匹配队列需要 3 人满员才开始。如果 10 秒内未满员,系统会用 AI 自动补位(1 真人 + 2 AI)。如果希望多人对战,需要多个客户端同时连接服务器。

Q: Web 客户端连接不上 WebSocket?

A: 检查以下几点:

  1. 服务端是否已启动(http://localhost:3000/health 返回正常)
  2. WebSocket 地址是否正确:ws://localhost:3000/game
  3. 浏览器控制台是否有跨域错误(确保在 CORS 允许的端口访问)
  4. 如果用 Docker 部署,使用 ws://服务器IP/ws 而非 ws://localhost

Q: 如何修改服务端口?

A: 通过环境变量 PORT 修改:

PORT=8080 npm run start:prod

或在 .env 文件中设置 PORT=8080

Q: 微信小游戏如何连接服务器?

A:game.js 中调用 wsClient.connect('wss://你的域名/game') 连接。生产环境需要使用 wss://(TLS 加密),并确保服务器已配置 SSL 证书。

Q: Docker 部署后如何查看日志?

A:

# 查看所有服务日志
docker compose logs -f

# 查看单个服务日志
docker compose logs -f server

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

暂无用户评论。