• [egret+pomelo]实时游戏杂记(3)


    [egret+pomelo]学习笔记(1)

    [egret+pomelo]学习笔记(2)

    [egret+pomelo]学习笔记(3)

    服务端的请求流程走完了一遍,下面就该看一下,在目前的服务端中,各服务端所提供的功能了。

    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;
                    }
                }
            }
        }
    }
    View Code

    完善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;
            }
        }
    }
    View Code

     之前例子中的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 });
        }
    }
    View Code

    因为服务端中多玩家的功能已经实现,这里不再继续赘述。只要找到对应的服务端方法 就可以进行服务端的逻辑代码修改。

    egret例子下载

    例子中已经实现游戏的登录和进入服务端,下面来看一下服务端中关于游戏数据的返回值处理。

    首先在游戏场景中申请游戏场景数据

                        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的工作流程,和使用哪些处理器处理相关的业务逻辑,下节就要根据自己的需求设计游戏,遇见什么问题解决什么问题。

  • 相关阅读:
    java 根据对象属性排序
    无法初始化SFTP协议。主机是SFTP服务器吗
    Spring IOC 学习(三)IOC容器的依赖注入
    Spring-IOC学习-02 IOC容器初始化
    nginx简单使用
    Spring-IOC学习-01 IOC重要的几个接口定义
    Spring-IOC学习
    Http Service
    C#从入门到放弃--字符串类型转数字类型
    VS系列--快捷键的使用
  • 原文地址:https://www.cnblogs.com/z-yue/p/8116403.html
Copyright © 2020-2023  润新知