JM_KA/assets/Script/Engine/Timer/Timer.ts
2022-08-26 16:48:17 +08:00

199 lines
6.2 KiB
TypeScript

import { CoroutineV2 } from "../CatanEngine/CoroutineV2/CoroutineV2";
import { ActionWithType } from "../CatanEngine/CSharp/System/ActionWithType";
import { NumberEx } from "../Utils/Number/NumberEx";
class TimerEvent extends ActionWithType<number, any> { }
/**
* 計時器(使用CoroutineV2)
*/
export class Timer {
//#region public
/** 訊息資料 */
public static Component: cc.Component;
//#endregion
//#region private
/** 訊息資料 */
private static Group: Map<any, TimerDataClass> = new Map<any, TimerDataClass>();
//#endregion
//#region static
/**
* 啟動計時
* @param {number} time 計時(seconds)
* @param {Function} callback Function
* @param {any} type (選填) 可以識別的東西
* @param {any} bindTarget (選填) 回呼時this綁定的對象
* @example
* Timer.Start(1, () => { console.log(`example`); });
* Timer.Start(1, () => { console.log(`example`); }, "example");
* Timer.Start(1, () => { console.log(`example`); }, "example", this);
*/
public static Start(time: number, callback: Function, bindTarget?: any, type?: any): void {
let self: typeof Timer = this;
let thistype: any = type;
if (!type) {
thistype = callback;
}
if (Timer.Group.has(thistype)) {
cc.error(`Timer Start Error Timer.Group.has(${thistype})`);
return;
}
let timerData: TimerDataClass = new TimerDataClass(thistype, time, callback, bindTarget);
Timer.Group.set(thistype, timerData);
let Coroutine_F: Generator<any, void, any> = function* (): Generator<any, void, any> {
yield CoroutineV2.WaitTime(time).Start(bindTarget);
if (Timer.Group.has(thistype)) {
self._callback(timerData.Type, timerData.Callback, timerData.BindTarget);
}
}();
CoroutineV2.Single(Coroutine_F).Start(bindTarget);
}
/**
* 刪除計時 By Target
* @param {any} target target
* @example
* Timer.ClearByTarget(this);
*/
public static ClearByTarget(target: any): void {
let timerData_Group: TimerDataClass[] = [];
Timer.Group.forEach(timerData => {
if (timerData.BindTarget === target) {
timerData_Group.push(timerData);
}
});
if (timerData_Group.length === 0) {
cc.warn(`Timer Clear Error Timer.Group.has not target`);
return;
}
for (let i: number = 0; i < timerData_Group.length; i++) {
let timerData: TimerDataClass = timerData_Group[i];
let type: any = timerData.Type;
Timer.Group.delete(type);
timerData = null;
}
CoroutineV2.StopCoroutinesBy(target);
}
/**
* 刪除計時 By Type
* @param PS 還是會吃效能在倒數 只是時間到不會執行
* @param {any} type type
* @example
* Timer.ClearByType("example");
*/
public static ClearByType(type: any): void {
let timerData_Group: TimerDataClass[] = [];
Timer.Group.forEach(timerData => {
if (timerData.Type === type) {
timerData_Group.push(timerData);
}
});
if (timerData_Group.length === 0) {
cc.warn(`Timer Clear Error Timer.Group.has not type`);
return;
}
for (let i: number = 0; i < timerData_Group.length; i++) {
let timerData: TimerDataClass = timerData_Group[i];
let type: any = timerData.Type;
Timer.Group.delete(type);
}
}
/**
* 結束計時時callback
* @param {Function} callback Function
*/
private static _callback(type: any, callback: Function, bindTarget: any): void {
if (Timer.Group.has(type)) {
Timer.Group.delete(type);
}
if (bindTarget) {
callback.bind(bindTarget)();
} else {
callback();
}
}
/**
* 定時事件(時間用 updateTime秒跑一次fn)
* @param startNum 起始index
* @param endNum 結束index
* @param updateTime 事件刷新間隔
* @param callbackfn 事件
* @example
* let startNum: number = 10;
* let endNum: number = 0;
* let updateTime: number = 1;
* yield CoroutineV2.Single(Timer.Timing(
* startNum,
* endNum,
* updateTime,
* (x: number) => {
* console.log(`x: ${x}`);
* }
* )).Start(this);
*/
public static *Timing(startNum: number, endNum: number, updateTime: number, callbackfn: Function): IterableIterator<any> {
let isIncrease: boolean = endNum >= startNum;
let totalCount: number = Math.abs(endNum - startNum) + 1;
let nowCount: number = NumberEx.divide(totalCount, updateTime);
let diff: number = NumberEx.divide(totalCount, nowCount) * (isIncrease ? 1 : -1);
let tempScore: number = startNum;
callbackfn(startNum);
while (true) {
if (endNum !== tempScore) {
yield CoroutineV2.WaitTime(updateTime);
tempScore += diff;
// 遞增
if (isIncrease && tempScore > endNum) {
tempScore = endNum;
}
// 遞減
if (!isIncrease && tempScore < endNum) {
tempScore = endNum;
}
callbackfn(Math.floor(tempScore));
} else {
break;
}
}
}
//#endregion
}
//#region Class
/** Timer資料 */
export class TimerDataClass {
/** Type */
public Type: any = null;
/** Time */
public Time: number = null;
/** Callback */
public Callback: Function = null;
/** BindTarget */
public BindTarget?: any = null;
constructor(type: any, time: number, callback: Function, bindTarget?: any) {
this.Type = type;
this.Time = time;
this.Callback = callback;
this.BindTarget = bindTarget;
}
}
// //#endregion