Egret开发笔记[五]:一个状态变化牵扯多对象方法处理法

文章目录

      • 为何采用这种方法
      • 实例分析:红点状态改变
      • RedPointManager
      • 使用方法

为何采用这种方法

一个状态的改变牵扯多个对象,比如玩家获取了一件物品.此时可以解锁某个关卡,也还使得玩家战力提升,还使得玩家可以拥有更多的背包格子.
好像可以用事件的处理机制来处理这种事情,当玩家获取物品时,派发事件,在多个事件里面监听.
但是这种有个弊端,并不是同步,且针对性不强,且无法及时去除事件的监听.

实例分析:红点状态改变

很多游戏控件上,如果有新内容需要显示红点,点击后红点消失.好像十分简单,但是随着项目不断变得复杂,红点牵扯到的东西越来越多.比如有个宝箱上的红点显示条件为:玩家为vip且等级为4,玩家没有加入家族,玩家人物等级大于30.当宝箱被点击,红点消失时,关于红点要发生下面事件:1.告诉服务器,玩家这个红点过了.2.玩家获得一个免费领取的奖品.

RedPointManager

红点管理器
以下四个属性

	//caller对象的词典
	private _callerOfHashCode: { [hashCode: string]: any }
	//回调词典
	private _callbackOfHashCode: { [hashCode: string]: { callback: (haveUnread: boolean) => void, caller: any } };
	//对象所注册的keys
	private _keysOfhashCode: { [hashCode: string]: string[] };
	//某个key对应被注册的对象
	private _hashCodesOfKey: { [key: string]: string[] };
	//键值对
	private _valueOfKey: { [key: string]: boolean };

对这四个属性的操作将实现这个功能.当我们要开始将一个函数关联到红点的时候,将会把函数所在对象储存进 _callerOfHashCode,hashCode做为键值对中的键是对象名,将函数储存到 _callbackOfHashCode .
一个函数有可能关联多个红点 ,_keysOfhashCode正是用来记录这个,键用的就是 hashCode 值用的就是红点名,我们事先将红点定义相关名字,比如

class UnreadDefine {
	/**
	 * 背包上红点
	 */
	static EDS_RANK_BE_REPLACED:string = "EDS_RANK_BE_REPLACED";
	/**
	 * 宝箱上红点
	 */
	static TOP_BATTLE_IN_TIME:string = "TOP_BATTLE_IN_TIME";

	public constructor() {
	}
}

"key"这个键是字符串类型,正是红点名.当一个红点发生改变,需要通过红点名获取所有的 hashCode 再通过 hashCode 获取对应的函数并执行.那么 _hashCodesOfKey 就是红点名对应的所有 hashCode.
最后一个属性 _valueOfKey 是储存红点的状态,true 则显示红点, false 不显示.
以下展示整个对象的逻辑.

class UnreadManager {
	//caller对象的词典
	private _callerOfHashCode: { [hashCode: string]: any }
	//回调词典
	private _callbackOfHashCode: { [hashCode: string]: { callback: (haveUnread: boolean) => void, caller: any } };
	//对象所注册的keys
	private _keysOfhashCode: { [hashCode: string]: string[] };
	//某个key对应被注册的对象
	private _hashCodesOfKey: { [key: string]: string[] };
	//键值对
	private _valueOfKey: { [key: string]: boolean };

	public constructor() {
		this._callerOfHashCode = {};
		this._callbackOfHashCode = {};
		this._keysOfhashCode = {};
		this._hashCodesOfKey = {};
		this._valueOfKey = {};
	}

	public registerUnread(keys: string[], callback: (haveUnread: boolean) => void, caller: any): void {
		var hashCode: string = FW.getQualifiedClassName(caller);
		this._callerOfHashCode[hashCode] = caller;
		let len: number = keys.length;
		let i: number = len - 1;
		if (!this._callbackOfHashCode[hashCode]) {
			this._callbackOfHashCode[hashCode] = { callback: callback, caller: caller };
		}
		if (!this._keysOfhashCode[hashCode]) {
			this._keysOfhashCode[hashCode] = [];
		}
		len = keys.length;
		i = len - 1;
		while (i >= 0) {
			if (!this._hashCodesOfKey[keys[i]]) {
				this._hashCodesOfKey[keys[i]] = [];
			}
			this._hashCodesOfKey[keys[i]].push(hashCode);
			i--;
		}
		this._keysOfhashCode[hashCode] = this._keysOfhashCode[hashCode].concat(keys);//key重复这里就不管了。
		this.notifyWithHashCode(hashCode);
	}

	public unregisterUnread(keys: string[], caller: any): void {
		var hashCode: string = FW.getQualifiedClassName(caller);

		//移除对象所注册的keys
		let len: number = this._keysOfhashCode[hashCode].length;
		let i: number = len - 1;
		while (i >= 0) {
			let key: string = this._keysOfhashCode[hashCode][i];
			if (keys.indexOf(key) >= 0) {
				this._keysOfhashCode[hashCode].splice(i, 1);
			}
			i--;
		}

		//移除caller对象的词典
		if (this._keysOfhashCode[hashCode].length == 0) {
			delete this._callerOfHashCode[hashCode];
			delete this._callbackOfHashCode[hashCode];
		}

		//移除某个key对应被注册的对象
		for (let i: number = 0; i < keys.length; i++) {
			let key: string = keys[i];
			let hashCodes = this._hashCodesOfKey[key];
			let len: number = hashCodes.length;
			let j: number = len - 1;
			while (j >= 0) {
				if (hashCodes[j] == hashCode) {
					hashCodes.splice(j, 1);
				}
				j--;
			}
		}

	}

	/**
	 * 更新值 参数value: 设置为未读为true,已读为false
	 * @param value 设置为未读为true,已读为false
	 */
	public updateUnreadValue(key: string, value: boolean): void {
		this._valueOfKey[key] = value;
		var hashCodes: string[] = this._hashCodesOfKey[key];
		if (!hashCodes) {//如果没有注册了的对象,直接返回
			return;
		}

		let len: number = hashCodes.length;
		let i: number = len - 1;
		while (i >= 0) {
			this.notifyWithHashCode(hashCodes[i]);
			i--;
		}
	}

	private notifyWithHashCode(hashCode: string): void {
		let value: boolean = this.getObjectValue(hashCode);
		let vo = this._callbackOfHashCode[hashCode];
		vo.callback.apply(vo.caller, [value]);
	}

	private getObjectValue(hashCode: string): boolean {
		var keys: string[] = this._keysOfhashCode[hashCode];
		if (!keys) {
			return false;
		}
		let len: number = keys.length;
		let i: number = len - 1;
		while (i >= 0) {
			if (this._valueOfKey[keys[i]]) {
				return true;
			}
			i--;
		}
		return false;
	}
}

使用方法

将一个函数关联到红点.

class RankingLintBtn {
    constructor(): void {
            var flags:string[] = [
            UnreadDefine.CBFL_BONUS_CAN_GET,
            UnreadDefine.RANK_LIST_FIRST_7_DAYS
        ];
    	unreadManager.registerUnread(flags,this.onUnread,this);
    }
     /**
     * 按钮点击,隐藏红点
     */
    private onClick(value:boolen): void {
        if(value){
            //当红点改变状态切变为显示的时候执行此处逻辑
        }else{
            //与上同理
        }
    }
}

当需要改变状态时

unreadManager.updateUnreadValue(UnreadDefine.RANK_LIST_FIRST_7_DAYS,true);

当需要注销关联时则调用 unregisterUnread() 方法

你可能感兴趣的:(Egret学习笔记)