You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

246 lines
6.0 KiB

  1. -- 用来实现自动倒计时,并可以做数据绑定,具体用法参考VT_RemainTime.lua
  2. local RemainTime = class("RemainTime");
  3. function RemainTime:ctor()
  4. -- 当前剩余秒数,每秒更新一次,可绑定
  5. self.Value = 0;
  6. -- 总剩余时间(单位秒,外部设置),可绑定
  7. self.RemainTime = 0;
  8. -- 上次更新的本地时间
  9. self.LastTime = 0
  10. -- 总共流失了多少时间
  11. self.TotalElapse = 0
  12. -- 开始倒计时的时间(os.time()获取)
  13. self.StartTime = 0;
  14. -- 计时到0后,回调OnTimeOver(self)
  15. self.OnTimeOver = nil;
  16. -- 数据绑定列表,key是变量名(Value或RemainTime),value是Binder表
  17. self.BindsByName = {}
  18. -- 根据索引排序的绑定列表,key是BindIndex,value是Binder表
  19. self.BindsByIndex = {}
  20. -- 绑定索引
  21. self.BindIndex = 0;
  22. -- 每隔多久触发一次
  23. self.Interval = 1;
  24. -- 定时器速度
  25. self.Speed = 1;
  26. -- 暂停状态
  27. self.Pause = false;
  28. end
  29. function RemainTime:setInterval(interval)
  30. if self.Interval ~= interval then
  31. self.Interval = interval;
  32. if self.TimerID then
  33. self:stopTimer();
  34. self:startTimer();
  35. end
  36. end
  37. end
  38. -- 设置加速速度
  39. function RemainTime:setSpeed(speed)
  40. self.Speed = speed
  41. end
  42. -- 设置剩余秒数多少
  43. function RemainTime:setRemainTime(seconds)
  44. --print("设置倒计时" , seconds);
  45. if type(seconds) == "table" then
  46. seconds = seconds:getRemainTime();
  47. end
  48. self.RemainTime = seconds;
  49. self.Value = seconds;
  50. self.StartTime = os.time()
  51. self.LastTime = self.StartTime
  52. self.TotalElapse = 0
  53. self:triggerBinder("RemainTime");
  54. self:triggerBinder("Value");
  55. -- 开始计时
  56. if self.Value > 0 and next(self.BindsByIndex) ~= nil and self.Pause == false then
  57. self:startTimer();
  58. end
  59. end
  60. function RemainTime:getRemainTime()
  61. return self.RemainTime;
  62. end
  63. function RemainTime:updateTo(target)
  64. target.Value = self.Value;
  65. target.RemainTime = self.RemainTime;
  66. target.StartTime = self.StartTime;
  67. target.LastTime = self.LastTime
  68. target.TotalElapse = self.TotalElapse
  69. target.Speed = self.Speed
  70. if target.startTimer and target.Value > 0 and next(target.BindsByIndex) ~= nil and target.Pause == false then
  71. target:startTimer()
  72. end
  73. return target;
  74. end;
  75. -- 获取一个绑定实例
  76. function RemainTime:getBinder(valueName)
  77. local bindTable = self.BindsByName[valueName];
  78. -- 根据名字创建绑定表,一个名字可以绑定多次
  79. if bindTable == nil then
  80. bindTable = {};
  81. self.BindsByName[valueName] = bindTable;
  82. end
  83. self.BindIndex = self.BindIndex + 1
  84. -- 创建单个绑定实例
  85. local binder =
  86. {
  87. TargetNode = nil;
  88. ValueName = valueName;
  89. BindIndex = self.BindIndex;
  90. OnPropChanged = nil
  91. };
  92. self.BindsByIndex[binder.BindIndex] = binder;
  93. bindTable[binder.BindIndex] = binder;
  94. return binder;
  95. end
  96. -- 每秒回调一次
  97. function RemainTime:onTimer()
  98. local now = os.time()
  99. local elapse = (now - self.LastTime) * self.Speed;
  100. self.TotalElapse = self.TotalElapse + elapse
  101. self.LastTime = now
  102. -- 计算剩余时间
  103. self.Value = self.RemainTime - self.TotalElapse;
  104. if self.Value <= 0 then
  105. self.Value = 0;
  106. end
  107. --print("计算剩余时间:" , self.Value , self.RemainTime , seconds , now , self.StartTime);
  108. -- 触发数据修改通知
  109. self:triggerBinder("Value");
  110. -- 倒计时结束
  111. if self.Value <= 0 then
  112. --print("倒计时结束" , self.Value);
  113. self:stopTimer();
  114. if self.OnTimeOver then
  115. self.OnTimeOver(self);
  116. end;
  117. end;
  118. end
  119. -- 触发数据修改通知
  120. function RemainTime:triggerBinder(valueName)
  121. local value = self[valueName];
  122. --print("值改变:" , valueName , value);
  123. local binders = self.BindsByName[valueName];
  124. if binders then
  125. for i , v in pairs(binders) do
  126. v.OnPropChanged(valueName , value);
  127. end
  128. end
  129. end
  130. -- 开始计时器
  131. function RemainTime:startTimer()
  132. if self.Pause then
  133. return
  134. end
  135. if self.TimerID == nil then
  136. self.TimerID = cc.Director:getInstance():getScheduler():scheduleScriptFunc(function()self:onTimer()end, self.Interval, false);
  137. end
  138. end
  139. -- 停止计时器
  140. function RemainTime:stopTimer()
  141. if self.TimerID then
  142. cc.Director:getInstance():getScheduler():unscheduleScriptEntry(self.TimerID);
  143. self.TimerID = nil;
  144. end
  145. end
  146. -- 暂停计时器(计时器就不走了)
  147. function RemainTime:pause()
  148. if self.Pause then
  149. return
  150. end
  151. self:stopTimer()
  152. -- 执行一次时间
  153. self:onTimer()
  154. self.Pause = true
  155. end
  156. -- 恢复计时器
  157. function RemainTime:resume()
  158. if not self.Pause then
  159. return
  160. end
  161. self.Pause = false
  162. -- 如果时间完了就不能开始了
  163. if self.Value <= 0 then
  164. print("计时器时间已经流失完了,恢复失败")
  165. return
  166. end
  167. -- 重新设置下时间
  168. self:setRemainTime(self.Value)
  169. end
  170. -- 实现自动绑定数据的函数
  171. -- @valueName 需要绑定哪个变量名
  172. -- @propertyNameOrFunc , 当添加事件发生时的回调或设置什么属性,回调格式是func(key , value);
  173. -- @return 返回绑定索引
  174. function RemainTime:bind(valueName , propertyNameOrFunc , targetNode)
  175. local onPropChange;
  176. local typeP = type(propertyNameOrFunc);
  177. if typeP == "function" then
  178. onPropChange = function(key , value)
  179. propertyNameOrFunc(self , value);
  180. end
  181. elseif typeP == "string" then
  182. local function onChange(key , value)
  183. self[propertyNameOrFunc](self , value);
  184. end
  185. onPropChange = onChange
  186. else
  187. error("绑定数据" .. tostring(valueName) .. "时第三个参数错误,必须是属性名或函数" .. tostring(propertyNameOrFunc))
  188. return;
  189. end
  190. local binder = self:getBinder(valueName);
  191. binder.TargetNode = targetNode;
  192. binder.OnPropChanged = onPropChange;
  193. -- 开始计时
  194. if self.Value > 0 then
  195. self:startTimer();
  196. end
  197. self:triggerBinder(valueName);
  198. return binder.BindIndex;
  199. end
  200. -- 解除绑定
  201. function RemainTime:unbind(bindIndex)
  202. local binder = self.BindsByIndex[bindIndex];
  203. if binder == nil then
  204. print("找不到绑定索引" .. tostring(bindIndex));
  205. return;
  206. end
  207. self.BindsByName[binder.ValueName][bindIndex] = nil;
  208. self.BindsByIndex[bindIndex] = nil;
  209. -- 没人绑定了,就停止计时器
  210. if next(self.BindsByIndex) == nil then
  211. self:stopTimer();
  212. end
  213. end
  214. return RemainTime;