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.

295 lines
8.3 KiB

  1. -- 动画播放实例,根据状态表来决定什么状态播放什么动画
  2. -- 对外接口:
  3. --[[
  4. self.Entity 骨骼动画的节点
  5. self.StateValues 可以用来做数据绑定的状态值列表
  6. self.OnStateFinished 状态播放完成的回调,参数形式OnStateFinish(animEntity, key , value)
  7. self.OnGetNextValue 状态播放完成后需要把value设置成什么的回调,,参数形式OnGetNextValue(animEntity, key , value),函数里要返回一个int,表示value要变成什么
  8. self:setValue
  9. self:getValue
  10. --]]
  11. local AnimEntity = class("AnimEntity")
  12. -- 初始化,传进来initStatus是状态表,拥有多少个状态,以及各个状态的值
  13. -- animation 动画名字
  14. -- loop 是否循环播放
  15. -- staticWhenEnd 是否静止在最后一帧
  16. -- randomPosition 开始播放这个动画时是否使用随机位置
  17. --[[
  18. local status = {
  19. death =
  20. {
  21. 1 = {animation = "death" , loop = true};
  22. };
  23. skill =
  24. {
  25. 1 = {animation = "skill" , loop = false};
  26. };
  27. attack =
  28. {
  29. 1 = {animation = "attack" , loop = false};
  30. };
  31. move =
  32. {
  33. 0 = {animation = "stand" , loop = true};
  34. 1 = {animation = "move" , loop = true};
  35. };
  36. }
  37. local function getAnimation(values)
  38. if values.death == 1 then
  39. return status.death[1];
  40. elseif values.skill == 1 then
  41. return status.skill[1];
  42. elseif values.attack == 1 then
  43. return status.attack[1];
  44. elseif values.move == 1 then
  45. return status.move[1];
  46. else
  47. return status.move[0];
  48. end
  49. end
  50. local entity = AnimEntity:new(skeleton , status , getAnimation);
  51. --]]
  52. function AnimEntity:ctor(skeletonEntity , initStatus , callbackGetAnimation)
  53. self.Status = initStatus;
  54. self.StateValues = require("luaScript.Protocol.BindableArray")();
  55. self.CallbackGetAnimation = callbackGetAnimation
  56. self.CurrentAnimation = nil;
  57. self.Entity = skeletonEntity;
  58. skeletonEntity.AnimEntity = self;
  59. self:initStatus();
  60. end
  61. -- 初始化状态表
  62. function AnimEntity:initStatus()
  63. for i , v in pairs(self.Status) do
  64. self.StateValues[i] = 0;
  65. -- 初始化所有动画长度
  66. for ii , state in pairs(v) do
  67. state.OnStateFinished = {};
  68. state.OnGetNextValue = {};
  69. local clipFile;
  70. if self.Entity.getClipFile then
  71. clipFile = self.Entity:getClipFile();
  72. end
  73. if clipFile then
  74. local clip = clipFile:getAnimationClip(state.animation);
  75. if clip == nil then
  76. print("获取模型动画" .. state.animation .. "失败" , self.Entity:getMeshFile());
  77. else
  78. -- 这个动画的持续时间为毫秒
  79. state.duration = clip:getDuration() / 1000 / clip:getSpeed();
  80. if state.duration == nil then
  81. error("获取模型动画" .. state.animation .. "长度失败" , self.Entity:getMeshFile());
  82. end
  83. -- 这里不用侦听了,因为我们统一通过Action来停止
  84. -- 侦听动画结束回调
  85. --self.Entity:getAnimationClip(state.animation):addEndListener(function()self:onPlayEnd(state.animation)end);
  86. end
  87. end
  88. end
  89. end
  90. -- 侦听状态改变通知
  91. self.Entity:bindUpdate(self.StateValues , handler(self , self.updateState));
  92. local function initAnimation(index)
  93. if self.CurrentAnimation then
  94. self:onChangeAnimation(nil , self.CurrentAnimation);
  95. end
  96. end
  97. self.Entity:runOnLoad(initAnimation);
  98. end
  99. --[[
  100. -- 事件回调
  101. function AnimEntity:onPlayEnd(animation)
  102. -- 动画播放完毕
  103. -- 完成了一次循环,则把非循环动画停止
  104. if self.CurrentAnimation ~= nil and animation == self.CurrentAnimation.animation and not self.CurrentAnimation.loop and not self.CurrentAnimation.staticWhenEnd then
  105. --print(tostring(self) .. "动画complete" .. animation);
  106. self.CurrentAnimation = nil;
  107. end
  108. end
  109. --]]
  110. -- 一个状态的动作是否无限长
  111. function AnimEntity:isInfiniteByState(stateName, stateValue)
  112. local stateInfo = self.Status[stateName]
  113. if stateInfo ~= nil and stateInfo[stateValue] ~= nil then
  114. return stateInfo[stateValue].loop
  115. end
  116. return false
  117. end
  118. -- 改变状态值
  119. function AnimEntity:setValue(state , value)
  120. self.StateValues[state] = value;
  121. end
  122. -- 获取状态值
  123. function AnimEntity:getValue(state)
  124. return self.StateValues[state];
  125. end
  126. function AnimEntity:addStateFinishListener(state , value , listener)
  127. local stateStatus = self.Status[state][value];
  128. if stateStatus.OnStateFinishedLoop then
  129. print("AnimEntity:addStateFinishListener,添加无效", state, value)
  130. return
  131. end
  132. stateStatus.OnStateFinished[listener] = listener;
  133. end
  134. function AnimEntity:removeStateFinishListener(state , value , listener)
  135. local stateStatus = self.Status[state][value];
  136. if stateStatus.OnStateFinishedLoop then
  137. --print("AnimEntity:removeStateFinishListener,移除无效, 遍历完成后会全部移除掉的", state, value)
  138. return
  139. end
  140. stateStatus.OnStateFinished[listener] = nil;
  141. end
  142. function AnimEntity:addNextValueListener(state , value , listener)
  143. local stateStatus = self.Status[state][value];
  144. if stateStatus.OnGetNextValueLoop then
  145. print("AnimEntity:addNextValueListener,添加无效", state, value)
  146. return
  147. end
  148. stateStatus.OnGetNextValue[listener] = listener;
  149. end
  150. function AnimEntity:removeNextValueListener(state , value , listener)
  151. local stateStatus = self.Status[state][value];
  152. if stateStatus.OnGetNextValueLoop then
  153. print("AnimEntity:removeNextValueListener,移除无效, 遍历完成后会全部移除掉的", state, value)
  154. return
  155. end
  156. stateStatus.OnGetNextValue[listener] = nil;
  157. end
  158. function AnimEntity:resetValues()
  159. for i , v in self.StateValues:pairs() do
  160. if v ~= 0 then
  161. self.StateValues[i] = 0;
  162. end
  163. end
  164. end
  165. -- 更新状态
  166. function AnimEntity:updateState(entity , key , value)
  167. --print(tostring(self) .. "动画状态改变:" .. key .. " = " .. value);
  168. -- 找不到对应的状态名(则说明设置错了)
  169. if self.Status[key] == nil then
  170. print("找不到对应的状态名:" .. key);
  171. return
  172. end
  173. local state = self.Status[key][value];
  174. if state then
  175. if tolua.isnull(state.Action) then
  176. -- 非循环状态,则自动停止
  177. if not state.loop then
  178. local function onEnd()
  179. state.Action = nil;
  180. state.OnStateFinishedLoop = true
  181. -- 动画状态播放完成回调
  182. for i , v in pairs(state.OnStateFinished) do
  183. v(self, key , value);
  184. end
  185. state.OnStateFinishedLoop = false
  186. state.OnStateFinished = {}
  187. --print(tostring(self) .. "动画状态播放完毕" .. state.animation);
  188. if not state.staticWhenEnd then
  189. local retValue = 0;
  190. state.OnGetNextValueLoop = true
  191. -- 获取播放完毕要设置的值
  192. for i , v in pairs(state.OnGetNextValue) do
  193. local nextValue = v(self, key , value);
  194. if nextValue then
  195. retValue = nextValue;
  196. end
  197. end
  198. state.OnGetNextValueLoop = false
  199. state.OnGetNextValue = {}
  200. self:setValue(key , retValue);
  201. end
  202. end
  203. -- 当模型没有这个动画时duration在开始的时候并没有赋值
  204. if state.duration ~= nil then
  205. -- 时间到了之后,自动把状态设置成0
  206. state.Action = self.Entity:runActions(cc.DelayTime:create(state.duration) , onEnd);
  207. state.Action.OnEnd = onEnd;
  208. else
  209. -- 没有这个动画的立马回调
  210. onEnd();
  211. end
  212. end
  213. end
  214. end
  215. local anim = self.CallbackGetAnimation(self.StateValues)
  216. self:setAnimation(anim);
  217. end
  218. -- 设置当前状态
  219. function AnimEntity:setAnimation(animation)
  220. if self.CurrentAnimation == animation then
  221. return;
  222. end
  223. local from = self.CurrentAnimation;
  224. self.CurrentAnimation = animation;
  225. if self.Entity:getModelScene() then
  226. self:onChangeAnimation(from , animation);
  227. end
  228. end
  229. -- 动画改变通知
  230. function AnimEntity:onChangeAnimation(from , to)
  231. --print(tostring(self) .. "播放动画" .. to.animation);
  232. local fromClip;
  233. -- 先停止之前的动画
  234. if from then
  235. fromClip = self.Entity:getAnimationClip(from.animation);
  236. -- 停止回调
  237. if from.Action then
  238. if not tolua.isnull(from.Action) then
  239. from.Action.OnEnd();
  240. self.Entity:stopAction(from.Action)
  241. end
  242. from.Action = nil;
  243. end
  244. end
  245. local targetClip = self.Entity:getAnimationClip(to.animation);
  246. if targetClip then
  247. if to.loop then
  248. targetClip:setRepeatCount(0);
  249. else
  250. targetClip:setRepeatCount(1);
  251. end
  252. if fromClip then
  253. --print("从" , fromClip:getId() , "切换到" , targetClip:getId());
  254. fromClip:crossFade(targetClip , 200);
  255. else
  256. --print("直接播放" , targetClip:getId());
  257. targetClip:play();
  258. end
  259. -- 随机设置开始位置
  260. if to.randomPosition then
  261. targetClip:setTimePosition(math.random(0 , targetClip:getDuration()));
  262. end
  263. end
  264. end
  265. return AnimEntity;