队列管理器连接数设置_游戏开发之UI管理器(跨引擎)

使用UI管理器的目的

  1. 使用单场景与zindex结合的方式管理UI。
  2. 能够隐藏底层UI达到优化效果。
  3. 很好的组织和管理UI。
  4. 跨引擎使用。

管理器分类

根据以往经验我开发了三种类型的管理器,队列管理器,栈式管理器,单UI管理器。

  1. 单UI管理器:SingleManager负责管理如登录,loading,大厅,游戏这样的一级UI,同一时刻只有一个UI实例存在。UI之间是替换关系。
  2. 栈式管理器:StackManager用于管理先进后出的UI,弹出功能UI使用。
  3. 队列管理器:QueueManager用于管理先进先出的UI,用于第一次进入大厅弹出各种活动UI时候使用,关闭一个弹出另一个。
  4. 类图

将UI分为五层

  1. 第一层:使用单UI管理器用于管理,大厅,游戏等一级界面。
  2. 第二层:使用栈式管理器 管理二级界面
  3. 第三层:使用队列管理器用于管理进入游戏时弹出的各种活动面板。
  4. 第四层:使用栈式管理器用于管理toast,tip等提示框。
  5. 第五层:为最上层,使用栈式管理器,用于管理教学,对话界面和网络屏蔽层等。

特别说明:比如将一个战斗UI分为战斗层和按钮层,这个不属于管理器范畴。

  1. 结构图

代码

  1. 为了跨引擎使用,需要将各个引擎的组件抽象。 export default interface LayerInterface { exit(): void; /** * 设置组件是否可见 * @param f */ setVisible(f: boolean): void; /** * 设置组件节点的zroder * @param order */ setOrder(order: number): void; /** * * @param t 管理器层级 */ setUIIndex(t: number): void; getUIIndex(): number; /** * 获得组件的node */ getNode(): any; isLoad(): boolean;

}

2. 管理器的父类

import LayerInterface from "./LayerInterface"; export default abstract class LayerManager {

//根节点protected root: any;protected list: LayerInterface[]//管理器中的内容是否可以被删除protected popFlag: boolean = false;protected zOrder: number = 1;constructor(zOrder: number = 1, canPop: boolean = true) {    this.list = []    this.zOrder = zOrder;    this.popFlag = canPop;}init(node: any) {    this.root = node;}setZOrder(order: number) {    this.zOrder = order;}getZOrder(): number {    return this.zOrder;}canPop() {    return this.popFlag;}//ui数量count() {    return this.list.length;}setVisible(flag: boolean) {    for (let index = 0; index < this.list.length; index++) {        const element = this.list[index];        element.setVisible(flag)    }}//判断某个ui是否存在has(layer: LayerInterface) {    for (let index = 0; index < this.list.length; index++) {        const element = this.list[index];        if (layer === element) {            return true;        }    }    return false;}//添加layerabstract pushView(layer: LayerInterface): void;// 移除layerabstract popView(view: LayerInterface): boolean;//删除指定uiremoveView(layer: LayerInterface): boolean {    // logInfo(' LayerManger removeView ')    for (let index = 0; index < this.list.length; index++) {        const element: LayerInterface = this.list[index];        if (layer === element) {            element.exit();            this.list.splice(index, 1);            return true;        }    }    // console.warn(' removeView is not have ', layer, ' list ', this.list)    return false;}//清空所有uiclear() {    // logInfo(' LayerManger clear ')    for (let index = 0; index < this.list.length; index++) {        const element: LayerInterface = this.list[index];        element.exit();    }    this.list.length = 0;}

}

3. 单UI管理器

import LayerManager from "./LayerManager"; import LayerInterface from "./LayerInterface";

export default class SingleManager extends LayerManager {

pushView(view: LayerInterface) {    if (this.list.length > 0) {        this.removeView(this.list.shift())    }    this.list.push(view);    view.setOrder(this.zOrder);    this.root.addChild(view.getNode())}//不支持主动移除popView(view: LayerInterface) {    return false;}

}

4. 栈结构管理器

import LayerManager from "./LayerManager" import LayerInterface from "./LayerInterface" export default class StackLayerManager extends LayerManager {

//添加layerpushView(view: LayerInterface) {    this.list.push(view);    view.setOrder(this.zOrder)    this.root.addChild(view.getNode())}// 移除layerpopView(view: LayerInterface): boolean {    if (this.list.length > 0) {        let layerInfo = this.list.pop();        layerInfo.exit();        return true;    } else {        return false;    }}

}

5. 队列管理器

import LayerManager from "./LayerManager" import LayerInterface from "./LayerInterface"; export default class QueueLayerManager extends LayerManager {

//添加layerpushView(view: LayerInterface) {    this.list.push(view);    if (this.list.length == 1) {        this.show(view);    }}show(view: LayerInterface) {    view.setOrder(this.zOrder);    this.root.addChild(view.getNode())}// 移除layerpopView(view: any): boolean {    if (this.list.length > 0) {        let layerInfo = this.list.shift();        layerInfo.exit();        if (this.list.length > 0) {            this.show(this.list[0]);        }        return true;    } else {        return false;    }}

}

6. 所有管理器的整合

import LayerManager from "./LayerManager" import EventDispatcher from "../event/EventDispatcher"; import GlobalEvent from "../event/GlobalEvent"; import LayerInterface from "./LayerInterface";

export default class UIManager extends EventDispatcher {

private managers: LayerManager[] = [];private root: any;private static ins: UIManager;static instance(): UIManager {    if (!UIManager.ins) {        UIManager.ins = new UIManager();    }    return UIManager.ins;}constructor() {    super();    this.managers = [];}/** *  * @param uiIndex  * @param flag  */setVisible(uiIndex: number, flag: boolean) {    // logInfo('setVisible ', uiIndex, flag)    this.managers[uiIndex].setVisible(flag)}init(node: any) {    this.root = node}setManager(index: number, manager: LayerManager) {    this.managers[index] = manager;    this.managers[index].init(this.root)}/** * 清除UI */clear() {    for (let index = this.managers.length - 1; index >= 0; index--) {        const manager = this.managers[index];        if (manager.canPop() && manager.count() > 0) {            manager.clear()        }    }}//添加UIpushView(layer: LayerInterface) {    if (layer) {        let uiIndex = layer.getUIIndex()        let manager = this.managers[uiIndex];        if (!manager) {            console.log(' manager is null ', layer)            return;        }        layer.setUIIndex(uiIndex)        manager.pushView(layer);        this.getOpenUICount();    }}/** * 此方法用于关闭界面,为了兼容Android的back键 所以layer有为null的情况。 * 如果 返回false 表明已经没有界面可以弹出,此时就可以弹出是否退出游戏提示了。 * @param layer  */popView(layer?: LayerInterface) {    // console.log('popView layer is ', layer)    let flag = false;    if (layer) {        let index: number = layer.getUIIndex()        // console.log(' popView  index is ', index, ' layer is ', layer)        let manger = this.managers[index];        if (!manger) {            // console.log(' popView layer is not found type is ', type)            flag = false;        } else {            flag = manger.popView(layer);        }    } else {        for (let index = this.managers.length - 1; index >= 0; index--) {            const manager = this.managers[index];            if (manager.canPop() && manager.count() > 0) {                if (manager.popView(null)) {                    flag = true;                    break;                }            }        }    }    return flag;}//获得当前存在的ui的数量getOpenUICount() {    let count: number = 0;    for (let index = this.managers.length - 1; index >= 0; index--) {        const manager = this.managers[index];        if (manager.canPop()) {            count += manager.count()        }    }    return count;}

}

7.  所有组件的父类

import LayerInterface from "../cfw/ui/LayerInterface"; import { UIIndex } from "../cfw/tools/Define";

const { ccclass, property } = cc._decorator;

@ccclass export default class EngineView extends cc.Component implements LayerInterface {

private uiIndex: number = 0;protected loadFlag: boolean = false;isLoad() {    return this.loadFlag}start() {    this.loadFlag = true;}exit() {    this.node.destroy()}setVisible(f: boolean): void {    this.node.active = f;}setOrder(order: number): void {    this.node.zIndex = order;}setUIIndex(t: UIIndex): void {    this.uiIndex = t;}getUIIndex(): UIIndex {    return this.uiIndex}getNode() {    return this.node;}show() {    UIManager.instance().pushView(this)}hide(){    UIManager.instance().popView(this)}

}

8. 使用方式定义层级枚举

//ui分层 export enum UIIndex { ROOT,//最底层 STACK,//堆栈管理 QUEUE,//队列管理 TOAST,// TOP,//永远不会清除的ui层 }

初始化:![image.png](https://upload-images.jianshu.io/upload_images/11168392-378df6deb1cf8130.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)封装函数:

/** * 将ui添加到管理器中。 * @param prefab 预制体麓景 * @param className 组件类型 * @param model 模型 * @param uiIndex ui管理器层级 * @param loader 加载器 * @param func 加载成功回调 */ pushView(prefab: string, className: string, c: BaseController, model: any, uiIndex: UIIndex = UIIndex.STACK, loader: ResLoader, func?: Function) { if (this.viewMap.has(prefab)) { console.warn(' pushVIew ', this.viewMap.has(prefab)) return; } this.viewMap.set(prefab, 1) this.pushToast(prefab, className, c, model, uiIndex, loader, (comp) => { // console.log(' delete viewMap ', prefab) this.viewMap.delete(prefab) if (func) { func(comp)

        }    })}/** *  * @param prefabName 预制体的名称 * @param callback 加载后的回调。 */getPrefab(prefabName: string, loader: ResLoader, callback: (err: string, node?: cc.Node) => void) {    let resName = "";    if (prefabName.indexOf("/") >= 0) {        resName = prefabName;        let list = prefabName.split("/");        prefabName = list[list.length - 1];    } else {        resName = "prefabs/" + prefabName;    }    loader.loadRes(resName, ResType.Prefab,        (err, item: ResItem) => {            if (err) {                callback(" UIManager getComponent err " + err);                return;            }            //这里可以配合对象池使用。            let node = cc.instantiate(item.getRes())            if (node) {                callback(null, node);            } else {                callback("node is null");            }        });}
这里边有个一小的处理,就是当一个UI成功加载后才会弹出另一个UI,避免的按钮被连续点击弹出多个UI的情况。使用:

this.pushView('LoginView', 'LoginView', null, ModuleManager.getLoader(), UIIndex.ROOT)

```

结语

欢迎扫码关注公众号《微笑游戏》,浏览更多内容。

c804885e0c34ef64f2317416931af537.png

欢迎扫码关注公众号《微笑游戏》,浏览更多内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值