当前位置:   article > 正文

Egret自定义计时器(决战沙城TimerManager和Laya.timer)

egret.gettimer

 

一 自定义计时器

因为游戏中经常用到计时器,比如每1秒发射一枚子弹啊,每2秒怪物AI自动转向啊

每次去new Timer 然后addEventListener(egret.TimerEvent...     之类的太麻烦了。

 

所以自定义一个计时器

 

二  决战沙城的自定义计时器

来看看决战沙城的自定义计时器

原理就是egret.Ticker每帧执行,让列表里TimerHandler加上时间或帧,检查当到了计时时间结束时,就执行回调。

  1. /**
  2. * Created by yangsong on 2014/11/23.
  3. * Timer管理器
  4. */
  5. class TimerManager extends SingtonClass {
  6. private _handlers: Array<TimerHandler>;
  7. private _delHandlers: Array<TimerHandler>;
  8. private _currTime: number;
  9. private _currFrame: number;
  10. private _count: number;
  11. private _timeScale: number;
  12. private _isPause: boolean;
  13. private _pauseTime: number;
  14. /**
  15. * 构造函数
  16. */
  17. public constructor() {
  18. super();
  19. this._handlers = new Array<TimerHandler>();
  20. this._delHandlers = new Array<TimerHandler>();
  21. this._currTime = egret.getTimer();
  22. this._currFrame = 0;
  23. this._count = 0;
  24. this._timeScale = 1;
  25. egret.Ticker.getInstance().register(this.onEnterFrame, this);
  26. }
  27. /**
  28. * 设置时间参数
  29. * @param timeScale
  30. */
  31. public setTimeScale(timeScale: number): void {
  32. this._timeScale = timeScale;
  33. }
  34. /**
  35. * 每帧执行函数
  36. * @param frameTime
  37. */
  38. private onEnterFrame(): void {
  39. if (this._isPause) {
  40. return;
  41. }
  42. this._currFrame++;
  43. this._currTime = egret.getTimer();
  44. App.DebugUtils.start("TimerManager:");
  45. while (this._delHandlers.length) {
  46. this.removeHandle(this._delHandlers.pop());
  47. }
  48. for (var i: number = 0; i < this._count; i++) {
  49. var handler: TimerHandler = this._handlers[i];
  50. if (this._delHandlers.indexOf(handler) != -1) {
  51. continue;
  52. }
  53. var t: number = handler.userFrame ? this._currFrame : this._currTime;
  54. if (t >= handler.exeTime) {
  55. App.DebugUtils.start(handler.method.toString());
  56. handler.method.call(handler.methodObj, (this._currTime - handler.dealTime) * this._timeScale);
  57. App.DebugUtils.stop(handler.method.toString());
  58. handler.dealTime = this._currTime;
  59. handler.exeTime += handler.delay;
  60. if (!handler.repeat) {
  61. if (handler.repeatCount > 1) {
  62. handler.repeatCount--;
  63. } else {
  64. if (handler.complateMethod) {
  65. handler.complateMethod.apply(handler.complateMethodObj);
  66. }
  67. if (this._delHandlers.indexOf(handler) == -1) {
  68. this._delHandlers.push(handler);
  69. }
  70. }
  71. }
  72. }
  73. }
  74. App.DebugUtils.stop("TimerManager:");
  75. }
  76. private removeHandle(handler: TimerHandler): void {
  77. var i = this._handlers.indexOf(handler);
  78. if (i == -1) {
  79. Log.warn("what????");
  80. return;
  81. }
  82. this._handlers.splice(i, 1);
  83. ObjectPool.push(handler);
  84. this._count--;
  85. }
  86. private create(useFrame: boolean, delay: number, repeatCount: number, method: Function, methodObj: any, complateMethod: Function, complateMethodObj: any): void {
  87. //参数监测
  88. if (delay < 0 || repeatCount < 0 || method == null) {
  89. return;
  90. }
  91. //先删除相同函数的计时
  92. this.remove(method, methodObj);
  93. //创建
  94. var handler: TimerHandler = ObjectPool.pop("TimerHandler");
  95. handler.userFrame = useFrame;
  96. handler.repeat = repeatCount == 0;
  97. handler.repeatCount = repeatCount;
  98. handler.delay = delay;
  99. handler.method = method;
  100. handler.methodObj = methodObj;
  101. handler.complateMethod = complateMethod;
  102. handler.complateMethodObj = complateMethodObj;
  103. handler.exeTime = delay + (useFrame ? this._currFrame : this._currTime);
  104. handler.dealTime = this._currTime;
  105. this._handlers.push(handler);
  106. this._count++;
  107. }
  108. /**
  109. * 在指定的延迟(以毫秒为单位)后运行指定的函数。
  110. * @param delay 执行间隔:毫秒
  111. * @param method 执行函数
  112. * @param methodObj 执行函数所属对象
  113. */
  114. public setTimeOut(delay: number, method: Function, methodObj: any): void {
  115. this.doTimer(delay, 1, method, methodObj);
  116. }
  117. /**
  118. * 在指定的帧后运行指定的函数。
  119. * @param delay 执行间隔:帧频
  120. * @param method 执行函数
  121. * @param methodObj 执行函数所属对象
  122. */
  123. public setFrameOut(delay: number, method: Function, methodObj: any): void {
  124. this.doFrame(delay, 1, method, methodObj);
  125. }
  126. /**
  127. *
  128. * 定时执行
  129. * @param delay 执行间隔:毫秒
  130. * @param repeatCount 执行次数, 0为无限次
  131. * @param method 执行函数
  132. * @param methodObj 执行函数所属对象
  133. * @param complateMethod 完成执行函数
  134. * @param complateMethodObj 完成执行函数所属对象
  135. *
  136. */
  137. public doTimer(delay: number, repeatCount: number, method: Function, methodObj: any, complateMethod: Function = null, complateMethodObj: any = null): void {
  138. this.create(false, delay, repeatCount, method, methodObj, complateMethod, complateMethodObj);
  139. }
  140. /**
  141. *
  142. * 定时执行
  143. * @param delay 执行间隔:帧频
  144. * @param repeatCount 执行次数, 0为无限次
  145. * @param method 执行函数
  146. * @param methodObj 执行函数所属对象
  147. * @param complateMethod 完成执行函数
  148. * @param complateMethodObj 完成执行函数所属对象
  149. *
  150. */
  151. public doFrame(delay: number, repeatCount: number, method: Function, methodObj: any, complateMethod: Function = null, complateMethodObj: any = null): void {
  152. this.create(true, delay, repeatCount, method, methodObj, complateMethod, complateMethodObj);
  153. }
  154. /**
  155. * 定时器执行数量
  156. * @return
  157. *
  158. */
  159. public get count(): number {
  160. return this._count;
  161. }
  162. /**
  163. * 清理
  164. * @param method 要移除的函数
  165. * @param methodObj 要移除的函数对应的对象
  166. */
  167. public remove(method: Function, methodObj: any): void {
  168. for (var i: number = 0; i < this._count; i++) {
  169. var handler: TimerHandler = this._handlers[i];
  170. if (handler.method == method && handler.methodObj == methodObj && this._delHandlers.indexOf(handler) == -1) {
  171. this._delHandlers.push(handler);
  172. break;
  173. }
  174. }
  175. }
  176. /**
  177. * 清理
  178. * @param methodObj 要移除的函数对应的对象
  179. */
  180. public removeAll(methodObj: any): void {
  181. for (var i: number = 0; i < this._count; i++) {
  182. var handler: TimerHandler = this._handlers[i];
  183. if (handler.methodObj == methodObj && this._delHandlers.indexOf(handler) == -1) {
  184. this._delHandlers.push(handler);
  185. }
  186. }
  187. }
  188. /**
  189. * 检测是否已经存在
  190. * @param method
  191. * @param methodObj
  192. *
  193. */
  194. public isExists(method: Function, methodObj: any): boolean {
  195. for (var i: number = 0; i < this._count; i++) {
  196. var handler: TimerHandler = this._handlers[i];
  197. if (handler.method == method && handler.methodObj == methodObj && this._delHandlers.indexOf(handler) == -1) {
  198. return true;
  199. }
  200. }
  201. return false;
  202. }
  203. /**
  204. * 暂停
  205. */
  206. public pause(): void {
  207. if (this._isPause) {
  208. return;
  209. }
  210. this._isPause = true;
  211. this._pauseTime = egret.getTimer();
  212. }
  213. /**
  214. * 从暂停中恢复
  215. */
  216. public resume(): void {
  217. if (!this._isPause) {
  218. return;
  219. }
  220. this._isPause = false;
  221. this._currTime = egret.getTimer();
  222. var gap = this._currTime - this._pauseTime;
  223. for (var i: number = 0; i < this._count; i++) {
  224. var handler: TimerHandler = this._handlers[i];
  225. handler.dealTime += gap;
  226. if (!handler.userFrame) {
  227. handler.exeTime += gap;
  228. }
  229. }
  230. }
  231. }
  232. class TimerHandler {
  233. /**执行间隔*/
  234. public delay: number = 0;
  235. /**是否重复执行*/
  236. public repeat: boolean;
  237. /**重复执行次数*/
  238. public repeatCount: number = 0;
  239. /**是否用帧率*/
  240. public userFrame: boolean;
  241. /**执行时间*/
  242. public exeTime: number = 0;
  243. /**处理函数*/
  244. public method: Function;
  245. /**处理函数所属对象*/
  246. public methodObj: any;
  247. /**完成处理函数*/
  248. public complateMethod: Function;
  249. /**完成处理函数所属对象*/
  250. public complateMethodObj: any;
  251. /**上次的执行时间*/
  252. public dealTime: number = 0;
  253. /**清理*/
  254. public clear(): void {
  255. this.method = null;
  256. this.methodObj = null;
  257. this.complateMethod = null;
  258. this.complateMethodObj = null;
  259. }
  260. }

  

三  Laya的timer

laya已经提供了一个timer给开发者使用,功能和决战沙城的差不多

 由于Laya用的Date.now,那么在游戏置于后台过久,再返回前台时,会导致时间相差巨大,执行很多次回调。所以Laya做了额外处理。

但是egret使用的egret.ticker,置于后台时,egret.ticker是停跳了的,所以不用处理时间相差巨大的问题。

  1. class Timer {
  2. constructor(autoActive = true) {
  3. this.scale = 1;
  4. this.currTimer = Date.now();
  5. this.currFrame = 0;
  6. this._delta = 0;
  7. this._lastTimer = Date.now();
  8. this._map = [];
  9. this._handlers = [];
  10. this._temp = [];
  11. this._count = 0;
  12. autoActive && Timer.gSysTimer && Timer.gSysTimer.frameLoop(1, this, this._update);
  13. }
  14. get delta() {
  15. return this._delta;
  16. }
  17. _update() {
  18. if (this.scale <= 0) {
  19. this._lastTimer = Date.now();
  20. this._delta = 0;
  21. return;
  22. }
  23. var frame = this.currFrame = this.currFrame + this.scale;
  24. var now = Date.now();
  25. var awake = (now - this._lastTimer) > 30000;
  26. this._delta = (now - this._lastTimer) * this.scale;
  27. var timer = this.currTimer = this.currTimer + this._delta;
  28. this._lastTimer = now;
  29. var handlers = this._handlers;
  30. this._count = 0;
  31. for (var i = 0, n = handlers.length; i < n; i++) {
  32. var handler = handlers[i];
  33. if (handler.method !== null) {
  34. var t = handler.userFrame ? frame : timer;
  35. if (t >= handler.exeTime) {
  36. if (handler.repeat) {
  37. if (!handler.jumpFrame || awake) {
  38. handler.exeTime += handler.delay;
  39. handler.run(false);
  40. if (t > handler.exeTime) {
  41. handler.exeTime += Math.ceil((t - handler.exeTime) / handler.delay) * handler.delay;
  42. }
  43. }
  44. else {
  45. while (t >= handler.exeTime) {
  46. handler.exeTime += handler.delay;
  47. handler.run(false);
  48. }
  49. }
  50. }
  51. else {
  52. handler.run(true);
  53. }
  54. }
  55. }
  56. else {
  57. this._count++;
  58. }
  59. }
  60. if (this._count > 30 || frame % 200 === 0)
  61. this._clearHandlers();
  62. }
  63. _clearHandlers() {
  64. var handlers = this._handlers;
  65. for (var i = 0, n = handlers.length; i < n; i++) {
  66. var handler = handlers[i];
  67. if (handler.method !== null)
  68. this._temp.push(handler);
  69. else
  70. this._recoverHandler(handler);
  71. }
  72. this._handlers = this._temp;
  73. handlers.length = 0;
  74. this._temp = handlers;
  75. }
  76. _recoverHandler(handler) {
  77. if (this._map[handler.key] == handler)
  78. this._map[handler.key] = null;
  79. handler.clear();
  80. Timer._pool.push(handler);
  81. }
  82. _create(useFrame, repeat, delay, caller, method, args, coverBefore) {
  83. if (!delay) {
  84. method.apply(caller, args);
  85. return null;
  86. }
  87. if (coverBefore) {
  88. var handler = this._getHandler(caller, method);
  89. if (handler) {
  90. handler.repeat = repeat;
  91. handler.userFrame = useFrame;
  92. handler.delay = delay;
  93. handler.caller = caller;
  94. handler.method = method;
  95. handler.args = args;
  96. handler.exeTime = delay + (useFrame ? this.currFrame : this.currTimer + Date.now() - this._lastTimer);
  97. return handler;
  98. }
  99. }
  100. handler = Timer._pool.length > 0 ? Timer._pool.pop() : new TimerHandler();
  101. handler.repeat = repeat;
  102. handler.userFrame = useFrame;
  103. handler.delay = delay;
  104. handler.caller = caller;
  105. handler.method = method;
  106. handler.args = args;
  107. handler.exeTime = delay + (useFrame ? this.currFrame : this.currTimer + Date.now() - this._lastTimer);
  108. this._indexHandler(handler);
  109. this._handlers.push(handler);
  110. return handler;
  111. }
  112. _indexHandler(handler) {
  113. var caller = handler.caller;
  114. var method = handler.method;
  115. var cid = caller ? caller.$_GID || (caller.$_GID = ILaya.Utils.getGID()) : 0;
  116. var mid = method.$_TID || (method.$_TID = (Timer._mid++) * 100000);
  117. handler.key = cid + mid;
  118. this._map[handler.key] = handler;
  119. }
  120. once(delay, caller, method, args = null, coverBefore = true) {
  121. this._create(false, false, delay, caller, method, args, coverBefore);
  122. }
  123. loop(delay, caller, method, args = null, coverBefore = true, jumpFrame = false) {
  124. var handler = this._create(false, true, delay, caller, method, args, coverBefore);
  125. if (handler)
  126. handler.jumpFrame = jumpFrame;
  127. }
  128. frameOnce(delay, caller, method, args = null, coverBefore = true) {
  129. this._create(true, false, delay, caller, method, args, coverBefore);
  130. }
  131. frameLoop(delay, caller, method, args = null, coverBefore = true) {
  132. this._create(true, true, delay, caller, method, args, coverBefore);
  133. }
  134. toString() {
  135. return " handlers:" + this._handlers.length + " pool:" + Timer._pool.length;
  136. }
  137. clear(caller, method) {
  138. var handler = this._getHandler(caller, method);
  139. if (handler) {
  140. this._map[handler.key] = null;
  141. handler.key = 0;
  142. handler.clear();
  143. }
  144. }
  145. clearAll(caller) {
  146. if (!caller)
  147. return;
  148. for (var i = 0, n = this._handlers.length; i < n; i++) {
  149. var handler = this._handlers[i];
  150. if (handler.caller === caller) {
  151. this._map[handler.key] = null;
  152. handler.key = 0;
  153. handler.clear();
  154. }
  155. }
  156. }
  157. _getHandler(caller, method) {
  158. var cid = caller ? caller.$_GID || (caller.$_GID = ILaya.Utils.getGID()) : 0;
  159. var mid = method.$_TID || (method.$_TID = (Timer._mid++) * 100000);
  160. return this._map[cid + mid];
  161. }
  162. callLater(caller, method, args = null) {
  163. CallLater.I.callLater(caller, method, args);
  164. }
  165. runCallLater(caller, method) {
  166. CallLater.I.runCallLater(caller, method);
  167. }
  168. runTimer(caller, method) {
  169. var handler = this._getHandler(caller, method);
  170. if (handler && handler.method != null) {
  171. this._map[handler.key] = null;
  172. handler.run(true);
  173. }
  174. }
  175. pause() {
  176. this.scale = 0;
  177. }
  178. resume() {
  179. this.scale = 1;
  180. }
  181. }
  182. Timer.gSysTimer = null;
  183. Timer._pool = [];
  184. Timer._mid = 1;
  185. class TimerHandler {
  186. clear() {
  187. this.caller = null;
  188. this.method = null;
  189. this.args = null;
  190. }
  191. run(withClear) {
  192. var caller = this.caller;
  193. if (caller && caller.destroyed)
  194. return this.clear();
  195. var method = this.method;
  196. var args = this.args;
  197. withClear && this.clear();
  198. if (method == null)
  199. return;
  200. args ? method.apply(caller, args) : method.call(caller);
  201. }
  202. }

  

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/54435
推荐阅读
相关标签
  

闽ICP备14008679号