[egret+pomelo]实时游戏杂记(2)
pomelo
pomelo服务端介绍(game-server/config/server.json):
{ "development": { "connector": [ {"id": "connector-server-1", "host": "127.0.0.1", "port": 3150, "clientPort": 3010, "frontend": true}, {"id": "connector-server-2", "host": "127.0.0.1", "port": 3151, "clientPort": 3011, "frontend": true} ], "area": [ {"id": "area-server-1", "host": "127.0.0.1", "port": 3250, "areaId": 1} ], "gate": [ {"id": "gate-server-1", "host": "127.0.0.1", "clientPort": 3014, "frontend": true} ] } }
可以看出,服务端是由以下几个部分构成:
* 2 个 `connector` 服务器,主要用于接受和发送消息。
* 1 个 `gate` 服务器,主要用于负载均衡,将来自客户端的连接分散到两个 `connector` 服务器上。
* 1 个 `area` 服务器,主要用于驱动游戏场景,和游戏逻辑
由服务端的关系图可以看出,访问pomelo,首先应该访问gate服务端,让服务端为其分配合适的connector以处理当前用户的请求。
egret
1.链接gate服务端,将玩家名称传递给gate服务端以作为注册
config.global.pomelo.request("gate.gateHandler.queryEntry", { uid: config.global.playerName }, this.onGateMsg);
2.当gate服务端链接返回成功后,链接gate服务端返回的地址,链接分配给自己的connector服务端
private onGateMsg(gate_data) { this.connectIp = gate_data.host; this.connectPort = gate_data.port; config.global.pomelo.disconnect(); trace("正在尝试链接connect服务端..."); config.global.pomelo.open(network.PomeloService.CONNECTION, this.connectIp, this.connectPort); }
3.使用connector.entryHandler.entry在connector中注册,注册成功后,使用area.playerHandler.enterScene访问游戏场景信息
private onConnectSucceed() { trace("CONNECT服务端链接成功"); trace("开始注册服务端信息..."); config.global.pomelo.request('connector.entryHandler.entry', { name: config.global.playerName }, this.onEntryMsg); } private onEntryMsg(entry_data) { if (entry_data.code === 200) { trace("注册信息成功"); trace("开始申请进入游戏..."); config.global.pomelo.request('area.playerHandler.enterScene', { name: config.global.playerName, playerId: entry_data.playerId }, (respose) => { Global.dispatchEvent(events.PomeloServerEvents.MAPMSG, respose); trace("进入游戏成功"); trace("开始解析地图信息"); }); } else { trace("注册服务端信息出现问题,请检查提交信息"); } }
4.游戏中会将地下散落的物品、玩家的位置以json格式返回 给客户端(返回的数据示例)
{ "code": 200, "data": { "area": { "id": "1", "entities": { "1": { "x": 2041, "y": 256, "entityId": 1, "kindId": "3", "kindName": "极限法剑", "areaId": 1, "type": "treasure", "imgId": 301804, "score": 20 }, "2": { "x": 1354, "y": 633, "entityId": 2, "kindId": 86, "kindName": "威严腿铠", "areaId": 1, "type": "treasure", "imgId": 344721, "score": 80 }, "3": { "x": 719, "y": 460, "entityId": 3, "kindId": 103, "kindName": "护身符", "areaId": 1, "type": "treasure", "imgId": 980057, "score": 1 }, "4": { "x": 246, "y": 1003, "entityId": 4, "kindId": 64, "kindName": "玉树Belt", "areaId": 1, "type": "treasure", "imgId": 371501, "score": 25 }, "5": { "x": 1343, "y": 426, "entityId": 5, "kindId": 15, "kindName": "紧身衣", "areaId": 1, "type": "treasure", "imgId": 331203, "score": 21 }, "6": { "x": 417, "y": 336, "entityId": 6, "kindId": 75, "kindName": "幻彩玉带", "areaId": 1, "type": "treasure", "imgId": 374224, "score": 90 }, "7": { "x": 1311, "y": 262, "entityId": 7, "kindId": 73, "kindName": "百窜云", "areaId": 1, "type": "treasure", "imgId": 374222, "score": 80 }, "8": { "x": 1385, "y": 870, "entityId": 8, "kindId": 57, "kindName": "荧光坠子", "areaId": 1, "type": "treasure", "imgId": 384921, "score": 71 }, "9": { "x": 432, "y": 1044, "entityId": 9, "kindId": 111, "kindName": "灵魂之石", "areaId": 1, "type": "treasure", "imgId": 90102, "score": 85 }, "10": { "x": 910, "y": 451, "entityId": 10, "kindId": 21, "kindName": "锁子甲", "areaId": 1, "type": "treasure", "imgId": 334303, "score": 80 }, "11": { "x": 982, "y": 160, "entityId": 11, "kindId": 21, "kindName": "锁子甲", "areaId": 1, "type": "treasure", "imgId": 334303, "score": 80 }, "12": { "x": 746, "y": 374, "entityId": 12, "kindId": 32, "kindName": "流云", "areaId": 1, "type": "treasure", "imgId": 394224, "score": 64 }, "13": { "x": 894, "y": 827, "entityId": 13, "kindId": 32, "kindName": "流云", "areaId": 1, "type": "treasure", "imgId": 394224, "score": 64 }, "14": { "x": 1027, "y": 724, "entityId": 14, "kindId": 73, "kindName": "百窜云", "areaId": 1, "type": "treasure", "imgId": 374222, "score": 80 }, "15": { "x": 699, "y": 156, "entityId": 15, "kindId": 60, "kindName": "Belt", "areaId": 1, "type": "treasure", "imgId": 371101, "score": 1 }, "16": { "x": 881, "y": 792, "entityId": 16, "kindId": 109, "kindName": "圣母之镜", "areaId": 1, "type": "treasure", "imgId": 90412, "score": 61 }, "17": { "x": 1442, "y": 96, "entityId": 17, "kindId": 62, "kindName": "银Belt", "areaId": 1, "type": "treasure", "imgId": 371201, "score": 13 }, "18": { "x": 1754, "y": 265, "entityId": 18, "kindId": 84, "kindName": "独孤腿铠", "areaId": 1, "type": "treasure", "imgId": 344701, "score": 66 }, "19": { "x": 1384, "y": 279, "entityId": 19, "kindId": 13, "kindName": "布衣", "areaId": 1, "type": "treasure", "imgId": 331103, "score": 1 }, "20": { "x": 1277, "y": 439, "entityId": 20, "kindId": 108, "kindName": "钻石之星", "areaId": 1, "type": "treasure", "imgId": 90472, "score": 51 }, "21": { "x": 53, "y": 313, "entityId": 21, "kindId": 53, "kindName": "骷髅吊坠", "areaId": 1, "type": "treasure", "imgId": 381701, "score": 31 }, "22": { "x": 965, "y": 367, "entityId": 22, "kindId": 73, "kindName": "百窜云", "areaId": 1, "type": "treasure", "imgId": 374222, "score": 80 }, "23": { "x": 146, "y": 94, "entityId": 23, "kindId": 69, "kindName": "攫魂铃", "areaId": 1, "type": "treasure", "imgId": 371803, "score": 55 }, "24": { "x": 374, "y": 400, "entityId": 24, "kindId": 100, "kindName": "荒芜之鞋", "areaId": 1, "type": "treasure", "imgId": 364724, "score": 70 }, "25": { "x": 1668, "y": 807, "entityId": 25, "kindId": 105, "kindName": "先祖护符", "areaId": 1, "type": "treasure", "imgId": 980055, "score": 21 }, "26": { "x": 875, "y": 384, "entityId": 26, "kindId": 39, "kindName": "布帽", "areaId": 1, "type": "treasure", "imgId": 321101, "score": 17 }, "27": { "x": 1799, "y": 146, "entityId": 27, "kindId": 105, "kindName": "先祖护符", "areaId": 1, "type": "treasure", "imgId": 980055, "score": 21 }, "28": { "x": 1543, "y": 384, "entityId": 28, "kindId": 31, "kindName": "风云雷电", "areaId": 1, "type": "treasure", "imgId": 394223, "score": 56 }, "29": { "x": 668, "y": 1083, "entityId": 29, "kindId": 73, "kindName": "百窜云", "areaId": 1, "type": "treasure", "imgId": 374222, "score": 80 }, "30": { "x": 1884, "y": 420, "entityId": 30, "kindId": 61, "kindName": "缎带", "areaId": 1, "type": "treasure", "imgId": 371103, "score": 7 }, "31": { "x": 2022, "y": 715, "entityId": 31, "kindId": 48, "kindName": "媚狐头饰", "areaId": 1, "type": "treasure", "imgId": 324701, "score": 85 }, "32": { "x": 1568, "y": 1138, "entityId": 32, "kindId": "9", "kindName": "丰城剑", "areaId": 1, "type": "treasure", "imgId": 304504, "score": 68 }, "33": { "x": 1219, "y": 747, "entityId": 33, "kindId": 63, "kindName": "水晶Belt", "areaId": 1, "type": "treasure", "imgId": 371401, "score": 19 }, "34": { "x": 1696, "y": 1146, "entityId": 34, "kindId": 16, "kindName": "鳞甲", "areaId": 1, "type": "treasure", "imgId": 331303, "score": 31 }, "35": { "x": 881, "y": 563, "entityId": 35, "kindId": 54, "kindName": "苍魂珠", "areaId": 1, "type": "treasure", "imgId": 384222, "score": 41 }, "36": { "x": 1983, "y": 456, "entityId": 36, "kindId": 101, "kindName": "玉衡之履", "areaId": 1, "type": "treasure", "imgId": 364803, "score": 85 }, "37": { "x": 268, "y": 164, "entityId": 37, "kindId": 88, "kindName": "斩魂腿甲", "areaId": 1, "type": "treasure", "imgId": 344922, "score": 90 }, "38": { "x": 1373, "y": 1047, "entityId": 38, "kindId": "8", "kindName": "寒雪枪", "areaId": 1, "type": "treasure", "imgId": 304501, "score": 60 }, "39": { "x": 964, "y": 790, "entityId": 39, "kindId": 26, "kindName": "折扇", "areaId": 1, "type": "treasure", "imgId": 391201, "score": 18 }, "40": { "x": 1257, "y": 1099, "entityId": 40, "kindId": 66, "kindName": "白面狼牙", "areaId": 1, "type": "treasure", "imgId": 371601, "score": 37 }, "54": { "x": 436, "y": 208, "entityId": 54, "kindId": 210, "areaId": 1, "id": 214, "type": "player", "name": "ss", "walkSpeed": 240, "score": 0 } }, "width": 2200, "height": 1201 }, "playerId": 214 } }
5.客户端根据返回的json,显示装备和玩家位置,并监听服务端中的移动以及状态更改事件,来做出相应的操作。
下面来看一下,pomelo服务端中是怎么处理前端的请求的。
在treasures的项目文档docs/tutorial.md 中给出的示例如下图
在(1)中,客户端通过pomelo.request方法,将gate.gateHandler.queryEntry 以及参数 uid 传递给gate服务端,下一步,我们进入服务端看一下(2)路径中的gateHandler文件
该方法为当前用户获取一个connector服务端,将用户uid参数与获取到的connector服务端绑定,并将分配后的connector服务端的获取状态code,链接host,端口port,返回给客户端进行处理,客户端在通过gate服务端接收到返回的参数后,就可以将gate服务端断开,然后链接分配给自己的connector服务端进行链接,通过 connector.entryHandler.entry,connector服务端会在用户第一次链接的时候初始化session信息,这样每次的服务端请求的时候,都不用再次 传递多余的数据。
entry方法成功后会向用户返回一个状态code 和玩家唯一标识playerId,客户端记住玩家唯一标识,以区分同场景中多个玩家时,哪一个玩家为自己的玩家。
这样一条用户请求和服务端返回的流程就走完了。