[egret+pomelo]實時遊戲雜記(3)

[egret+pomelo]學習筆記(1)html

[egret+pomelo]學習筆記(2)web

[egret+pomelo]學習筆記(3)服務器

 

服務端的請求流程走完了一遍,下面就該看一下,在目前的服務端中,各服務端所提供的功能了。session

Gate:game-server/app/servers/gate/handler/gateHandler.jsapp

queryEntry(msg,session,next):註冊服務端,返回分配的connector服務端地址

Connector:game-server/app/servers/connector/handler/entryHandler.jssocket

entry(msg, session, next):服務端註冊session信息 返回玩家playerId
onUserLeave(app, session, reason):用戶離開或關閉連接

Area:game-server/app/servers/area/handler/playerHandler.jside

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的工做流程,和使用哪些處理器處理相關的業務邏輯,下節就要根據本身的需求設計遊戲,碰見什麼問題解決什麼問題。

相關文章
相關標籤/搜索