跳到正文
GitHub·· 8 天前AI 评分22

纯 AI 编写的 Cocos Creator 2D 角色成长与装备玩法原型 olua

WebCoderT/olua

AI 导读

开发者 WebCoderT 开源了 olua,一个完全由 AI 编写代码的 2D 角色成长与装备玩法原型,人只负责提需求和看效果。项目基于 Cocos Creator 3.8.7 客户端、NestJS 12 服务端与 React 19 管理后台三端,覆盖登录、角色成长、装备、地图探索与自动战斗,含 555 件装备、100 阶军衔与 37 阶战魂系统。

正文

English | 简体中文

本项目是一个纯 AI 编写的项目(Vibe Coding):仓库里的每一行代码都是 AI 写的,没有一行是人手写的。 人在这里只做两件事 —— 提需求、看效果。具体怎么做的、留下了哪些痕迹,见 一个纯 AI 编写的项目。

一个基于 Cocos Creator 3.8.7 的 2D 角色成长与装备玩法原型 + 配套的 NestJS 服务端与 React 管理后台, 聚焦登录、角色创建、角色成长、装备系统、地图探索与战斗玩法(打怪 / 掉落 / 技能 / 自动战斗)的完整三端演示。

三个端

仓库按端分成三个平级目录,各自有独立的 README 与 FAQ;跨端的约定与机制放在本文件与根 FAQ.md。

端 是什么 技术栈 目录 文档
客户端 Cocos Creator 游戏(登录 / 选角 / 战斗 / 背包 / 商城…) Cocos Creator 3.8.7 + TypeScript client/ README · FAQ
服务端 账号 / 角色 / 管理接口,SQLite 落库,Swagger 文档 NestJS 12 + node:sqlite + JWT server/ README · FAQ
管理端 运营后台(账号 / 角色 / 管理员 / 操作日志) React 19 + Vite + Tailwind v4 admin/ README · FAQ

三端的关系:客户端是玩家玩的游戏,服务端是它唯一的权威数据源(本地只是缓存),管理端给运营改数据。 接口契约由服务端单向生成到另外两端(见 接口文件为什么是生成的)。

client(Cocos)  ─┐
                  ├─→  server(NestJS + SQLite)  ←─  admin(React)
admin(React)   ─┘       ↑ 唯一手写接口的地方
                          └─ swagger:emit → openapi.json → gen-api → 两端接口文件

项目简介

这个项目目前包含以下几部分:

  • 登录场景、角色选择与创建场景
  • 游戏场景主循环与地图切换(Loading 过渡场景,带进度显示)
  • Tiled 地图渲染与对象组驱动:NPC 点位、复活点出生、矩形刷怪区、碰撞区
  • 小地图(HUD):底图用当前地图的 preview.jpg,按视野等比缩放并随角色平移,红点落在底图上的位置即怪物真实位置
  • 路线指示线:自动寻路(点击寻路 / 快速攻击追怪 / 自动挂机)期间,大地图地面与右侧小地图同时画出「角色 → 目标」的白色点状路线,终点用更大的白圈标出目的地(同一处路径数据,终点随目标移动实时更新)
  • 角色属性、等级与成长系统(HP / MP / 攻防区间 / 每秒回血 / 战斗力)
  • 装备系统:穿脱、属性汇总、内外观(8 方向外观位置 / 缩放 / 旋转)、未穿衣服时按性别显示默认身体(男 role/1 / 女 role/2)、装备详情弹窗(三段式着色名称 / 等级 / 部位 / 属性区间)
  • 装备前后缀变体:前缀(普通 / 强化 / 精良 / 极品 / 超神)× 后缀(人级 / 天级 / 神级)每件基础装备展开 15 个变体,属性按倍率逐项缩放,名称与文字按品质着色
  • 装备品质边框与详情背景:背包格与身上装备图标按前后缀组合显示发光边框动画(resources/borders 84 张图集全登记),悬停详情弹窗按同一组合切换背景动画(resources/backgrounds 41 个帧序列目录全登记);两者均取前 15 套按强度分配给 15 种组合,其余留给特殊装备的自定义表
  • 战斗系统:技能触发统一入口、冷却(按动作速度折算)、魔法消耗、伤害飘字、击退、突进位移(十步一杀:鼠标落点瞬移 + 落点特效)
  • 怪物系统:区域刷怪、AI 行为(待机游走 / 主动追击 / 受伤激怒追击 / 普攻)、死亡动画、信息面板、选中光圈
  • 死亡与复活:怪物死亡倒地动画播完才消失;角色死亡停帧锁操控,弹窗选择原地复活 / 回复活点安全复活
  • 经验与等级:击杀按角色与怪物等级差结算经验(差值越大越少,差 6 级以上无经验),升级属性重算并补满状态
  • 掉落系统:按权重概率掉落、掉落件数按每只怪配的区间随机(如 [1, 10] = 本次掉 1~10 件,可重复命中同一物品)、掉落物同心环散落互不重叠、走上去自动拾取 / 点击拾取;每只怪的掉落列表独立配置在 configs/monsterDrops(key 与怪物一一对应),条目逐条配权重 / 概率 / 数量,555 件装备按等级分段铺满全部怪物
  • 掉落光柱:装备落在地上时按前缀品质播放光柱特效(resources/effect/light 6 套全登记,前 5 套按普通→超神自动分配、第 6 套预留给特殊装备的自定义表);地面掉落名按「前缀 + 名称 + 后缀」三段着色
  • 商城系统:底部「商城」入口,系统内全部装备(555 件含前后缀变体)自动上架,默认 1 绑定元宝/件,购买直接进背包;门面式弹窗 + 卡片网格分页浏览(一行 3 张、每页 6 件),悬停图标看完整详情
  • 背包操作:一键整理(合并同类可叠加物 + 按等级/部位重排,从第一格起铺满、空格沉底)、拖动物品换格(空格移动 / 同种合并 / 其余交换,拖物品不带动弹窗)、拖出弹窗松手 = 整格销毁(全屏确认框:确定销毁 / 取消回原位)、一键回收为绑定元宝、丢弃模式整格丢弃(不可恢复);整理与移动规则均为纯函数、可单测
  • 自动战斗:快速攻击与自动挂机开关,基于 A* 寻路绕障碍走位
  • 状态(Buff)系统:技能附加状态、身上循环特效、头像下方图标条
  • 悬停详情:鼠标放在状态图标上显示名称 / 介绍 / 剩余时间,放在技能格上显示技能名称 / 介绍 / 冷却等基础信息
  • 战魂系统:37 阶成长线(外观取自 war-soul 素材),绑定元宝升级,属性计入战力与地图进入条件,可勾选外显到主角右上角;弹窗入口在角色信息弹窗「战魂」按钮(与「军衔」「称号」三格竖排相邻,NPC 战魂使者仍可用)
  • 称号系统:34 个带字名牌动画(resources/titles 全登记)排成 1~34 阶成长线,解锁/升级流程与战魂一致(绑定元宝价格曲线),属性按曲线生成;解锁后名牌常显在角色头顶信息栏(与军衔红字/血条同一节点),弹窗入口在角色信息弹窗「称号」按钮(不走 NPC)
  • 军衔系统:100 阶成长线(10 大段 × 10 阶:兵卒 → 校尉 → 都尉 → 中郎将 → 将军 → 重号将军 → 公卿 → 王爵 → 神将 → 神话),绑定元宝晋升,属性按「等效等级裸属性 × rate × 大段 factor」生成(夹在称号与战魂之间);军衔没有素材,它的外观就是角色头顶信息栏血条上方那行红字,晋升后立即更新;弹窗入口在角色信息弹窗「军衔」按钮(三格最上),左栏 100 阶列表只在打开时建一次、切换选中不重建
  • 每秒血量回复:等级 / 防御装备 / 战魂 / 称号 / 军衔 五处来源相加成一项属性(每秒 N 点),游戏主循环每秒结算一次并落盘(与回蓝共用同一次写档);强度按最大生命比例派生(默认每秒回 1%,整体调速只改 configs/growth.attributeRange.hpRecoverRate 一个数);只有防御部位装备带回血(衣 40% / 头 20% / 腰带 20% / 鞋 20%);死亡期间不回复、回血不计入战斗力(不会抬高任何地图的战力门槛)、怪物不回血;旧存档自动补字段
  • 头顶显示口径:角色名称显示在人物区域正中间(与怪物名称同一套「身体中心」口径,位置随 roleBody 高度自动居中);头顶信息栏只留军衔红字 / 血条 / 血量文字,称号名牌动画插在最上方
  • 弹窗层级:同屏打开多个弹窗时,点哪个哪个浮到其它弹窗之上(触摸与鼠标两条输入通道都接管;飘字提示、悬停物品详情这类临时层仍在弹窗之上,全屏确认框与死亡遮罩保持盖住弹窗)
  • 地图传送:传送官弹窗按地图类型分类展示,等级/战力/战魂未达标的地图点击时提示
  • 小地图弹窗:读取地图目录 preview.jpg 大图预览,左键点击自动寻路、右键点击直接传送
  • 资源预加载:进图前预载地图、NPC / 怪物帧动画与角色穿戴外观
  • 操作摇杆:左下角常驻摇杆(底座 + 可拖动手柄),按住拖动即移动 —— 拖得少走路、拖得多跑动(死区/阈值见 configs/role.joystickMove);只用触摸通道,桌面端鼠标按住拖动同样可用,摇杆上的按压不穿透、拖动结束也不会误清选中目标
  • 屏幕适配:铺满窗口(NO_BORDER)不留黑边,常驻 HUD 按可见区贴边重排;选角场景整块舞台等比缩放(contain),窗口宽高比与设计不一致时元素也不会跑到屏幕外
  • 服务端:账号注册登录(scrypt 加盐摘要)、角色数据云端保存(防抖合并推送)、修订号乐观锁、两套令牌受众、权限点守卫、登录限流、口令重置与令牌主动作废、操作审计日志、公告发布与全服触达、邮件通道(模板 + 投递队列 + 失败重试)
  • 管理端:账号与角色管理(六维筛选 / 结构化编辑 / 批量删除)、管理员与权限、操作日志查询、我的账号

一个纯 AI 编写的项目

这个仓库里的每一行代码都是 AI 写的。 客户端(Cocos Creator)、服务端(NestJS)、管理端(React), 以及 client/tools/ 与 tools/ 下的全部单测与审计脚本、README.md / FAQ.md 这些文档 —— 没有一行出自人手。

这是一个 Vibe Coding 项目:人不写代码,人只用自然语言提需求、跑起来看效果、说哪里不对,剩下的全部交给 AI。

人和 AI 各自干了什么

人 AI
负责什么 提需求(「加个军衔系统」「后台要能改角色属性」)、看效果、指出哪里不对、在几个方案里拍板 读现有代码 → 设计方案 → 写实现 → 写单测与审计脚本 → 自查回归 → 同步文档 → 按功能提交
不负责什么 不写代码、不查 API 文档、不手工调格式 不拍板 —— 拿不准的方案会先把选项摆出来问

这套做法留在仓库里的痕迹

  • 每个踩过的坑都会变成一个脚本。这里不靠记性防回归,靠自动化守卫:client/tools/ 下有 25 套单测、tools/ 下有 7 套审计,比业务代码还密 —— 配置有没有外泄、接口地址有没有硬编码、生成物与服务端文档是否逐字节一致、战斗规则快照有没有漂移、服务端算的属性与客户端是不是同一份、界面点击会不会穿透到世界,全都有脚本盯着。
  • 一切可调的东西都收进 client/assets/configs。数值、文案、布局、配色、时长、资源路径都不写进逻辑里。这条约定是被「AI 反复改数值」逼出来的,不是为了好看。
  • 接口文件全部由服务端 Swagger 文档生成。三端签名对不上会编译报错,而不是线上出现一个 undefined。这同样是为了让 AI 改完一端后,另一端在编译期就被拦住。
  • 回归是硬门槛。每次改动都要跑:服务端 e2e(248 + 77 + 279 + 108 + 25 条)+ 两端类型检查 + 25 套单测 + 7 套审计,全绿才算完。
  • 每处理完一个问题就按功能提交一次。改完一个功能立刻落一次 commit,不留一堆混在一起的未提交改动 —— 这样「哪次改动引入了回归」永远能二分出来。
  • 踩过的坑写进了 FAQ。每端目录下的 FAQ 收纳该端的具体问题,跨端的机制与环境坑在 FAQ.md;里面的每一条都是真实撞过的,包括环境坑(例如某类终端注入的 NODE_OPTIONS 会让服务端静默起不来)。

期望管理

代码经过了完整回归、能跑通,但请把它当成一件 AI 的作品来看:结构上的取舍以「先跑起来再收敛」为主, 有些抽象(配置与逻辑分离、生成物 + 守卫、纯函数 + 单测)是为了让 AI 后续能安全改动而专门设计的,不一定是人类手写代码时的第一选择。

如果你想知道 AI 到底能把一个项目做到什么程度 —— 下面这份「功能清单」就是答案。欢迎 review、提 issue、拍砖。

游戏截图

登录

登录

角色选择与创建

角色选择与创建

游戏主界面(角色信息 / 背包 / 技能弹窗)

游戏主界面

技能列表

技能列表

怪物与战斗

怪物与战斗

装备掉落光柱(地面掉落物按前缀品质播放光柱特效:普通→超神 5 档自动分配,第 6 套预留给特殊装备)

装备掉落光柱

小地图预览弹窗(大图预览 + 怪物红点 / NPC / 刷怪区;左键点击自动寻路、右键直接传送)

小地图预览弹窗

战魂系统

战魂系统

装备品质边框与详情背景(背包 15 种前后缀品质边框;悬停详情弹窗显示按品质切换的背景动画)

装备品质边框与详情背景

商城(系统内全部装备上架,一行 3 张卡片、每页 6 件分页浏览;悬停图标看完整详情)

商城

目录结构

olua/
├── README.md · FAQ.md      # 总览与跨端问题(本文件)
├── client/                 # 客户端:Cocos Creator 工程(用它打开这个目录)
├── server/                 # 服务端:NestJS
├── admin/                  # 管理端:React
├── tools/                  # 项目级脚本(跨端)
├── website/                # 项目官网(纯静态单页)
├── public/                 # 截图与联系方式二维码
├── docs/                   # 项目文档(简历介绍等)
└── equip-aligner/          # 装备素材偏移对齐小工具

client —— 客户端(Cocos Creator 工程)

约定:核心代码只做「怎么跑」,一切可调的东西都在 assets/configs —— 数值、文案、布局、配色、时长、资源路径都不写在逻辑里。 自查:node tools/audit-config-leak.cjs(在仓库根跑;扫出散落在 ui/ 里的可配置项与未登记的文案 key)。

下列路径均相对 client/(即 assets/configs 的完整路径是 client/assets/configs)。

  • assets/configs:数值与静态配置(按域一文件:role/monster/skill/equipments/items/drop/map/status/border/background/title/light/mall 等)
    • configs/texts:面向玩家的全部文案(浮动提示 / 校验原因 / 界面标签 / 悬停详情 / 加载进度,带 {占位符} 模板)
    • configs/bottomNav:底部功能入口表(名称 / 图标 / 解锁等级 / 快捷键)
    • configs/network:客户端唯一的服务端地址来源(根地址 / 超时 / 重试 / 角色进度同步防抖间隔)
    • configs/layout:UI 布局与样式(hud / dialogs / panels / scenes / borders / backgrounds / lights / images / sizes / theme)
  • assets/types:纯类型声明(common/role/animation/good/skill/map/monster/drop/status/border/background/title/light)
  • assets/entities:运行时实体(Role)
  • assets/skills:技能行为实现(技能实现只依赖 SkillContext,不反查全局)
  • assets/ui:界面脚本
    • ui/core:静态管理器(GameHelper/LayerManager/MonsterManager/MonsterAI/DropManager/SkillManager/StatusManager/EffectManager/AutoBattle/PreloadManager/StorageManager/RoleUIManager/SceneManager 等)
    • ui/components:按职责分组(hud/panel/dialogs/role/input/map)
    • ui/helpers:UI 生成(UiHelper 基础封装 / GameUiHelper 零件库 / AnimationHelper 帧动画)
    • ui/utils:纯函数工具,按功能域分目录(battle/drop/map/physics/resource/input/cursor/layout/node)
    • ui/utils/net:对服务端的全部访问
      • 生成物(禁止手改):ApiRoutes 路径表 / ApiModels 类型(服务端 DTO 的镜像)/ Api 接口方法(HealthApi·AuthApi·RoleApi)
      • 手写:HttpClient 二次封装与统一调度 / ApiCodes 业务码与文案 key / ApiError 错误归一 / Session 会话 / RoleSync 进度同步 / NetworkSetup 接线
  • assets/resources:资源目录(地图 tmx、帧动画、图集、图标、UI 素材)
  • assets/scenes:登录、角色选择、加载和游戏场景
  • tools:客户端专属脚本(25 套单测 + gen-monster-config.cjs / gen-monster-drops.cjs 配置生成器 + clean-role-empty-frames.cjs 素材清理 + lib/ 单测沙箱)
  • settings / profiles / native / package.json / tsconfig.json:Cocos 工程配置(package.json 是 Cocos 的工程描述,不是 npm 脚本)
  • library / temp / build:Cocos 缓存与构建产物(不进版本库)
  • 详见 client/README.md,问题见 client/FAQ.md

server —— 服务端(NestJS)

  • src/common:统一响应包裹、业务码、守卫(认证 AuthGuard / 权限 PermissionGuard)、过滤器、拦截器、装饰器
    • constants/permission:权限点与管理员角色的唯一来源(角色 → 权限映射;文档上的「所需权限」由它反查生成)
    • constants/swagger-tags:文档分组(公共接口 / 客户端 / 管理端)
    • interceptors/audit.interceptor:管理端写接口自动记日志(动作取 operationId,口令类字段落库前打码)
    • security:登录限流的纯函数判定(rate-limit.util)+ 内存计数器服务(login-throttle.service)
  • src/database:SQLite 连接与六张表(accounts / roles / admins / audit_logs / announcements / mail_queue,含存量补列)的仓储层
  • src/modules:auth(玩家认证)/ roles(角色)/ admin(管理端:认证 / 账号 / 角色 / 管理员 / 口令)/ announcement(公告:公共拉取 + 管理端 CRUD)/ mail(邮件:模板 + 投递队列 + 后台调度)/ audit(操作日志)/ token(JWT)/ health
  • src/swagger/setup:文档挂载(抽成函数,好让自动化测试也生成一次文档来验分组 / 权限标注 / 悬空 $ref)
  • src/swagger/emit:离线产出 openapi.json(npm run swagger:emit,两端接口文件的唯一输入)
  • openapi.json:机器可读契约(提交进仓库;改接口后必须重新生成,否则两端停在旧契约上)
  • test/e2e.cjs:端到端用例(真实起服务 + 真实请求,248 条断言:注册登录 / 角色 CRUD / 越权 / 令牌受众隔离 / 管理端全流程 / 文档分组与权限点 / 四级越权与超管保护 / 公告拉取与时间窗)
  • test/e2e-roles.cjs:角色管理专项(77 条断言:修订号乐观锁 / 六维筛选 / 结构化字段校验 / 批量与整账号删除 / 只读观察员越权 / 文档)
  • test/e2e-guard.cjs:运营与安全底座专项(279 条断言:口令重置与令牌作废 / 自助改密 / 操作日志落库·打码·筛选·权限 / 按用户名与按 IP 的登录限流 / 踢下线)
  • test/e2e-mail.cjs:邮件通道专项(108 条断言:用可注入的假发信器验入队 / 投递 / 重试与用尽上限 / 手动重投 / 未配置 SMTP 时整体禁用;不需要真实 SMTP 服务器)
  • 详见 server/README.md,问题见 server/FAQ.md

admin —— 管理端(React)

  • src/api:地址配置(唯一来源 config.ts)+ 请求层 http.ts(拦截器 / 超时 / 包裹解包 / 错误归一 / 401 跳登录)
    • 生成物 routes.ts 路径表 / models.ts 类型 / endpoints.ts 接口方法(authApi·accountsApi·adminsApi·rolesApi·auditApi·announcementsApi·mailsApi·statsApi·systemApi)
    • 手写的 types.ts(业务码 / 权限点 / 动作与目标的中文字典)与 index.ts(统一出口)
  • src/pages:登录 / 注册 / 概览 / 账号列表与详情(重置密码 · 踢下线 · 清空该账号全部角色)/ 角色列表(筛选 + 多选批量删除)与详情(基础信息 / 常用数值 / 装备·技能·背包结构化编辑)/ 管理员(改角色 · 启停 · 重置密码 · 删除)/ 公告(发布 · 编辑 · 删除 · 启停 + 生效状态列)/ 邮件(发信入队 + 投递记录:状态筛选 · 重试次数 · 失败原因 · 重投)/ 操作日志(筛选 + 分页 + 请求体展开)/ 我的账号(自助改密)
  • 界面按令牌里的权限点显隐菜单与按钮(store/session.hasPermission),服务端仍独立校验
  • 详见 admin/README.md,问题见 admin/FAQ.md

tools —— 项目级脚本(跨端)

  • gen-api.cjs:由 server/openapi.json 产出两端接口文件(唯一的代码生成器,服务端 npm run gen:api 调它)
  • gen-battle-rules.cjs:由 client/assets/configs 产出服务端战斗规则快照(战斗权威化的地基,详见 server/src/modules/combat/)—— 等级 60 / 战魂 37 / 称号 34 / 军衔 100 + 战斗力权重 7 项 + 装备 555 件(已展开前后缀变体)
  • audit-api-generated.cjs:生成物与文档逐字节一致 / 头标记 / 接口全覆盖 / 类型不悬空 / 路径只在路径表 / Cocos .meta 齐全
  • audit-api-hardcode.cjs:三端有没有硬编码地址、请求是否只在唯一出口发出、环境变量键是否都登记进 .env.example
  • audit-config-leak.cjs:客户端核心代码有没有可配置项外泄 + configs/texts 的 key 是否都被登记(白名单 config-leak-allowlist.json)
  • audit-ui-click-through.cjs:客户端 UI 点击会不会穿透到世界、按压归属的接线是否齐全
  • audit-battle-rules.cjs:战斗规则快照与客户端 configs 是否逐字节一致(数据漂移不会报错,只会让两端慢慢算得不一样)
  • audit-combat-parity.cjs:服务端算的角色属性是否与客户端 combatCalc 一致(算法漂移)。期望值不是抄一份口径,而是把真的 GameHelper.combatCalc 编译进 Node 跑一遍 —— 2849 组输入 × 10 项,覆盖全等级 / 全装备 / 全战魂称号军衔

其它

  • website:项目官网(纯静态单页:核心特色 / 截图画廊 / 联系方式,logo 与 favicon 在 website/assets/icons)
  • public:截图、展示素材与联系方式二维码
  • docs:项目文档(resume.md 等)
  • equip-aligner:装备素材偏移对齐小工具(自带 README 与自检脚本)

技术栈

  • Cocos Creator 3.8.7
  • TypeScript
  • Cocos UI / 2D 场景系统 / Box2D 物理(刚体与碰撞体)
  • 服务端:NestJS 12 + node:sqlite(Node 22 内置,无原生模块依赖)+ JWT(玩家 / 管理端两套受众)+ Swagger
  • 管理端:React 19 + TypeScript + Vite + Tailwind CSS v4
  • 开发方式:全部由 AI 编写(Vibe Coding),人类只提需求与验收 —— 见 一个纯 AI 编写的项目

常用命令(Makefile)

仓库根有一份 Makefile,把三端的常用动作收在一处(make / make help 列出全部,make info 打印当前工具链与关键路径):

make install        # 首次:装 server / admin 的依赖
make env            # 生成 server/.env(已存在则跳过)
make dev            # 同时起服务端 :3100 与管理端 :5173,Ctrl-C 一起退出

make client-check   # 客户端类型检查(Cocos 自带 tsc,0 错才算过)
make client-test    # 客户端 25 套单测
make server-verify  # 服务端一条命令全验(编译 + 五套 e2e + 生成物审计)
make admin-build    # 管理端类型检查 + 构建
make gen-api        # 改完接口后重新生成契约与两端接口文件
make audit          # 7 个跨端审计脚本

make check          # 静态检查:客户端 tsc + 管理端 typecheck + 7 个审计
make test           # 全部测试:客户端 25 套 + 服务端五套 e2e
make verify         # 完整门禁:check + 三端构建 + 全部测试(提交前跑这个)
  • 单跑一套客户端单测:make client-test-one T=test-bag-tidy
  • 换机器 / 换 Cocos 版本:make TSC=/path/to/tsc client-check
  • 客户端生成器与清理器:make client-gen-monster / make client-clean-frames(预演)/ make client-clean-frames-apply
  • 受限终端(被注入了 NODE_OPTIONS)不用特殊处理 —— Makefile 已统一清掉;想用原始环境:make RUN_ENV= <目标>

下面是各端的手工命令,不依赖 make 也能跑。三端的详细说明与全部环境变量见各自的 README。

快速开始

三端的详细说明与全部环境变量见各自的 README;这里是「最短跑通路径」。

1. 服务端(先跑起来,客户端与管理端都依赖它)

cd server
npm install
cp .env.example .env     # 首次:端口 / 密钥 / 上限都在这里;注释里逐项说明
npm run dev              # 开发(热编译);或 npm run start 跑已构建产物

2. 客户端(Cocos)

  1. 安装并打开 Cocos Creator 3.8.7。
  2. 通过 Creator 的 “Open” / “Open Project” 打开 client/ 目录(它才是 Cocos 工程根)。
  3. 在编辑器中打开 client/assets/scenes 下的场景文件。
  4. 使用预览或播放按钮运行项目。

客户端没有 npm 脚本,依赖 Cocos Creator 编辑器启动与预览。 连哪个服务端只由 client/assets/configs/network.ts 的 baseUrl 决定(真机调试改成局域网 IP)。 详见 client/README.md。

3. 管理端(React)

cd admin
npm install
cp .env.example .env.development   # 首次:接口根地址在这里(VITE_API_BASE_URL)
npm run dev                        # 开发;npm run build 产出 dist

管理端注册需要在 server/.env 里配 ADMIN_REGISTER_CODE(留空则开放注册),注册时填同一个注册码。 第一个注册的管理员自动成为超级管理员(全部权限),之后的都是普通管理员,要提权由超管在「管理员」页调整。 详见 admin/README.md。

4. 改接口 = 改服务端 + 重新生成

客户端与管理端不手写任何接口文件:接口路径、方法名、请求/响应类型全部从服务端的 Swagger 文档产出。 这样「服务端改一个字段、另外两端忘了改」这类问题会变成编译报错,而不是线上出现一个 undefined。

cd server && npm run gen:api     # = swagger:emit + node ../tools/gen-api.cjs
server/src(控制器 + DTO + 装饰器)           ← 唯一需要手写的地方
        │  cd server && npm run swagger:emit
        ▼
server/openapi.json(机器可读契约,提交进仓库)
        │  node tools/gen-api.cjs
        ▼
客户端 client/assets/ui/utils/net/{ApiRoutes,ApiModels,Api}.ts
管理端 admin/src/api/{routes,models,endpoints}.ts

改接口的标准动作:

  1. 改服务端的控制器 / DTO / 装饰器(每个接口必须有 operationId,形如 role.save);
  2. npm run gen:api 重新产出文档与两端接口文件;
  3. 两端 tsc / npm run build —— 有签名不兼容的地方会直接报出来(调用点按报错改)。

生成器认文档里的这几个字段(约定都写进文档,不靠猜):

文档里的字段 由谁写 决定什么
operationId(<模块>.<方法>) @ApiPublicDoc / @ApiPlayerDoc / @ApiAdminDoc 的 operationId 生成到哪个模块的哪个方法
x-olua-audience 同上(装饰器自动加) 是否带令牌(public → auth: false)
x-olua-data-schema / x-olua-data-nullable @ApiDataResponse(...) 响应里 data 的类型(缺省 = null)
x-olua-query-schema @ApiQueryModel(XxxQueryDto) query 参数对应的命名类型
x-olua-permissions @ApiAdminDoc({ permissions }) 生成物注释里的「所需权限」(方便两端对照)

生成物禁止手改,tools/audit-api-generated.cjs 会逐条盯着。 契约管线的完整说明见 FAQ.md。

5. 回归门槛

改动合并前至少跑完这三类(全绿才算完)。装了 make 的话就是一条命令:

make verify   # = check + 三端构建 + 全部测试

手工跑(等价,不依赖 make):

# 客户端:25 套单测(在 client/ 下跑,脚本自己找 Cocos 自带的 tsc)
cd client && for t in tools/test-*.cjs; do node "$t" || exit 1; done

# 服务端:编译 + 五套 e2e(248 / 77 / 279 / 108 / 25)+ 生成物一致性
cd server && npm run verify

# 管理端:类型检查 + 构建
cd admin && npm run build

# 项目级审计(在仓库根跑)
node tools/audit-api-generated.cjs && node tools/audit-api-hardcode.cjs \
  && node tools/audit-config-leak.cjs && node tools/audit-ui-click-through.cjs

在受限环境(例如注入了 NODE_OPTIONS 的终端)里跑服务端子进程需要清掉它:env -u NODE_OPTIONS npm run dev。详见 FAQ.md。

功能清单

✅ 已完成 ❌ 未完成  服务端与管理端的细粒度能力见各自 README。

账号与角色

功能 说明 状态
账号注册 / 登录 账号存服务端(SQLite),口令 scrypt 加盐摘要;令牌 7 天有效,登录失败不区分「账号不存在」与「密码错误」 ✅
角色选择与创建 每个账号最多 3 个角色,列表与数据都存服务端;创建的新角色按客户端配置生成(新手装备/背包/快捷键) ✅
游戏进度云端保存 角色改动(打怪升级 / 拾取 / 买卖 / 换装 / 吃药)自动写回服务端,防抖 1.5 秒合并,切地图与退出前立即补推 ✅
旧存档自动迁移 新增字段/存储格式变更时读取自动补齐(装备/背包 id 引用制等) ✅
删除角色 选角界面「管理」进入管理态,各角色头顶出现删除按钮,两步确认后由服务端删除(不可恢复) ✅
新角色出生背包 通用件 + 全部基础武器/衣服,外加 1 级武器的全部前后缀变体(15 件品质) 一起发进背包,出生即可对比外观与边框 ✅
管理端(React) 管理员登录注册、账号分页检索与封禁、查看账号下的每个角色并改属性 / 切换在线 / 删除、重置玩家口令、踢下线 → admin/README.md ✅
后台角色管理 六维筛选(关键字 / 在线状态 / 职业 / 性别 / 等级区间 / 账号);全部基础信息可改(名称 / 职业 / 性别 / 等级 / 时装 / 头像 / 所在地图 + 金币 / 元宝 / 银两 / 经验 / 战魂 / 称号 / 军衔);装备 / 技能 / 背包结构化编辑(服务端只校验结构,清单以客户端配置为唯一真相);多选批量删除、整账号清空角色;改名仍受「同账号不重名」约束 ✅
后台改动与在线玩家一致 角色带修订号(每次落库 +1):玩家推进度时带上它做乐观锁,对不上说明后台改过 —— 服务端拒收、客户端自动拉最新并以它为基线(后台改动优先,玩家的旧存档不会覆盖它);角色被后台删除/踢下线时客户端自愈回选角场景 ✅
口令管理 玩家忘记口令只能由客服在后台重置(客户端没有找回流程):重置时前端生成随机口令、只显示一次(服务端只存哈希),旧口令与新旧口令相同都会被拒;管理员改自己的密码要验证原密码,成功后服务端下发新令牌(否则改完立刻被自己踢出后台) ✅
令牌主动作废 改口令会让此前签发的全部令牌立即失效(两表各带 token_version,签发时写进令牌、守卫每次回查库比对)—— 无状态 JWT 光改口令踢不掉旧令牌,这是补上的那一环 ✅
登录限流 按用户名(默认 5 次 / 10 分钟)与来源 IP(默认 20 次 / 10 分钟)两个维度计数,超限锁定并告知还要等多久;达阈值后计数归零(正常用户被误锁不会「一错再错」);阈值与开关都在 server/.env,反代的 TRUST_PROXY 陷阱有注释说明 ✅
踢下线 后台一键清掉账号的在线角色;只清标记是拦不住的(玩家本地还在跑),所以服务端同时拒收该账号非在线角色的存档推送(业务码 20007),客户端收到后飘字并回选角界面 —— 角色数据完好,重选一次即可继续 ✅
操作日志 管理端写操作自动留痕(动作取接口的 operationId,新增接口零额外工作;读接口不记);口令 / 令牌 / 注册码一类字段落库前递归打码;登录成功与失败都记(含来源 IP 与尝试的账号名);带筛选(关键字 / 动作 / 目标 / 结果 / 时间范围)与分页界面;写日志永不影响主流程(内部吞异常 + 超量自动清理最旧的) ✅
权限管理 管理员分三级(超级管理员 / 管理员 / 只读观察员),权限点粒度到「每个接口」(查看 / 封禁 / 删除 / 改角色 / 重置口令 / 查日志 / 发公告…);权限点唯一来源 + 守卫实时校验,界面按权限显隐;保护最后一个启用中的超级管理员 ✅
公告发布 运营在管理端发布「标题 / 正文 / 级别(重要优先展示)」并设定生效时间窗(可立即生效 / 不设截止),停用即下架;「是不是生效中」由服务端判定(与玩家侧拉取同源),管理端只展示、不拿本地时钟自己算 ✅
邮件触达 运营按模板给玩家发信:只入队不等投递(后台调度器发,失败指数退避重试、用尽上限标失败并留原因),投递记录可查状态 / 重试次数 / 失败原因并支持重投;未配 SMTP 时通道整体禁用(明确报错而不是静默丢信);模板是数据、必填变量缺失即拒发 ✅
接口文档 Swagger 抛出(/api-docs),按公共接口 / 客户端 / 管理端三组展示;每个接口标出令牌要求与所需权限点;统一响应包裹 + 业务码 ✅
泡点活动 持续获得经验,经验条与等级动态更新 ✅

地图与场景

功能 说明 状态
场景切换与 Loading 过渡 换图/进图带进度显示 ✅
Tiled 对象组驱动 NPC 点位、复活点、矩形刷怪区、碰撞区 ✅
复活点出生 进图/传送统一从 revive 点出生 ✅
小地图 真实地图底图(地图 preview.jpg 按视野等比缩放、随角色平移)+ 名称/世界坐标/角色黑点/附近怪物红点/寻路路线 ✅
小地图预览弹窗 读取地图目录 preview.jpg,左键点击自动寻路、右键点击传送;NPC 白点与名称、刷怪区名称、寻路路线 ✅
地图传送官弹窗 按 MapType 分类,标题 + grid 排列传送按钮,新增地图自动扩展 ✅
地图进入限制 等级/战力/战魂未达标时拦截传送并提示原因 ✅
碰撞范围调试可视化 按开关显示碰撞框(角色/障碍/怪物配色区分) ✅

角色成长

功能 说明 状态
等级属性成长 按等级生成攻击/防御区间,战斗力计算 ✅
击杀经验 按角色与怪物等级差衰减(差 ≥6 级无经验),击杀位置飘字 ✅
升级流程 属性重算、血蓝补满、升级特效 ✅
HP / MP 血球魔法球、头顶血量实时刷新、魔法自然回复 ✅
战魂系统 37 阶单一成长线,左中右三栏弹窗,绑定元宝升级;入口 = 角色信息弹窗「战魂」按钮(紧邻「称号」),NPC 战魂使者仍可用 ✅
战魂属性生效 各阶属性计入角色属性与战斗力,并作为地图进入条件 ✅
战魂外显 弹窗勾选后当前等级战魂动画挂主角右上角,切图/重登保留 ✅
称号系统 34 个带字名牌动画(resources/titles 全登记)排成 1~34 阶成长线;解锁/升级流程与战魂一致(绑定元宝价格曲线),属性按「等效等级裸属性 × rate × 系列 factor」生成 ✅
称号外显 解锁后名牌常显在角色头顶信息栏(与名称/血条同一个节点,原生尺寸不缩放),无开关、切图/重登保留;入口在角色信息弹窗「称号」按钮(紧邻「战魂」,不走 NPC) ✅
军衔系统 100 阶(10 大段 × 10 阶)单一成长线,左中右三栏弹窗 + 军衔徽记;绑定元宝晋升(价格 = 30 × N²),属性按「等效等级裸属性 × rate × 大段 factor」生成(满衔 ≈ 裸属性 52.5%,夹在称号 39% 与战魂 67% 之间) ✅
军衔外显 军衔名以红色文字常显在角色头顶信息栏血条上方(角色名称之下,军衔没有素材、这行红字就是它的外观),未授衔留空、晋升后立即更新,切图/重登保留;入口在角色信息弹窗「军衔」按钮(与「战魂」「称号」三格竖排相邻,不走 NPC) ✅
战魂数值与消耗逐级手调 升级消耗与属性为公式占位,待逐级调整 ❌

装备与物品

功能 说明 状态
装备穿脱与属性汇总 穿戴校验(等级/性别/职业),换装实时重算 ✅
id 引用制存储 装备槽/背包存物品 key,改配置重启即生效 ✅
内外观显示 8 方向外观位置/缩放/旋转、内观位置、前后缀与标签 ✅
装备/物品配置 12 衣服、20 武器及戒指/项链/鞋/盔/带,带图标与文案 ✅
装备前后缀变体 前缀 5 档 × 后缀 3 档,每件展开 15 变体(共 555 件),属性按倍率缩放、名称品质着色 ✅
装备品质边框 背包与身上装备图标按前后缀组合显示发光边框动画(resources/borders 84 张图集全登记,前 15 张按强度分配给 15 组合),特殊装备可配自定义边框 ✅
装备详情弹窗 三段式着色名称、等级/部位、回收价、属性区间与基础信息;悬停位置由纯函数摆放(尽量靠屏幕中间 + 整块留在可见区,任意窗口尺寸/任意格子都完整可见) ✅
装备详情背景 详情弹窗按前后缀组合显示品质背景动画(resources/backgrounds 41 个帧序列目录全登记,前 15 个按强度分配给 15 组合),特殊装备可配自定义背景 ✅
掉落系统 权重掉落表、件数区间随机([1,10] 掉 1~10 件)、同心环散落不重叠、自动拾取/点击拾取 ✅
每怪独立掉落表 configs/monsterDrops 一只怪一份列表,条目逐条配权重/概率/数量 + 掉落件数区间;药品材料按等级分档、装备按等级段铺满 555 件变体 ✅
背包一键整理 弹窗底部一键:合并同类可叠加物 + 按等级/部位重排,从第一格起铺满、空格沉底,算法纯函数可单测 ✅
背包拖动物品 按住物品拖到别的格子:空格 = 移动、同种可叠加 = 合并(超上限留原格)、其余 = 交换;幽灵图标跟随 + 落点高亮,拖物品不会带动整个弹窗,规则纯函数可单测 ✅
背包一键回收 弹窗底部一键:背包里的装备换成绑定元宝(身上穿着的不算),价 = 等级曲线 × 前后缀倍率,两步确认后生效 ✅
背包丢弃物品 把物品拖到背包弹窗外面松手 → 全屏确认框(确定 = 整格销毁、取消 = 物品回原位);另有弹窗底部「丢弃」进入丢弃模式点格子丢弃(两步确认)。不限物品大类,与「一键回收」并存 ✅
通用确认框 components/dialogs/ConfirmDialog:全屏模态黑幕 + 面板 + 确定/取消,自己独占触摸与鼠标两路输入(下层 UI 与世界都点不到);文案由使用方从 configs/texts 传入 ✅
装备数值填写 战斗数值逐件调整 ❌
背包叠加数量角标 格子显示可叠加物品数量 ❌
掉落物名称前后缀 地面掉落名按「前缀 + 名称 + 后缀」拼全并三段着色(前缀/名称用前缀色、后缀用后缀色),与装备详情弹窗同走一套取色规则;非装备仍单行白字 ✅
装备掉落光柱 装备落在地上时图标下方播放品质光柱动画(resources/effect/light 6 套全登记,前 5 套按前缀普通→超神自动分配、第 6 套预留给特殊装备自定义表),进图预载 ✅
商城系统 底部「商城」入口(M):系统内全部装备(555 件含前后缀变体)自动上架,默认 1 绑定元宝/件,购买直接进背包(余额不足/背包满不扣钱不改包);弹窗即商城门面背景(resources/mall/bg),商品一行 3 张卡片、每页 6 件分页浏览(翻页整页重建,打开不卡顿),悬停图标看完整详情;商品与价格见 configs/mall ✅

战斗与技能

功能 说明 状态
技能系统 统一触发入口、冷却/耗蓝/距离校验、特效、击退 ✅
键盘 + 鼠标双操控 WASD/SHIFT + 左键走右键跑、拖动实时改向、左键点怪攻击/右键选中 ✅
自动战斗 快速攻击/挂机开关,A* 寻路绕障碍,卡住换目标 ✅
路线指示线 自动寻路期间大地图地面 + 小地图同步绘制白色点状路线(终点大白圈) ✅
状态 Buff 技能附加状态、身上循环特效、图标倒计时 ✅
突进技能(十步一杀) 按鼠标位置瞬移:范围内落鼠标点、范围外按技能距离取最远落点,落地播放特效 ✅
状态数值接入伤害 格挡/减伤/加防等数值效果参与结算 ❌
怪物技能 怪物释放配置的技能(当前只会普攻) ❌
玩家受击反馈 受击动作/飘字等表现完善 ❌

怪物

功能 说明 状态
区域刷怪 开图按地图配置的刷怪矩形随机生成 ✅
怪物 AI 待机游走、主动追击、被动怪受伤激怒追击、普攻结算 ✅
死亡动画 死亡倒地播完才移除节点,缺帧兜底直接移除 ✅
怪物地图信息 名称居中(主动红/被动黄),头顶血条+血量文字 ✅
怪物信息面板/选中光圈 点击选中,血量/属性实时显示 ✅
怪物配置全量完善 220 只怪的可见身体尺寸(contentSize)与外观偏移(outOffset)按素材 auto-trim 实测(client/tools/gen-monster-config.cjs 生成,碰撞盒/点选/血条位置全由它决定,历史上 5~220 号是 0×0 点不中);动作速度收敛为 monsterDefaultSpeedRate 默认表 + 条目可覆盖;主动怪按「BOSS 或身体宽 ≥ 250px」规则铺开(76/220),出售价按等级×定位生成 ✅
怪物定时刷新 死亡后按周期补充(当前开图生成一次) ❌

死亡与复活

功能 说明 状态
角色死亡流程 死亡动画停末帧、锁全部操控、怪物停止追击尸体 ✅
复活弹窗 黑色半透明遮罩 + 原地复活 / 安全复活(回当前地图复活点) ✅

界面与其他

功能 说明 状态
HUD 全家桶 角色信息栏/血球/魔法球/经验条/快捷键栏(6 格+冷却)/小地图 ✅
悬停详情弹窗 状态图标悬停显名称/介绍/剩余时间;技能格悬停显名称/介绍/冷却等 ✅
自定义鼠标指针 指向怪物攻击指针、指向物品按大类变色 ✅
资源预加载 进图前预载地图/NPC/怪物/外观帧动画,按目录缓存 ✅
UI 命中检测 点击界面元素不穿透到世界(不打断操作) ✅
UI 点击不穿透(UI 内部) 点击元素在鼠标事件通道上同时登记,点弹窗关闭按钮/面板不会触发下层 HUD(如误开小地图弹窗) ✅
世界侧按压归属 按住走路以按下开始、抬起结束:界面拦下抬起时交还世界侧(不会卡住一直走);按压起点由各界面元素自己登记(记的是引擎给的命中目标,与冒泡顺序无关),登记点一律先过 UITransform 防呆(不会把引擎打崩);点 NPC 不误触发走路、不打断挂机 ✅
屏幕适配 铺满窗口(NO_BORDER)+ 常驻 HUD 贴边重排;选角场景整块舞台等比缩放,任意窗口宽高比下元素都在可见区内 ✅
公告展示 登录页:进入登录场景就弹「重要」公告(只弹重要、不按已读过滤),「我知道了」关闭;游戏内:小地图「公告」入口 + 未读红点,公告板左右分栏(左列表按「重要在前」分层、同级保持服务端次序,右正文),打开即把本次生效中的公告标为已读(本次仍看得到哪几条是新的) ✅
素材缺口补齐 武器每方向后 4 帧、cloth 011/012/013、weapon 005/021 缺失资源 ❌
界面布局打磨与命名规范 整体视觉与资源命名统一 ❌

文档

文档 内容
README.md 本文件:项目总览、三端索引、目录结构、快速开始、功能清单
FAQ.md 跨端:地址唯一来源、契约管线、三端联动的机制、环境坑、回归怎么跑
client/README.md · client/FAQ.md 客户端:Cocos 工程怎么打开、客户端架构与约定、预览报错与玩法配置的问题
server/README.md · server/FAQ.md 服务端:启动与环境变量、数据模型、认证与权限、契约生成、限流与审计
admin/README.md · admin/FAQ.md 管理端:启动与构建、权限显隐、页面清单、api 层分工
docs/resume.md 简历用项目介绍

素材与联系方式

资源素材过大无法进行版本控制,如果需要请联系我。

微信二维码

来源:GitHub · github.com