zglSpriteEngine.pas 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. {
  2. * Copyright (c) 2012 Andrey Kemka
  3. *
  4. * This software is provided 'as-is', without any express or
  5. * implied warranty. In no event will the authors be held
  6. * liable for any damages arising from the use of this software.
  7. *
  8. * Permission is granted to anyone to use this software for any purpose,
  9. * including commercial applications, and to alter it and redistribute
  10. * it freely, subject to the following restrictions:
  11. *
  12. * 1. The origin of this software must not be misrepresented;
  13. * you must not claim that you wrote the original software.
  14. * If you use this software in a product, an acknowledgment
  15. * in the product documentation would be appreciated but
  16. * is not required.
  17. *
  18. * 2. Altered source versions must be plainly marked as such,
  19. * and must not be misrepresented as being the original software.
  20. *
  21. * 3. This notice may not be removed or altered from any
  22. * source distribution.
  23. }
  24. unit zglSpriteEngine;
  25. {$I zglCustomConfig.cfg}
  26. {$IFDEF FPC}
  27. {$MODE DELPHI}
  28. {$ENDIF}
  29. interface
  30. uses
  31. zgl_window,
  32. zgl_fx,
  33. zgl_sprite_2d,
  34. zgl_textures,
  35. zgl_types;
  36. type
  37. zglCSprite2D = class;
  38. // zglCSEngine2D = class;
  39. zglCSEngine2D = class
  40. protected
  41. FCount : Integer;
  42. FList : array of zglCSprite2D;
  43. procedure SortByLayer( iLo, iHi : Integer );
  44. procedure SortByID( iLo, iHi : Integer );
  45. function GetSprite( ID : Integer ) : zglCSprite2D;
  46. procedure SetSprite( ID : Integer; Sprite : zglCSprite2D );
  47. public
  48. destructor Destroy; override;
  49. function AddSprite : Integer; overload; virtual;
  50. function AddSprite( Texture : zglPTexture; Layer : Integer ) : zglCSprite2D; overload; virtual;
  51. procedure AddSprite( Sprite : zglCSprite2D; Layer : Integer ); overload; virtual;
  52. procedure DelSprite( ID : Integer ); virtual;
  53. procedure ClearAll; virtual;
  54. procedure Draw; virtual;
  55. procedure Proc; virtual;
  56. property Count: Integer read FCount;
  57. property List[ID : Integer]: zglCSprite2D read GetSprite write SetSprite;
  58. end;
  59. zglCSprite2D = class
  60. protected
  61. public
  62. ID : Integer;
  63. Manager : zglCSEngine2D;
  64. Texture : zglPTexture;
  65. Kill : Boolean;
  66. Layer : Integer;
  67. X, Y : Single;
  68. W, H : Single;
  69. Angle : Single;
  70. Frame : Single;
  71. Alpha : Integer;
  72. FxFlags : LongWord;
  73. constructor Create( _Manager : zglCSEngine2D; _ID : Integer ); virtual;
  74. destructor Destroy; override;
  75. procedure OnInit( _Texture : zglPTexture; _Layer : Integer ); virtual;
  76. procedure OnDraw; virtual;
  77. procedure OnProc; virtual;
  78. procedure OnFree; virtual;
  79. end;
  80. implementation
  81. destructor zglCSEngine2D.Destroy;
  82. begin
  83. ClearAll();
  84. end;
  85. procedure zglCSEngine2D.SortByLayer( iLo, iHi : Integer );
  86. var
  87. lo, hi, mid : Integer;
  88. t : zglCSprite2D;
  89. begin
  90. lo := iLo;
  91. hi := iHi;
  92. mid := FList[ ( lo + hi ) shr 1 ].Layer;
  93. repeat
  94. while FList[ lo ].Layer < mid do INC( lo );
  95. while FList[ hi ].Layer > mid do DEC( hi );
  96. if lo <= hi then
  97. begin
  98. t := FList[ lo ];
  99. FList[ lo ] := FList[ hi ];
  100. FList[ hi ] := t;
  101. INC( lo );
  102. DEC( hi );
  103. end;
  104. until lo > hi;
  105. if hi > iLo Then SortByLayer( iLo, hi );
  106. if lo < iHi Then SortByLayer( lo, iHi );
  107. end;
  108. procedure zglCSEngine2D.SortByID( iLo, iHi : Integer );
  109. var
  110. lo, hi, mid : Integer;
  111. t : zglCSprite2D;
  112. begin
  113. lo := iLo;
  114. hi := iHi;
  115. mid := FList[ ( lo + hi ) shr 1 ].ID;
  116. repeat
  117. while FList[ lo ].ID < mid do INC( lo );
  118. while FList[ hi ].ID > mid do DEC( hi );
  119. if Lo <= Hi then
  120. begin
  121. t := FList[ lo ];
  122. FList[ lo ] := FList[ hi ];
  123. FList[ hi ] := t;
  124. INC( lo );
  125. DEC( hi );
  126. end;
  127. until lo > hi;
  128. if hi > iLo Then SortByID( iLo, hi );
  129. if lo < iHi Then SortByID( lo, iHi );
  130. end;
  131. function zglCSEngine2D.GetSprite( ID : Integer ) : zglCSprite2D;
  132. begin
  133. Result := FList[ ID ];
  134. end;
  135. procedure zglCSEngine2D.SetSprite( ID : Integer; Sprite : zglCSprite2D );
  136. begin
  137. FList[ ID ] := Sprite;
  138. end;
  139. function zglCSEngine2D.AddSprite : Integer;
  140. begin
  141. if FCount + 1 > Length( FList ) Then
  142. SetLength( FList, FCount + 16384 );
  143. Result := FCount;
  144. INC( FCount );
  145. end;
  146. function zglCSEngine2D.AddSprite( Texture : zglPTexture; Layer : Integer ) : zglCSprite2D;
  147. var
  148. id : Integer;
  149. begin
  150. id := AddSprite();
  151. FList[ id ] := zglCSprite2D.Create( Self, id );
  152. Result := FList[ id ];
  153. Result.OnInit( Texture, Layer );
  154. end;
  155. procedure zglCSEngine2D.AddSprite( Sprite : zglCSprite2D; Layer : Integer );
  156. var
  157. id : Integer;
  158. begin
  159. if not Assigned( Sprite ) Then exit;
  160. id := AddSprite();
  161. FList[ id ] := Sprite;
  162. FList[ id ].Manager := Self;
  163. FList[ id ].ID := id;
  164. FList[ id ].OnInit( Sprite.Texture, Layer );
  165. end;
  166. procedure zglCSEngine2D.DelSprite( ID : Integer );
  167. var
  168. i : Integer;
  169. begin
  170. if ( ID < 0 ) or ( ID > FCount - 1 ) or ( FCount = 0 ) Then exit;
  171. FList[ ID ].Free;
  172. for i := ID to FCount - 2 do
  173. begin
  174. FList[ i ] := FList[ i + 1 ];
  175. FList[ i ].ID := i;
  176. end;
  177. DEC( FCount );
  178. end;
  179. procedure zglCSEngine2D.ClearAll;
  180. var
  181. i : Integer;
  182. begin
  183. for i := 0 to FCount - 1 do
  184. FList[ i ].Destroy();
  185. SetLength( FList, 0 );
  186. FCount := 0;
  187. end;
  188. procedure zglCSEngine2D.Draw;
  189. var
  190. i : Integer;
  191. s : zglCSprite2D;
  192. begin
  193. i := 0;
  194. while i < FCount do
  195. begin
  196. s := FList[ i ];
  197. s.OnDraw();
  198. if s.Kill Then
  199. DelSprite( s.ID )
  200. else
  201. INC( i );
  202. end;
  203. end;
  204. procedure zglCSEngine2D.Proc;
  205. var
  206. i, a, b, l : Integer;
  207. s : zglCSprite2D;
  208. begin
  209. i := 0;
  210. while i < FCount do
  211. begin
  212. s := FList[ i ];
  213. s.OnProc();
  214. if s.Kill Then
  215. DelSprite( s.ID )
  216. else
  217. INC( i );
  218. end;
  219. if FCount > 1 Then
  220. begin
  221. l := 0;
  222. for i := 0 to FCount - 1 do
  223. begin
  224. s := FList[ i ];
  225. if s.Layer > l Then l := s.Layer;
  226. if s.Layer < l Then
  227. begin
  228. SortByLayer( 0, FCount - 1 );
  229. // TODO: provide parameter for enabling/disabling stable sorting
  230. l := FList[ 0 ].Layer;
  231. a := 0;
  232. for b := 0 to FCount - 1 do
  233. begin
  234. s := FList[ b ];
  235. if ( l <> s.Layer ) Then
  236. begin
  237. SortByID( a, b - 1 );
  238. a := b;
  239. l := s.Layer;
  240. end;
  241. if b = FCount - 1 Then
  242. SortByID( a, b );
  243. end;
  244. for a := 0 to FCount - 1 do
  245. FList[ a ].ID := a;
  246. break;
  247. end;
  248. end;
  249. end;
  250. end;
  251. constructor zglCSprite2D.Create( _Manager : zglCSEngine2D; _ID : Integer );
  252. begin
  253. Manager := _Manager;
  254. ID := _ID;
  255. OnInit( nil, 0 );
  256. end;
  257. destructor zglCSprite2D.Destroy;
  258. begin
  259. OnFree();
  260. end;
  261. procedure zglCSprite2D.OnInit( _Texture : zglPTexture; _Layer : Integer );
  262. begin
  263. Texture := _Texture;
  264. Layer := _Layer;
  265. X := 0;
  266. Y := 0;
  267. if Assigned( Texture ) Then
  268. begin
  269. W := Round( ( Texture.FramesCoord[ 1, 1 ].X - Texture.FramesCoord[ 1, 0 ].X ) * Texture.Width / Texture.U );
  270. H := Round( ( Texture.FramesCoord[ 1, 0 ].Y - Texture.FramesCoord[ 1, 2 ].Y ) * Texture.Height / Texture.V );
  271. end else
  272. begin
  273. W := 0;
  274. H := 0;
  275. end;
  276. Angle := 0;
  277. Frame := 1;
  278. Alpha := 255;
  279. FxFlags := FX_BLEND;
  280. end;
  281. procedure zglCSprite2D.OnDraw;
  282. begin
  283. asprite2d_Draw( Texture, X, Y, W, H, Angle, Round( Frame ), Alpha, FxFlags );
  284. end;
  285. procedure zglCSprite2D.OnProc;
  286. begin
  287. end;
  288. procedure zglCSprite2D.OnFree;
  289. begin
  290. end;
  291. end.