Files
oops-plugin-framework/assets/core/common/manager/TimerManager.ts
2022-09-02 14:54:04 +08:00

313 lines
9.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { Component } from "cc";
import { StringUtil } from "../../utils/StringUtil";
import { EventDispatcher } from "../event/EventDispatcher";
/** 时间管理 */
export class TimerManager extends EventDispatcher {
private static times: any = {};
private schedules: any = {};
private scheduleCount: number = 1;
private initTime: number = (new Date()).getTime(); // 当前游戏进入的时间毫秒值
private component: Component;
// 服务器时间与本地时间同步
private serverTime: number = 0;
/**
* 构造函数
* @param component cc.Component对象
*/
constructor(component: Component) {
super();
this.component = component;
this.schedule(this.onUpdate.bind(this), 1);
}
/**
* 服务器时间与本地时间同步
* @param val 服务器时间刻度
*
*/
setServerTime(val?: number): number {
if (val) {
this.serverTime = val;
}
return this.serverTime;
}
/**
* 格式化日期显示
* @param format 格式化字符串yyyy-MM-dd hh:mm:ss
* @param date 时间对象
*/
format(format: string, date: Date): string {
let o: any = {
"M+": date.getMonth() + 1, // month
"d+": date.getDate(), // day
"h+": date.getHours(), // hour
"m+": date.getMinutes(), // minute
"s+": date.getSeconds(), // second
"q+": Math.floor((date.getMonth() + 3) / 3), // quarter
"S": date.getMilliseconds() // millisecond
}
if (/(y+)/.test(format)) {
format = format.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
}
for (let k in o) {
if (new RegExp("(" + k + ")").test(format)) {
format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length));
}
}
return format;
}
/** 获取游戏开始到现在逝去的时间 */
getTime(): number {
return this.getLocalTime() - this.initTime;
}
/** 获取本地时间刻度 */
getLocalTime(): number {
return Date.now();
}
/**
* 注册一个固定间隔时间的触发器
* @param callback 触发时的回调方法
* @param interval 固定间隔触发时间
* @returns string
* @example
oops.timer.schedule(()=>{
// 每秒触发一次
}, 1000);
*/
schedule(callback: Function, interval: number): string {
let uuid = `schedule_${this.scheduleCount++}`
this.schedules[uuid] = callback;
this.component.schedule(callback, interval);
return uuid;
}
/**
* 注册一个只触发一次的延时的触发器
* @param callback 触发时的回调方法
* @param delay 延时触发时间
* @returns string
* @example
oops.timer.scheduleOnce(()=>{
// 1秒后触发一次后不会在触发
}, 1000);
*/
scheduleOnce(callback: Function, delay: number = 0): string {
let uuid = `scheduleOnce_${this.scheduleCount++}`;
this.schedules[uuid] = callback;
this.component.scheduleOnce(() => {
let cb = this.schedules[uuid];
if (cb) {
cb();
}
this.unschedule(uuid);
}, Math.max(delay, 0));
return uuid;
}
/**
* 删除一个时间触发器
* @param uuid 唯一标识
* @example
var uuid = oops.timer.schedule(()=>{
// 每秒触发一次
}, 1000);
// 删除指定标识的触发器
oops.timer.unschedule(uuid);
*/
unschedule(uuid: string) {
let cb = this.schedules[uuid];
if (cb) {
this.component.unschedule(cb);
delete this.schedules[uuid];
}
}
/** 删除所有时间触发器 */
unscheduleAll() {
for (let k in this.schedules) {
this.component.unschedule(this.schedules[k]);
}
this.schedules = {};
}
private onUpdate(dt: number) {
// 后台管理倒计时完成事件
for (let key in TimerManager.times) {
let data = TimerManager.times[key];
if (data.object[data.field] > 0) {
data.object[data.field]--;
if (data.object[data.field] == 0) {
this.onTimerComplete(data);
}
else { // 修改是否完成状态
if (data.onSecond) {
data.onSecond.call(data.object); // 触发每秒回调事件
}
}
}
}
}
/** 触发倒计时完成事件 */
private onTimerComplete(data: any) {
if (data.onComplete) data.onComplete.call(data.object);
if (data.event) this.dispatchEvent(data.event);
}
/**
* 在指定对象上注册一个倒计时的回调管理器
* @param object 注册定时器的对象
* @param field 时间字段
* @param onSecond 每秒事件
* @param onComplete 倒计时完成事件
* @returns
* @example
export class Test extends Component {
private timeId!: string;
start() {
// 在指定对象上注册一个倒计时的回调管理器
this.timeId = oops.timer.register(this, "countDown", this.onSecond, this.onComplete);
}
private onSecond() {
console.log("每秒触发一次");
}
private onComplete() {
console.log("倒计时完成触发");
}
}
*/
register(object: any, field: string, onSecond: Function, onComplete: Function): any {
let data: any = {};
data.id = StringUtil.guid();
data.object = object; // 管理对象
data.field = field; // 时间字段
data.onSecond = onSecond; // 每秒事件
data.onComplete = onComplete; // 倒计时完成事件
TimerManager.times[data.id] = data;
return data.id;
}
/**
* 在指定对象上注销一个倒计时的回调管理器
* @param id 时间对象唯一表示
* @example
export class Test extends Component {
private timeId!: string;
start() {
this.timeId = oops.timer.register(this, "countDown", this.onSecond, this.onComplete);
}
onDestroy() {
// 在指定对象上注销一个倒计时的回调管理器
oops.timer.unRegister(this.timeId);
}
}
*/
unRegister(id: string) {
if (TimerManager.times[id])
delete TimerManager.times[id];
}
/** 游戏最小化时记录时间数据 */
save() {
for (let key in TimerManager.times) {
TimerManager.times[key].startTime = this.getTime();
}
}
/** 游戏最大化时回复时间数据 */
load() {
for (let key in TimerManager.times) {
let interval = Math.floor((this.getTime() - (TimerManager.times[key].startTime || this.getTime())) / 1000);
let data = TimerManager.times[key];
data.object[data.field] = data.object[data.field] - interval;
if (data.object[data.field] < 0) {
data.object[data.field] = 0;
this.onTimerComplete(data);
}
TimerManager.times[key].startTime = null;
}
}
}
/**
* 定时跳动组件
* @example
export class Test extends Component {
// 创建一个定时跳动组件
private timer: Timer = new Timer(1);
update(dt: number) {
if (this.timer.update(this.dt)) {
console.log(每一秒触发一次);
}
}
}
*/
export class Timer {
/** 定时到了回调 */
callback: Function | null = null;
private _elapsedTime: number = 0;
/** 逝去时间 */
get elapsedTime(): number {
return this._elapsedTime;
}
private _step: number = 0;
/** 获取触发间隔时间单位秒 */
get step(): number {
return this._step;
}
/** 设置触发间隔时间单位秒 */
set step(step: number) {
this._step = step; // 每次修改时间
this._elapsedTime = 0; // 逝去时间
}
/** 进度 */
get progress(): number {
return this._elapsedTime / this._step;
}
/**
* 构造函数
* @param step 每跳动一次步长单位位
*/
constructor(step: number = 0) {
this.step = step;
}
/** 游戏引擎的cc.Component组件的update方法调用 */
update(dt: number) {
this._elapsedTime += dt;
if (this._elapsedTime >= this._step) {
this._elapsedTime -= this._step;
this.callback?.call(this);
return true;
}
return false;
}
/** 重置 */
reset() {
this._elapsedTime = 0;
}
}