From b2bcff1a3862b27e03c1801a66c8aefe6a223aa7 Mon Sep 17 00:00:00 2001 From: dgflash Date: Wed, 20 Jul 2022 18:27:06 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=97=B6=E9=97=B4=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=E6=96=87=E6=A1=A3;=E6=B7=BB=E5=8A=A0=E8=A1=8C?= =?UTF-8?q?=E4=B8=BA=E6=A0=91DEMO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/demo/behavior-tree.meta | 12 + assets/demo/behavior-tree/Main.ts | 76 +++ assets/demo/behavior-tree/Main.ts.meta | 1 + assets/demo/behavior-tree/main.scene | 618 ++++++++++++++++++ assets/demo/behavior-tree/main.scene.meta | 1 + assets/main.scene | 2 +- assets/script/Main.ts | 2 +- doc/core/common/timer.md | 92 +++ .../core/common/manager/TimerManager.ts | 129 ++-- .../assets/core/gui/label/LabelTime.ts | 4 +- 10 files changed, 867 insertions(+), 70 deletions(-) create mode 100644 assets/demo/behavior-tree.meta create mode 100644 assets/demo/behavior-tree/Main.ts create mode 100644 assets/demo/behavior-tree/Main.ts.meta create mode 100644 assets/demo/behavior-tree/main.scene create mode 100644 assets/demo/behavior-tree/main.scene.meta create mode 100644 doc/core/common/timer.md diff --git a/assets/demo/behavior-tree.meta b/assets/demo/behavior-tree.meta new file mode 100644 index 0000000..a0e7c3c --- /dev/null +++ b/assets/demo/behavior-tree.meta @@ -0,0 +1,12 @@ +{ + "ver": "1.1.0", + "importer": "directory", + "imported": true, + "uuid": "94de2d30-864e-422c-bd80-80090d601d45", + "files": [], + "subMetas": {}, + "userData": { + "compressionType": {}, + "isRemoteBundle": {} + } +} diff --git a/assets/demo/behavior-tree/Main.ts b/assets/demo/behavior-tree/Main.ts new file mode 100644 index 0000000..462d8a2 --- /dev/null +++ b/assets/demo/behavior-tree/Main.ts @@ -0,0 +1,76 @@ +/* + * @Author: dgflash + * @Date: 2022-07-14 10:57:43 + * @LastEditors: dgflash + * @LastEditTime: 2022-07-20 14:42:13 + */ +import { _decorator } from 'cc'; +import { Timer } from '../../../extensions/oops-framework/assets/core/manager/TimerManager'; +import { Root } from '../../../extensions/oops-framework/assets/core/Root'; +import { BehaviorTree, BTreeNode, Decorator, Sequence, Task } from '../../../extensions/oops-framework/assets/libs/behavior-tree'; + +const { ccclass, property } = _decorator; + +/** + * 行为演示 + * 功能说明:一个角色向前移动,如果碰到敌人就停下,如果没有则继续移动 + */ +@ccclass('Main') +export class Main extends Root { + /** 角色位置 */ + role_pos: number = 0; + /** 敌人位置 */ + enemy_pos: number = 3; + + private bt: BehaviorTree = null!; + private timer: Timer = new Timer(1); + + start() { + var btns: Array = []; + btns.push(new RoleMoveTask()); + btns.push(new IsSeeEnemy(new RoleMoveStopTask())); + + // 这里表达,RoleMoveTask节点先处理角色移动一步,IsSeeEnemy节点验证是否碰到敌人,如果碰到,IsSeeEnemy下面挂的任务节点就处理碰到敌人的提示。 + this.bt = new BehaviorTree(new Sequence(btns)); + } + + update(dt: number) { + if (this.timer.update(dt)) { + this.bt.setObject(this) + this.bt.run(); + } + } +} + +/** 演示控制移动,通过行为树黑板的概念把需要处理的Main对象传递到行为树中,每过一秒先移动一步 */ +class RoleMoveTask extends Task { + run(obj?: Main): void { + if (obj) { + obj.role_pos++; + console.log(`角色当前移动了【${obj.role_pos}】步`); + } + this.success(); + } +} + +/** 装饰器是条件语句只能附加在其他节点上并且定义所附加的节点是否执行,这里验证比如敌人位置与之相等后,表示条件验证成功,继续执行后续任务,失败结束行为树的处理流程 */ +class IsSeeEnemy extends Decorator { + run(blackboard: Main) { + if (blackboard.role_pos >= blackboard.enemy_pos) { + super.run(blackboard); + this.success(); // 调用此方法,代表此节点表达验证逻辑为true的结果,可以执行后续节点 + } + else { + this.fail(); // 调用此方法,代表此节点表达验证逻辑为false的结果,不能执行后续节点 + } + } +} + +/** 玩家自己停止动作逻辑,这类逻辑一般只会成本,属于确定的流程 */ +class RoleMoveStopTask extends Task { + run(blackboard: Main): void { + console.log(`角色当前停止移动`); + blackboard.enabled = false; // 不在触发行为树处理逻辑 + this.success(); + } +} \ No newline at end of file diff --git a/assets/demo/behavior-tree/Main.ts.meta b/assets/demo/behavior-tree/Main.ts.meta new file mode 100644 index 0000000..95ee72d --- /dev/null +++ b/assets/demo/behavior-tree/Main.ts.meta @@ -0,0 +1 @@ +{"ver":"4.0.23","importer":"typescript","imported":true,"uuid":"2c1f2fca-be85-4d02-9e86-b5942d4d7f16","files":[],"subMetas":{},"userData":{}} diff --git a/assets/demo/behavior-tree/main.scene b/assets/demo/behavior-tree/main.scene new file mode 100644 index 0000000..2db36be --- /dev/null +++ b/assets/demo/behavior-tree/main.scene @@ -0,0 +1,618 @@ +[ + { + "__type__": "cc.SceneAsset", + "_name": "", + "_objFlags": 0, + "_native": "", + "scene": { + "__id__": 1 + } + }, + { + "__type__": "cc.Scene", + "_name": "main", + "_objFlags": 0, + "_parent": null, + "_children": [ + { + "__id__": 2 + } + ], + "_active": true, + "_components": [], + "_prefab": { + "__id__": 17 + }, + "autoReleaseAssets": false, + "_globals": { + "__id__": 18 + }, + "_id": "4e145a53-6718-4a42-8e1e-b578f7da5c6d" + }, + { + "__type__": "cc.Node", + "_name": "root", + "_objFlags": 0, + "_parent": { + "__id__": 1 + }, + "_children": [ + { + "__id__": 3 + }, + { + "__id__": 4 + } + ], + "_active": true, + "_components": [ + { + "__id__": 16 + } + ], + "_prefab": null, + "_lpos": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_layer": 1073741824, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "51KEOywK1E4akKtZVxf+Lk" + }, + { + "__type__": "cc.Node", + "_name": "game", + "_objFlags": 0, + "_parent": { + "__id__": 2 + }, + "_children": [], + "_active": true, + "_components": [], + "_prefab": null, + "_lpos": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_layer": 1073741824, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "72HkSn751F86VoFGmJXpeo" + }, + { + "__type__": "cc.Node", + "_name": "gui", + "_objFlags": 0, + "_parent": { + "__id__": 2 + }, + "_children": [ + { + "__id__": 5 + }, + { + "__id__": 7 + } + ], + "_active": true, + "_components": [ + { + "__id__": 10 + }, + { + "__id__": 12 + }, + { + "__id__": 14 + } + ], + "_prefab": null, + "_lpos": { + "__type__": "cc.Vec3", + "x": 640, + "y": 375, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_layer": 33554432, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "04HVz/X+dO/KoC2LOzh7O1" + }, + { + "__type__": "cc.Node", + "_name": "UICamera", + "_objFlags": 0, + "_parent": { + "__id__": 4 + }, + "_children": [], + "_active": true, + "_components": [ + { + "__id__": 6 + } + ], + "_prefab": null, + "_lpos": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 1000 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_layer": 33554432, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "e73tUR45BNpa1z9e8ecKdC" + }, + { + "__type__": "cc.Camera", + "_name": "", + "_objFlags": 0, + "node": { + "__id__": 5 + }, + "_enabled": true, + "__prefab": null, + "_projection": 0, + "_priority": 1073741824, + "_fov": 45, + "_fovAxis": 0, + "_orthoHeight": 375, + "_near": 1, + "_far": 2000, + "_color": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "_depth": 1, + "_stencil": 0, + "_clearFlags": 7, + "_rect": { + "__type__": "cc.Rect", + "x": 0, + "y": 0, + "width": 1, + "height": 1 + }, + "_aperture": 19, + "_shutter": 7, + "_iso": 0, + "_screenScale": 1, + "_visibility": 33554432, + "_targetTexture": null, + "_id": "58hTt8B3tKnZaTs3OzCwkE" + }, + { + "__type__": "cc.Node", + "_name": "Label", + "_objFlags": 0, + "_parent": { + "__id__": 4 + }, + "_children": [], + "_active": true, + "_components": [ + { + "__id__": 8 + }, + { + "__id__": 9 + } + ], + "_prefab": null, + "_lpos": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_layer": 33554432, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "f4o1uDaudFI7Bc0yjB/YLp" + }, + { + "__type__": "cc.UITransform", + "_name": "", + "_objFlags": 0, + "node": { + "__id__": 7 + }, + "_enabled": true, + "__prefab": null, + "_contentSize": { + "__type__": "cc.Size", + "width": 320, + "height": 50.4 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 + }, + "_id": "3dMf+QLKhB96q1F3jRIVtE" + }, + { + "__type__": "cc.Label", + "_name": "", + "_objFlags": 0, + "node": { + "__id__": 7 + }, + "_enabled": true, + "__prefab": null, + "_customMaterial": null, + "_srcBlendFactor": 2, + "_dstBlendFactor": 4, + "_color": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "_string": "打开控制台看输出", + "_horizontalAlign": 1, + "_verticalAlign": 1, + "_actualFontSize": 40, + "_fontSize": 40, + "_fontFamily": "Arial", + "_lineHeight": 40, + "_overflow": 0, + "_enableWrapText": true, + "_font": null, + "_isSystemFontUsed": true, + "_spacingX": 0, + "_isItalic": false, + "_isBold": false, + "_isUnderline": false, + "_underlineHeight": 2, + "_cacheMode": 0, + "_id": "63XsEQNL1BdoxSNx702kZv" + }, + { + "__type__": "cc.UITransform", + "_name": "Canvas", + "_objFlags": 0, + "node": { + "__id__": 4 + }, + "_enabled": true, + "__prefab": { + "__id__": 11 + }, + "_contentSize": { + "__type__": "cc.Size", + "width": 1280, + "height": 750 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 + }, + "_id": "9b8MclXbNFz593SPtnWKrD" + }, + { + "__type__": "cc.CompPrefabInfo", + "fileId": "03ZMhNEpRK75Hmdzr8ZGhG" + }, + { + "__type__": "cc.Canvas", + "_name": "Canvas", + "_objFlags": 0, + "node": { + "__id__": 4 + }, + "_enabled": true, + "__prefab": { + "__id__": 13 + }, + "_cameraComponent": { + "__id__": 6 + }, + "_alignCanvasWithScreen": true, + "_id": "1dz15JMmpAgKNYspEOuXh6" + }, + { + "__type__": "cc.CompPrefabInfo", + "fileId": "7acBC/yU9N05fc6HGd8fZS" + }, + { + "__type__": "cc.Widget", + "_name": "", + "_objFlags": 0, + "node": { + "__id__": 4 + }, + "_enabled": true, + "__prefab": { + "__id__": 15 + }, + "_alignFlags": 45, + "_target": null, + "_left": 0, + "_right": 0, + "_top": 0, + "_bottom": 0, + "_horizontalCenter": 0, + "_verticalCenter": 0, + "_isAbsLeft": true, + "_isAbsRight": true, + "_isAbsTop": true, + "_isAbsBottom": true, + "_isAbsHorizontalCenter": true, + "_isAbsVerticalCenter": true, + "_originalWidth": 0, + "_originalHeight": 1280, + "_alignMode": 2, + "_lockFlags": 45, + "_id": "94hxkzOX9ClLtqc63q0wsQ" + }, + { + "__type__": "cc.CompPrefabInfo", + "fileId": "1chkRDp1xCFqsnwJh1NVq1" + }, + { + "__type__": "2c1f2/KvoVNAp6GtZQtTX8W", + "_name": "", + "_objFlags": 0, + "node": { + "__id__": 2 + }, + "_enabled": true, + "__prefab": null, + "game": { + "__id__": 3 + }, + "gui": { + "__id__": 4 + }, + "_id": "cbYJ6mJrFE0K0B9H4lzwOs" + }, + { + "__type__": "cc.PrefabInfo", + "fileId": "984e383b-d959-4558-aeb1-4ceb5fabbd10" + }, + { + "__type__": "cc.SceneGlobals", + "ambient": { + "__id__": 19 + }, + "shadows": { + "__id__": 20 + }, + "_skybox": { + "__id__": 21 + }, + "fog": { + "__id__": 22 + }, + "octree": { + "__id__": 23 + } + }, + { + "__type__": "cc.AmbientInfo", + "_skyColorHDR": { + "__type__": "cc.Vec4", + "x": 0.242613, + "y": 0.362617, + "z": 0.798746, + "w": 0.520833125 + }, + "_skyColor": { + "__type__": "cc.Vec4", + "x": 0.242613, + "y": 0.362617, + "z": 0.798746, + "w": 0.520833125 + }, + "_skyIllumHDR": 20000, + "_skyIllum": 20000, + "_groundAlbedoHDR": { + "__type__": "cc.Vec4", + "x": 0.241814, + "y": 0.361945, + "z": 0.798799, + "w": 0 + }, + "_groundAlbedo": { + "__type__": "cc.Vec4", + "x": 0.241814, + "y": 0.361945, + "z": 0.798799, + "w": 0 + }, + "_skyColorLDR": { + "__type__": "cc.Vec4", + "x": 0.519964, + "y": 0.630786, + "z": 0.905039, + "w": 0.5208 + }, + "_skyIllumLDR": 0.5208, + "_groundAlbedoLDR": { + "__type__": "cc.Vec4", + "x": 0.519544, + "y": 0.630484, + "z": 0.905069, + "w": 0 + } + }, + { + "__type__": "cc.ShadowsInfo", + "_enabled": false, + "_type": 0, + "_normal": { + "__type__": "cc.Vec3", + "x": 0, + "y": 1, + "z": 0 + }, + "_distance": 0, + "_shadowColor": { + "__type__": "cc.Color", + "r": 76, + "g": 76, + "b": 76, + "a": 255 + }, + "_maxReceived": 4, + "_size": { + "__type__": "cc.Vec2", + "x": 1024, + "y": 1024 + } + }, + { + "__type__": "cc.SkyboxInfo", + "_envLightingType": 0, + "_envmapHDR": { + "__uuid__": "d032ac98-05e1-4090-88bb-eb640dcb5fc1@b47c0", + "__expectedType__": "cc.TextureCube" + }, + "_envmap": { + "__uuid__": "d032ac98-05e1-4090-88bb-eb640dcb5fc1@b47c0", + "__expectedType__": "cc.TextureCube" + }, + "_envmapLDR": { + "__uuid__": "6f01cf7f-81bf-4a7e-bd5d-0afc19696480@b47c0", + "__expectedType__": "cc.TextureCube" + }, + "_diffuseMapHDR": null, + "_diffuseMapLDR": null, + "_enabled": true, + "_useHDR": true, + "_editableMaterial": null + }, + { + "__type__": "cc.FogInfo", + "_type": 0, + "_fogColor": { + "__type__": "cc.Color", + "r": 200, + "g": 200, + "b": 200, + "a": 255 + }, + "_enabled": false, + "_fogDensity": 0.3, + "_fogStart": 0.5, + "_fogEnd": 300, + "_fogAtten": 5, + "_fogTop": 1.5, + "_fogRange": 1.2, + "_accurate": false + }, + { + "__type__": "cc.OctreeInfo", + "_enabled": false, + "_minPos": { + "__type__": "cc.Vec3", + "x": -1024, + "y": -1024, + "z": -1024 + }, + "_maxPos": { + "__type__": "cc.Vec3", + "x": 1024, + "y": 1024, + "z": 1024 + }, + "_depth": 8 + } +] \ No newline at end of file diff --git a/assets/demo/behavior-tree/main.scene.meta b/assets/demo/behavior-tree/main.scene.meta new file mode 100644 index 0000000..6f3d870 --- /dev/null +++ b/assets/demo/behavior-tree/main.scene.meta @@ -0,0 +1 @@ +{"ver":"1.1.39","importer":"scene","imported":true,"uuid":"4e145a53-6718-4a42-8e1e-b578f7da5c6d","files":[".json"],"subMetas":{},"userData":{}} diff --git a/assets/main.scene b/assets/main.scene index cd377fd..5447d60 100644 --- a/assets/main.scene +++ b/assets/main.scene @@ -227,7 +227,7 @@ "_priority": 1073741824, "_fov": 45, "_fovAxis": 0, - "_orthoHeight": 471.4346895074946, + "_orthoHeight": 446.3340563991323, "_near": 1, "_far": 2000, "_color": { diff --git a/assets/script/Main.ts b/assets/script/Main.ts index 900df32..2d1a1c1 100644 --- a/assets/script/Main.ts +++ b/assets/script/Main.ts @@ -2,7 +2,7 @@ * @Author: dgflash * @Date: 2021-07-03 16:13:17 * @LastEditors: dgflash - * @LastEditTime: 2022-07-19 14:17:43 + * @LastEditTime: 2022-07-20 17:28:50 */ import { dynamicAtlasManager, macro, profiler, _decorator } from 'cc'; import { DEBUG, JSB } from 'cc/env'; diff --git a/doc/core/common/timer.md b/doc/core/common/timer.md new file mode 100644 index 0000000..24d6ee4 --- /dev/null +++ b/doc/core/common/timer.md @@ -0,0 +1,92 @@ +### 功能说明 +OopsFramework-时间管理模块主要实现在游戏中不同类型的定时器功能。 + +### 使用说明 +##### 获取游戏开始到现在逝去的时间 +``` +oops.timer.getTime(); +``` + +##### 获取本地时间刻度 +``` +oops.timer.getLocalTime(); +``` + +##### 注册一个固定间隔时间的触发器 +``` +oops.timer.schedule(()=>{ + // 每秒触发一次 +}, 1000); +``` + +##### 注册一个只触发一次的延时的触发器 +``` +oops.timer.scheduleOnce(()=>{ + // 1秒后触发一次后不会在触发 +}, 1000); +``` + +##### 删除一个时间触发器 +``` +var uuid = oops.timer.schedule(()=>{ + // 每秒触发一次 +}, 1000); + +// 删除指定标识的触发器 +oops.timer.unschedule(uuid); +``` + +##### 删除所有时间触发器 +``` +oops.timer.unscheduleAll(); +``` + +##### 在指定对象上注册一个倒计时的回调管理器 +``` +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("倒计时完成触发"); + } +} +``` + +##### 在指定对象上注销一个倒计时的回调管理器 +``` +export class Test extends Component { + private timeId!: string; + + start() { + this.timeId = oops.timer.registerObject(this, "countDown", this.onSecond, this.onComplete); + } + + onDestroy() { + // 在指定对象上注销一个倒计时的回调管理器 + oops.timer.unRegister(this.timeId); + } +} +``` + +##### 定时跳动组件 +``` +export class Test extends Component { + // 创建一个定时跳动组件 + private timer: Timer = new Timer(1); + + update(dt: number) { + if (this.timer.update(this.dt)) { + console.log(每一秒触发一次); + } + } +} +``` \ No newline at end of file diff --git a/extensions/oops-framework/assets/core/common/manager/TimerManager.ts b/extensions/oops-framework/assets/core/common/manager/TimerManager.ts index 30327f6..0a6fe63 100644 --- a/extensions/oops-framework/assets/core/common/manager/TimerManager.ts +++ b/extensions/oops-framework/assets/core/common/manager/TimerManager.ts @@ -15,28 +15,29 @@ export const guid = function () { export class TimerManager extends EventDispatcher { private static times: any = {}; private schedules: any = {}; - private _scheduleCount: number = 1; + private scheduleCount: number = 1; private initTime: number = (new Date()).getTime(); // 当前游戏进入的时间毫秒值 private component: Component; - // 服务器时间与本地时间间隔 - private _$serverTimeElasped: number = 0; + // 服务器时间与本地时间同步 + private serverTime: number = 0; constructor(component: Component) { super(); this.component = component; this.schedule(this.onUpdate.bind(this), 1); } + /** - * 设置服务器时间与本地时间间隔 + * 服务器时间与本地时间同步 * @param val */ - public serverTimeElasped(val?: number): number { + public setServerTime(val?: number): number { if (val) { - this._$serverTimeElasped = val; + this.serverTime = val; } - return this._$serverTimeElasped; + return this.serverTime; } /** @@ -76,26 +77,42 @@ export class TimerManager extends EventDispatcher { return Date.now(); } + /** + * 注册一个固定间隔时间的触发器 + * @param callback 触发时的回调方法 + * @param interval 固定间隔触发时间 + * @returns uuid + */ public schedule(callback: Function, interval: number): string { - let UUID = `schedule_${this._scheduleCount++}` - this.schedules[UUID] = callback; + let uuid = `schedule_${this.scheduleCount++}` + this.schedules[uuid] = callback; this.component.schedule(callback, interval); - return UUID; + return uuid; } + /** + * 注册一个只触发一次的延时的触发器 + * @param callback 触发时的回调方法 + * @param delay 延时触发时间 + * @returns uuid + */ public scheduleOnce(callback: Function, delay: number = 0): string { - let UUID = `scheduleOnce_${this._scheduleCount++}`; - this.schedules[UUID] = callback; + let uuid = `scheduleOnce_${this.scheduleCount++}`; + this.schedules[uuid] = callback; this.component.scheduleOnce(() => { - let cb = this.schedules[UUID]; + let cb = this.schedules[uuid]; if (cb) { cb(); } - this.unschedule(UUID); + this.unschedule(uuid); }, Math.max(delay, 0)); - return UUID; + return uuid; } + /** + * 删除一个时间触发器 + * @param uuid 唯一标识 + */ public unschedule(uuid: string) { let cb = this.schedules[uuid]; if (cb) { @@ -104,14 +121,15 @@ export class TimerManager extends EventDispatcher { } } - public unscheduleAllCallbacks() { + /** 删除所有时间触发器 */ + public unscheduleAll() { for (let k in this.schedules) { this.component.unschedule(this.schedules[k]); } this.schedules = {}; } - onUpdate(dt: number) { + private onUpdate(dt: number) { // 后台管理倒计时完成事件 for (let key in TimerManager.times) { let data = TimerManager.times[key]; @@ -119,9 +137,9 @@ export class TimerManager extends EventDispatcher { data.object[data.field]--; if (data.object[data.field] == 0) { - this.timerComplete(data); + this.onTimerComplete(data); } - else { // 修改是否完成状态 + else { // 修改是否完成状态 if (data.onSecond) { data.onSecond.call(data.object); // 触发每秒回调事件 } @@ -130,7 +148,31 @@ export class TimerManager extends EventDispatcher { } } - /** 游戏最小划时记录时间数据 */ + /** 触发倒计时完成事件 */ + private onTimerComplete(data: any) { + if (data.onComplete) data.onComplete.call(data.object); + if (data.event) this.dispatchEvent(data.event); + } + + /** 在指定对象上注册一个倒计时的回调管理器 */ + public register(object: any, field: string, onSecond: Function, onComplete: Function) { + let data: any = {}; + data.id = guid(); + data.object = object; // 管理对象 + data.field = field; // 时间字段 + data.onSecond = onSecond; // 每秒事件 + data.onComplete = onComplete; // 倒计时完成事件 + TimerManager.times[data.id] = data; + return data.id; + } + + /** 在指定对象上注销一个倒计时的回调管理器 */ + public unRegister(id: string) { + if (TimerManager.times[id]) + delete TimerManager.times[id]; + } + + /** 游戏最小化时记录时间数据 */ public save() { for (let key in TimerManager.times) { TimerManager.times[key].startTime = this.getTime(); @@ -145,56 +187,11 @@ export class TimerManager extends EventDispatcher { data.object[data.field] = data.object[data.field] - interval; if (data.object[data.field] < 0) { data.object[data.field] = 0; - this.timerComplete(data); + this.onTimerComplete(data); } TimerManager.times[key].startTime = null; } } - - /** 触发倒计时完成事件 */ - private timerComplete(data: any) { - if (data.onComplete) data.onComplete.call(data.object); - if (data.event) this.dispatchEvent(data.event); - } - - /** 注册指定对象的倒计时属性更新 */ - public registerObject(object: any, field: string, onSecond: Function, onComplete: Function) { - let data: any = {}; - data.id = guid(); - data.object = object; // 管理对象 - data.field = field; // 时间字段 - data.onSecond = onSecond; // 每秒事件 - data.onComplete = onComplete; // 倒计时完成事件 - TimerManager.times[data.id] = data; - return data.id; - } - - /** 注消指定对象的倒计时属性更新 */ - public unRegisterObject(id: string) { - if (TimerManager.times[id]) - delete TimerManager.times[id]; - } - - /** - * 注册事件需要管理的实时变化的时间对象 - * @param event(String) 时间为零时触发的事件 - * @param object(object) 需要管理的数据结构对象 - * @param field(Array) 需要管理的字段 - */ - public register(event: string, object: any, field: Array) { - let data: any = {}; - data.id = event; - data.event = event; // 倒计时完成事件 - data.object = object; // 管理对象 - data.field = field; // 时间字段 - TimerManager.times[data.id] = data; - } - - /** 注销定时器 */ - public unRegister(event: string) { - if (TimerManager.times[event]) - delete TimerManager.times[event]; - } } /** 定时跳动组件 */ diff --git a/extensions/oops-framework/assets/core/gui/label/LabelTime.ts b/extensions/oops-framework/assets/core/gui/label/LabelTime.ts index 42e3614..17dee3c 100644 --- a/extensions/oops-framework/assets/core/gui/label/LabelTime.ts +++ b/extensions/oops-framework/assets/core/gui/label/LabelTime.ts @@ -116,12 +116,12 @@ export default class LabelTime extends Label { start() { this.format(); if (!EDITOR) - this.timeId = oops.timer.registerObject(this, "countDown", this.onSecond, this.onComplete); + this.timeId = oops.timer.register(this, "countDown", this.onSecond, this.onComplete); } onDestroy() { if (!EDITOR) - oops.timer.unRegisterObject(this.timeId); + oops.timer.unRegister(this.timeId); } private onSecond() {