一个状态的改变牵扯多个对象,比如玩家获取了一件物品.此时可以解锁某个关卡,也还使得玩家战力提升,还使得玩家可以拥有更多的背包格子.
好像可以用事件的处理机制来处理这种事情,当玩家获取物品时,派发事件,在多个事件里面监听.
但是这种有个弊端,并不是同步,且针对性不强,且无法及时去除事件的监听.
很多游戏控件上,如果有新内容需要显示红点,点击后红点消失.好像十分简单,但是随着项目不断变得复杂,红点牵扯到的东西越来越多.比如有个宝箱上的红点显示条件为:玩家为vip且等级为4,玩家没有加入家族,玩家人物等级大于30.当宝箱被点击,红点消失时,关于红点要发生下面事件:1.告诉服务器,玩家这个红点过了.2.玩家获得一个免费领取的奖品.
红点管理器
以下四个属性
//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() 方法