[egret+pomelo]实时游戏杂记
Posted 枫之戊
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[egret+pomelo]实时游戏杂记相关的知识,希望对你有一定的参考价值。
服务端的请求流程走完了一遍,下面就该看一下,在目前的服务端中,各服务端所提供的功能了。
Gate:game-server/app/servers/gate/handler/gateHandler.js
queryEntry(msg,session,next):注册服务端,返回分配的connector服务端地址
Connector:game-server/app/servers/connector/handler/entryHandler.js
entry(msg, session, next):服务端注册session信息 返回玩家playerId
onUserLeave(app, session, reason):用户离开或关闭链接
Area:game-server/app/servers/area/handler/playerHandler.js
enterScene(msg, session, next):玩家申请加入游戏场景
getAnimation(msg, session, next):获取玩家动画数据
changeStage(msg, session, next):更改玩家状态
move(msg, session, next):玩家移动
这里还涉及到一个玩家离开场景事的调用game-server/app/servers/area/remote/playerRemote.js
目前服务端的使用已经很清晰了,要开始摒弃示例,可以开始自己的游戏逻辑了。第一步要做的,就是借助pomelo的捡宝项目,让多个玩家站在同一个场景中并显示。
整理egret代码
根据当前的服务端结构,创建服务器信息管理类network.Servers
module network { /** * 服务端信息 */ export class Servers { public constructor() { } /** * 服务端事件 * currServerDisConnect:当前服务端关闭 */ public static events = { currServerDisConnect: "DISCONNECT_SUCCEED" } /** * Gate模块 */ public static GATE = { KEY: "Server_GATE", info: { ip: "", port: "" }, handler: { queryEntry: "gate.gateHandler.queryEntry" }, events: { succeed: "CONNECTION_GATE_SUCCEED", error: "CONNECTION_GATE_ERROR" } }; /** * Connect 模块操作 */ public static CONNECTION = { KEY: "Server_CONNECTION", info: { ip: "", port: "" }, handler: { entry: "connector.entryHandler.entry", onUserLeave: "connector.entryHandler.onUserLeave" }, events: { succeed: "CONNECTION_CONNECT_SUCCEED", error: "CONNECTION_CONNECT_ERROR" } }; /** * 游戏场景服务器 */ public static AREA = { KEY: "Server_AREA", info: { ip: "", port: "" }, handler: { enterScene: "area.playerHandler.enterScene", getAnimation: "area.playerHandler.getAnimation", changeStage: "area.playerHandler.changeStage", move: "area.playerHandler.move" }, events: { succeed: "CONNECTION_AREA_SUCCEED", error: "CONNECTION_AREA_ERROR" } }; /** * 获取模块 * targetName:模块的名称 info/handler/events * key:模块的key */ public static GetTargetByKey(targetName: string, key: string) { var target; switch (key) { case Servers.GATE.KEY: target = Servers.GATE; break; case Servers.CONNECTION.KEY: target = Servers.CONNECTION; break; case Servers.AREA.KEY: target = Servers.AREA; break; default: console.log("发现未知服务端[network/servers/]"); break; } if (target) { switch (targetName) { case "info": return target.info; case "handler": return target.handler; case "events": return target.events; default: console.log("发现未知服务数据[network/servers/]"); break; } } } } }
完善socket链接类 network.GameSocket
module network { /** * webSocket for pomelo */ export class GameSocket { public constructor() { } static instance: GameSocket = new GameSocket(); /** * 单例模式 */ static getInstance(): GameSocket { return GameSocket.instance; } private pomelo: Pomelo; /** * 当前正在操作的是服务端 */ private currServer: Object; /** * 服务端状态 是否开启 */ private running: boolean = false; /** * 初始化 */ init() { if (this.pomelo == null) { this.pomelo = new Pomelo(); this.pomelo.on(\'server_push_message\', (msg) => { var route = msg["route"]; //根据服务端返回派发事件 Global.dispatchEvent("PomeloServerEvents_" + route, msg); }); this.pomelo.on(\'onKick\', (msg) => { trace("onKick"); }); this.pomelo.on(\'heartbeat_timeout\', () => { trace("heartbeat_timeout"); }); this.pomelo.on(\'close\', (e: CloseEvent) => { trace(e.currentTarget["url"] + "的链接被断开"); }); } } /** * 打开服务端 * @param server:需要打开的服务端 * @param host:ip * @param port:端口 * @param callback:回调函数 * @param log:是否启用日志 */ open(server, callback?: Function, log: boolean = true) { //获取服务端的设置 var targetEventsInfo = Servers.GetTargetByKey("events", server.KEY); //初始化服务端 this.pomelo.init({ host: server.info.ip, port: server.info.port, log: log }, false, (succeedRes) => { this.currServer = server; this.running = true; //派发服务端启动成功事件 Global.dispatchEvent(targetEventsInfo.succeed); }, (errRES) => { //派发服务端发生错误事件 Global.dispatchEvent(targetEventsInfo.error); }, (closeRes) => { trace("一个服务端关闭完成。"); }, null); } /** * 发起请求 * @param route: 路由 (服务端处理函数) * @param msg:内容 * @param callback:回调函数 * @param thisArg:参数 */ request(route: string, msg: any, callback: Function, thisArg?: any): void { this.pomelo.request(route, msg, (response) => { callback.call(thisArg, response); }); } /** * 通知 */ notify(route: string, msg: any): void { this.pomelo.notify(route, msg); } /** * 关闭当前服务 */ disconnect() { this.pomelo.disconnect(); this.running = false; Global.dispatchEvent(Servers.events.currServerDisConnect, { currServer: this.currServer }); } /** * 获取当前的服务端 */ getCurrServer() { return this.currServer; } /** * 获取当前的服务端状态 */ isRunning(): boolean { return this.running; } } }
之前例子中的PomeloTest变成
class PomeloTest { public constructor() { Global.addEventListener(network.Servers.GATE.events.succeed, this.onGateSucceed, this); Global.addEventListener(network.Servers.GATE.events.error, this.onGateError, this); Global.addEventListener(network.Servers.CONNECTION.events.succeed, this.onConnectSucceed, this); Global.addEventListener(network.Servers.CONNECTION.events.error, this.onConnectError, this); } connectGate() { network.GameSocket.getInstance().init(); network.GameSocket.getInstance().open(network.Servers.GATE); } private onGateSucceed() { Global.addEventListener(network.Servers.events.currServerDisConnect, this.onGateClosed, this); network.GameSocket.getInstance().request("gate.gateHandler.queryEntry", { uid: "" }, this.onGateMsg); trace("Gate服务端链接成功"); } private onGateError() { trace("Gate服务端链接失败"); } private onGateMsg(gate_data) { network.Servers.CONNECTION.info.ip=gate_data.host; network.Servers.CONNECTION.info.port=gate_data.port; network.GameSocket.getInstance().disconnect(); trace("正在尝试链接connect服务端..."); network.GameSocket.getInstance().open(network.Servers.CONNECTION); } private onGateClosed() { trace("Gate服务端成功断开链接"); // trace("正在尝试链接connect服务端..."); // config.global.pomelo.open(network.PomeloService.CONNECTION, this.connectIp, this.connectPort); } private onConnectSucceed() { trace("CONNECT服务端链接成功"); trace("开始注册服务端信息..."); network.GameSocket.getInstance().request(\'connector.entryHandler.entry\', { name: "" }, this.onEntryMsg); } private onConnectError() { trace("CONNECT服务端链接失败..."); } private onEntryMsg(entry_data) { if (entry_data.code === 200) { trace("注册信息成功"); trace("开始申请进入游戏..."); network.GameSocket.getInstance().request(\'area.playerHandler.enterScene\', { name: "", playerId: entry_data.playerId }, (respose) => { //Global.dispatchEvent(events.PomeloServerEvents.MAPMSG, respose); trace("进入游戏成功"); trace("开始解析地图信息"); }); } else { trace("注册服务端信息出现问题,请检查提交信息"); } } move(x: number, y: number, targetId: string) { network.GameSocket.getInstance().notify(\'area.playerHandler.move\', { targetPos: { x: x, y: y }, target: targetId }); } changeStage(s: string) { network.GameSocket.getInstance().notify(\'area.playerHandler.changeStage\', { S: s }); } }
因为服务端中多玩家的功能已经实现,这里不再继续赘述。只要找到对应的服务端方法 就可以进行服务端的逻辑代码修改。
例子中已经实现游戏的登录和进入服务端,下面来看一下服务端中关于游戏数据的返回值处理。
首先在游戏场景中申请游戏场景数据
network.GameSocket.getInstance().request(network.Servers.AREA.handler.enterScene, { name: this.txt_playerName.text, playerId: entry_data.playerId }, (respose) => { self.lbl_info.text = "进入游戏成功"; self.lbl_info.text = "开始解析地图信息"; console.log(respose); });
在服务端经过
在客户端console出来的结果 便是散落在地上的装备 数据
客户端的显示和玩家的移动通知处理,暂时不去做,因为和自己想要做的逻辑未必相同。至此已经大体了解pomelo的工作流程,和使用哪些处理器处理相关的业务逻辑,下节就要根据自己的需求设计游戏,遇见什么问题解决什么问题。
以上是关于[egret+pomelo]实时游戏杂记的主要内容,如果未能解决你的问题,请参考以下文章