CPJSprite.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. using System;
  2. using CommonUI.Display;
  3. using CommonLang;
  4. namespace CommonUI.Cell.Game
  5. {
  6. public class CSpriteMeta
  7. {
  8. public const byte CD_TYPE_MAP = 0;
  9. public const byte CD_TYPE_ATK = 1;
  10. public const byte CD_TYPE_DEF = 2;
  11. public const byte CD_TYPE_EXT = 3;
  12. private SpriteSet data;
  13. private CAnimates animates;
  14. private CCollides collides;
  15. private int animCount;
  16. private int[] frameCounts;
  17. //frameAnimate[animate id][frame id] = canimate frame index.
  18. private string[] AnimateNames;
  19. //
  20. private int[][] FrameAnimate;
  21. // frameAnimate[animate id][frame id] = ccollide frame index.
  22. private int[][] FrameCDMap;
  23. // frameAnimate[animate id][frame id] = ccollide frame index.
  24. private int[][] FrameCDAtk;
  25. // frameAnimate[animate id][frame id] = ccollide frame index.
  26. private int[][] FrameCDDef;
  27. // frameAnimate[animate id][frame id] = ccollide frame index.
  28. private int[][] FrameCDExt;
  29. private float[][] FrameAlpha;
  30. public CAnimates Animates { get { return animates; } }
  31. public CCollides Collides { get { return collides; } }
  32. public SpriteSet Data { get { return data; } }
  33. public CPJAtlas Atlas { get { return animates.tiles; } }
  34. public CSpriteMeta(SpriteSet tsprite, CPJAtlas tiles)
  35. {
  36. this.data = tsprite;
  37. {
  38. //scene parts
  39. int scenePartCount = tsprite.PartTileID.Length; // --> u16
  40. CAnimates animates = new CAnimates(scenePartCount, tiles);
  41. for (int i = 0; i < scenePartCount; i++)
  42. {
  43. animates.setPart(i,
  44. tsprite.PartX[i],
  45. tsprite.PartY[i],
  46. tsprite.PartTileID[i],
  47. tsprite.PartTileTrans[i],
  48. tsprite.PartAlpha[i],
  49. tsprite.PartRotate[i],
  50. tsprite.PartScaleX[i],
  51. tsprite.PartScaleY[i]);
  52. }
  53. //scene frames
  54. animates.setFrames(tsprite.Parts);
  55. //cd parts
  56. int cdCount = tsprite.BlocksMask.Length; // --> u16
  57. CCollides collides = new CCollides(cdCount);
  58. for (int i = 0; i < cdCount; i++)
  59. {
  60. collides.setCDRect(i,
  61. tsprite.BlocksMask[i],
  62. tsprite.BlocksX1[i],
  63. tsprite.BlocksY1[i],
  64. tsprite.BlocksW[i],
  65. tsprite.BlocksH[i]);
  66. }
  67. //cd frames
  68. collides.setFrames(tsprite.Blocks);
  69. this.animates = animates;
  70. this.collides = collides;
  71. }
  72. {
  73. animCount = tsprite.AnimateCount;
  74. frameCounts = new int[animCount];
  75. AnimateNames = tsprite.AnimateNames;
  76. FrameAnimate = new int[animCount][];
  77. FrameCDMap = new int[animCount][];
  78. FrameCDAtk = new int[animCount][];
  79. FrameCDDef = new int[animCount][];
  80. FrameCDExt = new int[animCount][];
  81. FrameAlpha = new float[animCount][];
  82. for (int a = 0; a < animCount; a++)
  83. {
  84. int fc = tsprite.FrameAnimate[a].Length;
  85. frameCounts[a] = fc;
  86. FrameAnimate[a] = new int[fc];
  87. FrameCDMap[a] = new int[fc];
  88. FrameCDAtk[a] = new int[fc];
  89. FrameCDDef[a] = new int[fc];
  90. FrameCDExt[a] = new int[fc];
  91. FrameAlpha[a] = new float[fc];
  92. for (int f = 0; f < fc; f++)
  93. {
  94. FrameAnimate[a][f] = tsprite.FrameAnimate[a][f];
  95. FrameCDMap[a][f] = tsprite.FrameCDMap[a][f];
  96. FrameCDAtk[a][f] = tsprite.FrameCDAtk[a][f];
  97. FrameCDDef[a][f] = tsprite.FrameCDDef[a][f];
  98. FrameCDExt[a][f] = tsprite.FrameCDExt[a][f];
  99. FrameAlpha[a][f] = tsprite.FrameAlpha[a][f];
  100. }
  101. }
  102. }
  103. }
  104. // ------------------------------------------------------------------------------------------
  105. public int getFrameImageCount(int anim, int frame = 0)
  106. {
  107. return animates.getComboFrameCount(FrameAnimate[anim][frame]);
  108. }
  109. public int getFrameTileID(int anim, int frame = 0, int sub = 0)
  110. {
  111. return animates.getFrameTileID(FrameAnimate[anim][frame], sub);
  112. }
  113. public float getFrameImageX(int anim, int frame = 0, int sub = 0)
  114. {
  115. return animates.getFrameX(FrameAnimate[anim][frame], sub);
  116. }
  117. public float getFrameImageY(int anim, int frame = 0, int sub = 0)
  118. {
  119. return animates.getFrameY(FrameAnimate[anim][frame], sub);
  120. }
  121. public float getFrameImageWidth(int anim, int frame = 0, int sub = 0)
  122. {
  123. return animates.getFrameW(FrameAnimate[anim][frame], sub);
  124. }
  125. public float getFrameImageHeight(int anim, int frame = 0, int sub = 0)
  126. {
  127. return animates.getFrameH(FrameAnimate[anim][frame], sub);
  128. }
  129. public Trans getFrameImageTransform(int anim, int frame = 0, int sub = 0)
  130. {
  131. return animates.getFrameTransform(FrameAnimate[anim][frame], sub);
  132. }
  133. public int getAvaliableTileID()
  134. {
  135. for (int anim = 0; anim < getAnimateCount(); anim++)
  136. {
  137. for (int frame = 0; frame < getFrameCount(anim); frame++)
  138. {
  139. for (int sub = 0; sub < getFrameImageCount(anim, frame); sub++)
  140. {
  141. int tid = getFrameTileID(anim, frame, sub);
  142. if (!Atlas.IsNullTile(tid))
  143. {
  144. return tid;
  145. }
  146. }
  147. }
  148. }
  149. return 0;
  150. }
  151. // ------------------------------------------------------------------------------------------
  152. public int[][] getCDAnimates(byte type)
  153. {
  154. switch (type)
  155. {
  156. case CD_TYPE_MAP:
  157. return FrameCDMap;
  158. case CD_TYPE_ATK:
  159. return FrameCDAtk;
  160. case CD_TYPE_DEF:
  161. return FrameCDDef;
  162. case CD_TYPE_EXT:
  163. return FrameCDExt;
  164. }
  165. return null;
  166. }
  167. public int getFrameCDCount(int anim, int frame, byte type)
  168. {
  169. int[][] out_animates = getCDAnimates(type);
  170. if (out_animates != null)
  171. {
  172. return collides.getComboFrameCount(out_animates[anim][frame]);
  173. }
  174. return -1;
  175. }
  176. public CCD getFrameCD(int anim, int frame, byte type, int sub)
  177. {
  178. int[][] out_animates = getCDAnimates(type);
  179. if (out_animates != null)
  180. {
  181. return collides.getFrameCD(out_animates[anim][frame], sub);
  182. }
  183. return null;
  184. }
  185. // ------------------------------------------------------------------------------------------
  186. public CCD getVisibleBounds()
  187. {
  188. return animates.getAllBounds();
  189. }
  190. public CCD getVisibleBounds(int anim, int frame)
  191. {
  192. if (anim < animCount)
  193. {
  194. if (frame < frameCounts[anim])
  195. {
  196. CCD out_bounds = new CCD();
  197. out_bounds.X1 = float.MaxValue;
  198. out_bounds.X2 = float.MinValue;
  199. out_bounds.Y1 = float.MaxValue;
  200. out_bounds.Y2 = float.MinValue;
  201. int frameid = FrameAnimate[anim][frame];
  202. int count = animates.getComboFrameCount(frameid);
  203. for (int i = 0; i < count; i++)
  204. {
  205. out_bounds.X1 = Math.Min(out_bounds.X1, animates.getFrameX(frameid, i));
  206. out_bounds.Y1 = Math.Min(out_bounds.Y1, animates.getFrameY(frameid, i));
  207. out_bounds.X2 = Math.Max(out_bounds.X2, animates.getFrameX(frameid, i) + animates.getFrameW(frameid, i));
  208. out_bounds.Y2 = Math.Max(out_bounds.Y2, animates.getFrameY(frameid, i) + animates.getFrameH(frameid, i));
  209. }
  210. return out_bounds;
  211. }
  212. }
  213. return null;
  214. }
  215. public CCD getVisibleBounds(int anim)
  216. {
  217. if (anim < animCount)
  218. {
  219. CCD out_bounds = new CCD();
  220. out_bounds.X1 = float.MaxValue;
  221. out_bounds.X2 = float.MinValue;
  222. out_bounds.Y1 = float.MaxValue;
  223. out_bounds.Y2 = float.MinValue;
  224. for (int f = getFrameCount(anim) - 1; f >= 0; --f)
  225. {
  226. int frameid = FrameAnimate[anim][f];
  227. int count = animates.getComboFrameCount(frameid);
  228. for (int i = 0; i < count; i++)
  229. {
  230. out_bounds.X1 = Math.Min(out_bounds.X1, animates.getFrameX(frameid, i));
  231. out_bounds.Y1 = Math.Min(out_bounds.Y1, animates.getFrameY(frameid, i));
  232. out_bounds.X2 = Math.Max(out_bounds.X2, animates.getFrameX(frameid, i) + animates.getFrameW(frameid, i));
  233. out_bounds.Y2 = Math.Max(out_bounds.Y2, animates.getFrameY(frameid, i) + animates.getFrameH(frameid, i));
  234. }
  235. }
  236. return out_bounds;
  237. }
  238. return null;
  239. }
  240. public CCD getCDBounds()
  241. {
  242. return collides.getAllBounds();
  243. }
  244. public int getAnimateIndex(string animate_name)
  245. {
  246. for (int i = animCount - 1; i >= 0; --i)
  247. {
  248. if (string.Equals(AnimateNames[i], animate_name))
  249. {
  250. return i;
  251. }
  252. }
  253. return -1;
  254. }
  255. public string getAnimateName(int anim)
  256. {
  257. return AnimateNames[anim];
  258. }
  259. public int getAnimateCount()
  260. {
  261. return animCount;
  262. }
  263. public int getFrameCount(int anim)
  264. {
  265. return frameCounts[anim];
  266. }
  267. public void render(Graphics g, int anim, int frame, float dx = 0, float dy = 0)
  268. {
  269. if ((anim < animCount) && (frame < frameCounts[anim]))
  270. {
  271. float olda = g.getAlpha();
  272. g.addAlpha(FrameAlpha[anim][frame]);
  273. animates.render(g, FrameAnimate[anim][frame], dx, dy);
  274. g.setAlpha(olda);
  275. }
  276. }
  277. public void addVertex(VertexBuffer v, int anim, int frame, float dx, float dy)
  278. {
  279. if ((anim < animCount) && (frame < frameCounts[anim]))
  280. {
  281. animates.addVertex(v, FrameAnimate[anim][frame], dx, dy);
  282. }
  283. }
  284. public void beginImage(Graphics g)
  285. {
  286. animates.beginImage(g);
  287. }
  288. }
  289. public struct TSpriteMetaAnimateFrame
  290. {
  291. public CSpriteMeta sprite;
  292. public int anim, frame;
  293. }
  294. /// <summary>
  295. /// CPJSprite 控制类
  296. /// </summary>
  297. public class CSpriteController : ICellSpriteController
  298. {
  299. private readonly CSpriteMeta mMeta;
  300. private int mCurAnimate = 0;
  301. private int mCurFrame = 0;
  302. private int mPlayTimes = -1;
  303. private int mCurrentPlayTimes = 0;
  304. public bool IsAutoPlay = true;
  305. public CSpriteController(CSpriteMeta src)
  306. {
  307. mMeta = src;
  308. }
  309. public bool Update()
  310. {
  311. if (IsAutoPlay)
  312. {
  313. NextCycFrame();
  314. PlayTimesTick();
  315. return true;
  316. }
  317. return false;
  318. }
  319. public void Dispose()
  320. {
  321. IsAutoPlay = false;
  322. m_FinishCallback = null;
  323. }
  324. public CSpriteMeta Meta
  325. {
  326. get { return mMeta; }
  327. }
  328. public int CurrentFrame
  329. {
  330. get { return mCurFrame; }
  331. }
  332. public int CurrentAnimate
  333. {
  334. get { return mCurAnimate; }
  335. }
  336. public bool IsEndFrame
  337. {
  338. get
  339. {
  340. if (mCurFrame + 1 >= mMeta.getFrameCount(mCurAnimate))
  341. {
  342. return true;
  343. }
  344. else
  345. {
  346. return false;
  347. }
  348. }
  349. }
  350. public void SetCurrentAnimate(string anim_name)
  351. {
  352. int anim = mMeta.getAnimateIndex(anim_name);
  353. if (anim >= 0)
  354. {
  355. SetCurrentAnimate(anim);
  356. }
  357. }
  358. public void SetCurrentAnimate(int anim)
  359. {
  360. mCurAnimate = anim;
  361. mCurAnimate = CMath.cycNum(mCurAnimate, 0, mMeta.getAnimateCount());
  362. mCurFrame = CMath.cycNum(mCurFrame, 0, mMeta.getFrameCount(mCurAnimate));
  363. }
  364. public void SetCurrentFrame(int anim, int index)
  365. {
  366. mCurAnimate = CMath.cycNum(anim, 0, mMeta.getAnimateCount());
  367. mCurFrame = CMath.cycNum(index, 0, mMeta.getFrameCount(mCurAnimate));
  368. }
  369. public bool NextFrame()
  370. {
  371. mCurFrame++;
  372. int acount = mMeta.getFrameCount(mCurAnimate);
  373. if (mCurFrame >= acount)
  374. {
  375. mCurFrame = acount - 1;
  376. return true;
  377. }
  378. else
  379. {
  380. return false;
  381. }
  382. }
  383. public void NextCycFrame()
  384. {
  385. mCurFrame++;
  386. int acount = mMeta.getFrameCount(mCurAnimate);
  387. if (acount > 0)
  388. {
  389. mCurFrame %= acount;
  390. }
  391. }
  392. public void NextCycFrame(int restart)
  393. {
  394. mCurFrame++;
  395. int acount = mMeta.getFrameCount(mCurAnimate);
  396. if (mCurFrame < acount)
  397. {
  398. }
  399. else
  400. {
  401. if (acount > 0)
  402. {
  403. mCurFrame = (restart % acount);
  404. }
  405. }
  406. }
  407. public bool PrewFrame()
  408. {
  409. mCurFrame--;
  410. if (mCurFrame < 0)
  411. {
  412. mCurFrame = 0;
  413. return true;
  414. }
  415. else
  416. {
  417. return false;
  418. }
  419. }
  420. public void PrewCycFrame()
  421. {
  422. mCurFrame--;
  423. if (mCurFrame < 0)
  424. {
  425. mCurFrame = mMeta.getFrameCount(mCurAnimate) - 1;
  426. }
  427. }
  428. public void PrewCycFrame(int restart)
  429. {
  430. mCurFrame--;
  431. if (mCurFrame < 0)
  432. {
  433. mCurFrame = (restart % mMeta.getFrameCount(mCurAnimate));
  434. }
  435. }
  436. /// <summary>
  437. /// 播放动画:anim动画名、times次数(-1=无限).
  438. /// </summary>
  439. /// <param name="anim"></param>
  440. /// <param name="times"></param>
  441. /// <param name="callBack"></param>
  442. public void PlayAnimate(int anim, int times, CSpriteEventHandler callBack)
  443. {
  444. mPlayTimes = times;
  445. m_FinishCallback = callBack;
  446. SetCurrentAnimate(anim);
  447. mCurFrame = 0;
  448. IsAutoPlay = true;
  449. }
  450. /// <summary>
  451. /// 播放动画:anim_name动画名、times次数(-1=无限).
  452. /// </summary>
  453. /// <param name="anim_name"></param>
  454. /// <param name="times"></param>
  455. /// <param name="callBack"></param>
  456. public void PlayAnimate(string anim_name, int times, CSpriteEventHandler callBack)
  457. {
  458. int anim = mMeta.getAnimateIndex(anim_name);
  459. if (anim >= 0)
  460. {
  461. PlayAnimate(anim, times, callBack);
  462. }
  463. }
  464. public void StopAnimate(bool needCallBack)
  465. {
  466. IsAutoPlay = false;
  467. if (m_FinishCallback != null && needCallBack)
  468. {
  469. m_FinishCallback(this);
  470. }
  471. m_FinishCallback = null;
  472. }
  473. private void PlayTimesTick()
  474. {
  475. if (mPlayTimes < 0) { return; }
  476. if (!IsEndFrame) { return; }
  477. mCurrentPlayTimes++;
  478. if (mCurrentPlayTimes >= mPlayTimes)
  479. {
  480. IsAutoPlay = false;
  481. if (m_FinishCallback != null)
  482. {
  483. CSpriteEventHandler temp = m_FinishCallback;
  484. m_FinishCallback = null;
  485. temp(this);
  486. temp = null;
  487. }
  488. }
  489. }
  490. //---------------------------------------------------------------------------------------------------
  491. private CSpriteEventHandler m_FinishCallback;
  492. public event CSpriteEventHandler Finish { add { m_FinishCallback += value; } remove { m_FinishCallback -= value; } }
  493. //---------------------------------------------------------------------------------------------------
  494. }
  495. /// <summary>
  496. /// 动画编辑器控制类
  497. /// </summary>
  498. public interface ICellSpriteController
  499. {
  500. int CurrentFrame { get; }
  501. int CurrentAnimate { get; }
  502. bool IsEndFrame { get; }
  503. void SetCurrentAnimate(string anim);
  504. void SetCurrentAnimate(int anim);
  505. void SetCurrentFrame(int anim, int index);
  506. bool NextFrame();
  507. void NextCycFrame();
  508. void NextCycFrame(int restart);
  509. bool PrewFrame();
  510. void PrewCycFrame();
  511. void PrewCycFrame(int restart);
  512. }
  513. public delegate void CSpriteEventHandler(ICellSpriteController sender);
  514. }