首页
首次启动运行游戏
Demo资源下载
- [gitlab_demo地址](https://git.jumpw.com/popx/client/popx-game-demo.git)
运行环境配置
node 版本 v10.24.1
推荐使用指定的node版本,可以用nvm来转换。
- [nvm下载及安装方式](https://blog.csdn.net/ppz8823/article/details/130862191)
- [使用nvm命令的参考](https://blog.csdn.net/qq_45621643/article/details/139989015)
参考上述文档安装完成nvm后,运行如下命令切换到node版本v10.24.1
nvm install 10.24.1 nvm use 10.24.1
修改host文件
找到host文件,一般在C:\WINDOWS\system32\drivers\etc目录下 最后一行添加
199.232.68.133 raw.githubusercontent.com
laya 版本 v2.13.1
[laya官方ide](https://ldc2.layabox.com/layadownload/?type=layaairide-LayaAir%20IDE%202.13.1)
安装laya的cmd命令库
推荐如下安装方式,demo目录下
npm i -g cnpm@6.1.0 cnpm config set registry https://registry.npmmirror.com cnpm i layaair2-cmd -g
首次运行时的操作
打开demo目录文件夹,运行
demo目录下安装相关依赖
npm i
如果安装失败,检查host文件是否修改,删掉node_modules目录重新运行命令
安装完成后,VSCODE运行调试,或者按键F5 注意,不需要打开laya的IDE环境,直接用VSCode调试即可。
上述操作无误,即可进入游戏的登录界面,
输入账号密码后,选择指定地图(也可以不选择,地图的制作可以查看demo视频)
就可以看到战斗服务器世界中有自己的人物了。
游戏的基础开发逻辑
该篇会讲述最基础的开发逻辑,如果想要先了解项目目录和工作流,建议先参考如下篇幅 #主要工程目录
进入房间(游戏世界)
如下是最基本的开发登录流程说明
步骤 | 描述 | 流向 |
---|---|---|
开始 | 流程的开始 | -> 登录页面 |
登录页面 | 账号密码,选定地图,输入房间号(可不填) | -> 远端服务器(官方) |
远端服务器(官方) | 获取玩家账户信息,分配到房间,房间就是我们的host代码 | -> Client 和 -> Host |
Client | 监听XPopManager.onGameStart | -> 前端逻辑开始 |
Host | 监听XPopManager.onHostStart | -> 房间战斗逻辑开始 |
远端服务器(官方)会处理最基本的登录,分配房间,创建游戏世界的逻辑,并且同步该世界中的游戏数据。
通过XpopManager管理类,来向Client和Host抛出事件,开发者可以监听这些事件做处理。
开发者需要关心的逻辑,就是Clint和Server(上图中Host)目录下的代码。
模型加载(人物动作)
XModelHero可以用于加载玩家的模型
let hero = new Hero(); hero.onInit(0, 0, userid); hero.index = index; hero.loadModel('role/model_avatar_body_default');
上述Hero类对角色的模型和数据进行了封装,最终 [公共模型的路径集合](https://h5ppreview.jumpw.com/popion/web/v1.0.1729/version.json)
前后端协议交互
项目采用proto来做相互通信,建议参考如下篇幅 #npm run proto(协议通信)
前后端共用配置
前端src/client目录和后端src/server目录中,都可以调用如下代码来加载所有的表格配置
CsvManager.ins.loadCsvs(this, () => { // Do some thing after load });
表格的加载逻辑和解析逻辑,可以参考CsvManager中的代码 src/shared/csv/CsvManager.ts
如何新增配置?
以demo中的item.csv为例.
- 1.配置csv文件资源的根目录为res-extra/csv/ ,在里面添加item.csv
- 2.CsvManager.ts文件中,添加读取表格和解析表格的逻辑
// loadCsvs代码中,添加你需要解析的csv名称 public loadCsvs(caller: any = null, listener: Function = null) { let assets = [ this._prefix + "item.csv", ]; // XResManager加载本地资源 XResManager.instance.loadText(assets, () => { // 在加载完成的回调中,处理表格数据结构,生成CItemData,不再赘述 this.onCompleted(caller, listener); }); }
- 3.解析表格得到的CItemData结构,定义在src/shared/dataMgr/中,可以被前后端一起调用
玩家战斗数据快照
游戏战斗服务器中,每个玩家的实时信息,通过快照来更新
XVF_SnapData
以demo中的Snap_UserData.ts为例
- 该玩家数据中类中,包含的各种public变量,都是XVF_SnapData接口类型
export class Snap_UserData { //坐标旋转 public position: XVF_SnapData<SyncPos>; //状态 public state: XVF_SnapData<SyncState>; //hp public hp: XVF_SnapData<number>; }
- 每次该接口类型的数据发生变化时,会调用OnSet方法,这类数据的修改逻辑是:服务器修改,前端监听变化
- 前端登录成功后,服务器注册对应玩家数据
- 前端对数据中的某个XVF_SnapData做监听,注册OnSet方法
- 服务器战斗逻辑修改了该数据时,前端根据OnSet的逻辑做表现处理
- XVF_SnapData数据,如果是复杂类型,需要调用UpdateData()方法,前端才能触发OnSet
如下的SyncState就是复杂类型
public state: XVF_SnapData<SyncState>; public setState(key:string, obj:string):void{ this.state.value.key = key; this.state.value.obj = obj; this.state.UpdateData(); }
- XVF_SnapData如果是基础类型,不需要调用UpdateData()
public hp: XVF_SnapData<number>; public setHP(hp:number):void { this.hp.value = hp; }
项目目录和命令
主要工程目录
对于开发者,需要关心和操作的目录如下:
- node_modules/ - 通过npm安装的PGT库文件,对外暴露的方法,可以通过bridge.d.ts来外部引用
- res-extra/ - 开发者除了PGT的远程资源外,需要额外使用到的资源目录,比如UI,图片,音频,表格,最后会打包上传到PGT远端资源服务器
- ui/ - 开发者自己在laya编辑器中,拼接的界面json文件,运行命令后,会转化为PGT指定的XUIComponent存放于此
- src/ - 开发者所有的战斗逻辑代码修改都在此进行
* src/client/ - 前端代码,入口文件index.ts,监听XPopManager.onGameStart,前端游戏逻辑 * src/server/ - 后端代码,入口文件index.ts,监听XPopManager.onHostStart,后端游戏逻辑 * src/shared/ - 前后端共用的数据结构,包括表格,协议,玩家数据
- dist/ - 编译后,生成的运行文件,包含前后端代码
* dist/client/ - 编译后生成的混淆的前端代码 * dist/host/ - 编译后服务端的代码文件,里面也包括表格数据的缓存
npm命令说明
以下是项目中常用的命令,和工作流相关,先简要说明用法,后续工作流中会继续补充。
npm run proto(协议通信)
该命令会用到tsrpc的proto协议, 把src/shared/protocols下的指定格式文件, 转换到src/shared/protocols/generated/serviceProto文件中,
- 文件名为:Ptl{接口名}.ts (Ptl 是 Protocol 的缩写,l是小写的L)
- 请求类型名为: Req{接口名},通过 interface 或 type 定义,需 export
- 响应类型名为:Res{接口名},通过 interface 或 type 定义,需 export
例如,添加PtlPosition.ts文件 文件代码如下
// 该接口用于向服务器同步自身的坐标 export interface ReqPosition { i: number; x: number; y: number; z: number; ry: number; } export interface ResPosition { ret: string; diy: string; }
在demo目录下运行 npm run proto后, serviceProto.ts中会增加可外部调用的api类型
export interface ServiceType { api: { "Position": { req: ReqPosition, res: ResPosition }, }, msg: { } }
前端代码调用请求
// 前端可以用promise语法来调用同步位置的Request,异步处理服务器的返回值 let remote = XPopManager.instance.xRemote; let ret = await remote.Request('Position', {i: 1, x:2, y:3, z:4, ry:5}); if(ret && ret.isSucc){ console.log(ret.res.diy) }
后端代码监听请求处理返回
// 服务器收到前端请求的处理返回RegisterRpc let host = XPopManager.instance.xHost; //当收到坐标变化请求 host.RegisterRpc("Position", async (call: ApiCall<ReqPosition, ResPosition>) => { let index = call.req.i; let userData = this.usersData.get(index); userData.setPosition(call.req.x, call.req.y, call.req.z, call.req.ry); return call.succ({ ret: "Success", diy: "自定义参数" }); });
如果想更多了解proto的结构和数据类型说明,可以参考官方链接 [tsrpc-proto格式说明](https://tsrpc.cn/docs/server/service-proto.html)
npm run build ( 编译构建 )
每次代码有修改时,如果要调试运行,必须先运行此命令
运行后,会在dist目录下生成混淆过后的可执行代码
此时VSCode编辑器可以直接F5运行
npm run ui ( 生成ui类 )
如果开发者有额外的ui交互需求,希望在IDE中自己拼接UI 可以在指定目录下,
- ui_laya/laya/ - 开发者可以自由扩展的ui资源目录
* ui_laya/laya/pages - 开发者创建的.scene文件目录 * ui_laya/laya/assets/uiextra - secne文件中引用到的各种美术资源,包括音频和动画
运行后,会在client目录代码中,生成对应的XUIComponent类,#XUIComponent
npm run server ( 启动本地host服务 )
启动一个本地host服务器, 局域网内其他用户在登录时输入你的房间号,就可以链接到你的本地游戏一起调试
npm run publish ( 打包文件 )
npm run upload( 上传文件 )
核心类目说明
XPopManager
XActor
XUIComponent
XStateMachine
地图的制作
地图官网地址
[地图网页](https://h5ppreview.jumpw.com/pgc/pgcedit0.0.2/index.html)
地图制作导出
在项目目录/地图编辑器操作说明中,有视频教程
地图测试权限申请
[论坛帖子](https://pgcbbs.popx.com/d/49-di-tu-shang-chuan-he-wan-fa-ce-shi-lin-shi-fang-an)
官方论坛
[论坛地址](https://pgcbbs.popx.com/)