zglSpriteEngine.pas 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  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. {$IFDEF USE_ZENGL_STATIC}
  32. zgl_main,
  33. zgl_fx,
  34. zgl_sprite_2d,
  35. zgl_textures
  36. {$ELSE}
  37. zglHeader
  38. {$ENDIF}
  39. ;
  40. type
  41. zglCSprite2D = class;
  42. zglCSEngine2D = class;
  43. zglCSEngine2D = class
  44. protected
  45. FCount : Integer;
  46. FList : array of zglCSprite2D;
  47. procedure SortByLayer( iLo, iHi : Integer );
  48. procedure SortByID( iLo, iHi : Integer );
  49. function GetSprite( ID : Integer ) : zglCSprite2D;
  50. procedure SetSprite( ID : Integer; Sprite : zglCSprite2D );
  51. public
  52. destructor Destroy; override;
  53. function AddSprite : Integer; overload; virtual;
  54. function AddSprite( Texture : zglPTexture; Layer : Integer ) : zglCSprite2D; overload; virtual;
  55. procedure AddSprite( Sprite : zglCSprite2D; Layer : Integer ); overload; virtual;
  56. procedure DelSprite( ID : Integer ); virtual;
  57. procedure ClearAll; virtual;
  58. procedure Draw; virtual;
  59. procedure Proc; virtual;
  60. property Count: Integer read FCount;
  61. property List[ID : Integer]: zglCSprite2D read GetSprite write SetSprite;
  62. end;
  63. zglCSprite2D = class
  64. protected
  65. public
  66. ID : Integer;
  67. Manager : zglCSEngine2D;
  68. Texture : zglPTexture;
  69. Kill : Boolean;
  70. Layer : Integer;
  71. X, Y : Single;
  72. W, H : Single;
  73. Angle : Single;
  74. Frame : Single;
  75. Alpha : Integer;
  76. FxFlags : LongWord;
  77. constructor Create( _Manager : zglCSEngine2D; _ID : Integer ); virtual;
  78. destructor Destroy; override;
  79. procedure OnInit( _Texture : zglPTexture; _Layer : Integer ); virtual;
  80. procedure OnDraw; virtual;
  81. procedure OnProc; virtual;
  82. procedure OnFree; virtual;
  83. end;
  84. implementation
  85. destructor zglCSEngine2D.Destroy;
  86. begin
  87. ClearAll();
  88. end;
  89. procedure zglCSEngine2D.SortByLayer( iLo, iHi : Integer );
  90. var
  91. lo, hi, mid : Integer;
  92. t : zglCSprite2D;
  93. begin
  94. lo := iLo;
  95. hi := iHi;
  96. mid := FList[ ( lo + hi ) shr 1 ].Layer;
  97. repeat
  98. while FList[ lo ].Layer < mid do INC( lo );
  99. while FList[ hi ].Layer > mid do DEC( hi );
  100. if lo <= hi then
  101. begin
  102. t := FList[ lo ];
  103. FList[ lo ] := FList[ hi ];
  104. FList[ hi ] := t;
  105. INC( lo );
  106. DEC( hi );
  107. end;
  108. until lo > hi;
  109. if hi > iLo Then SortByLayer( iLo, hi );
  110. if lo < iHi Then SortByLayer( lo, iHi );
  111. end;
  112. procedure zglCSEngine2D.SortByID( iLo, iHi : Integer );
  113. var
  114. lo, hi, mid : Integer;
  115. t : zglCSprite2D;
  116. begin
  117. lo := iLo;
  118. hi := iHi;
  119. mid := FList[ ( lo + hi ) shr 1 ].ID;
  120. repeat
  121. while FList[ lo ].ID < mid do INC( lo );
  122. while FList[ hi ].ID > mid do DEC( hi );
  123. if Lo <= Hi then
  124. begin
  125. t := FList[ lo ];
  126. FList[ lo ] := FList[ hi ];
  127. FList[ hi ] := t;
  128. INC( lo );
  129. DEC( hi );
  130. end;
  131. until lo > hi;
  132. if hi > iLo Then SortByID( iLo, hi );
  133. if lo < iHi Then SortByID( lo, iHi );
  134. end;
  135. function zglCSEngine2D.GetSprite( ID : Integer ) : zglCSprite2D;
  136. begin
  137. Result := FList[ ID ];
  138. end;
  139. procedure zglCSEngine2D.SetSprite( ID : Integer; Sprite : zglCSprite2D );
  140. begin
  141. FList[ ID ] := Sprite;
  142. end;
  143. function zglCSEngine2D.AddSprite : Integer;
  144. begin
  145. if FCount + 1 > Length( FList ) Then
  146. SetLength( FList, FCount + 16384 );
  147. Result := FCount;
  148. INC( FCount );
  149. end;
  150. function zglCSEngine2D.AddSprite( Texture : zglPTexture; Layer : Integer ) : zglCSprite2D;
  151. var
  152. id : Integer;
  153. begin
  154. id := AddSprite();
  155. FList[ id ] := zglCSprite2D.Create( Self, id );
  156. Result := FList[ id ];
  157. Result.OnInit( Texture, Layer );
  158. end;
  159. procedure zglCSEngine2D.AddSprite( Sprite : zglCSprite2D; Layer : Integer );
  160. var
  161. id : Integer;
  162. begin
  163. if not Assigned( Sprite ) Then exit;
  164. id := AddSprite();
  165. FList[ id ] := Sprite;
  166. FList[ id ].Manager := Self;
  167. FList[ id ].ID := id;
  168. FList[ id ].OnInit( Sprite.Texture, Layer );
  169. end;
  170. procedure zglCSEngine2D.DelSprite( ID : Integer );
  171. var
  172. i : Integer;
  173. begin
  174. if ( ID < 0 ) or ( ID > FCount - 1 ) or ( FCount = 0 ) Then exit;
  175. FList[ ID ].Free;
  176. for i := ID to FCount - 2 do
  177. begin
  178. FList[ i ] := FList[ i + 1 ];
  179. FList[ i ].ID := i;
  180. end;
  181. DEC( FCount );
  182. end;
  183. procedure zglCSEngine2D.ClearAll;
  184. var
  185. i : Integer;
  186. begin
  187. for i := 0 to FCount - 1 do
  188. FList[ i ].Destroy();
  189. SetLength( FList, 0 );
  190. FCount := 0;
  191. end;
  192. procedure zglCSEngine2D.Draw;
  193. var
  194. i : Integer;
  195. s : zglCSprite2D;
  196. begin
  197. i := 0;
  198. while i < FCount do
  199. begin
  200. s := FList[ i ];
  201. s.OnDraw();
  202. if s.Kill Then
  203. DelSprite( s.ID )
  204. else
  205. INC( i );
  206. end;
  207. end;
  208. procedure zglCSEngine2D.Proc;
  209. var
  210. i, a, b, l : Integer;
  211. s : zglCSprite2D;
  212. begin
  213. i := 0;
  214. while i < FCount do
  215. begin
  216. s := FList[ i ];
  217. s.OnProc();
  218. if s.Kill Then
  219. DelSprite( s.ID )
  220. else
  221. INC( i );
  222. end;
  223. if FCount > 1 Then
  224. begin
  225. l := 0;
  226. for i := 0 to FCount - 1 do
  227. begin
  228. s := FList[ i ];
  229. if s.Layer > l Then l := s.Layer;
  230. if s.Layer < l Then
  231. begin
  232. SortByLayer( 0, FCount - 1 );
  233. // TODO: provide parameter for enabling/disabling stable sorting
  234. l := FList[ 0 ].Layer;
  235. a := 0;
  236. for b := 0 to FCount - 1 do
  237. begin
  238. s := FList[ b ];
  239. if ( l <> s.Layer ) Then
  240. begin
  241. SortByID( a, b - 1 );
  242. a := b;
  243. l := s.Layer;
  244. end;
  245. if b = FCount - 1 Then
  246. SortByID( a, b );
  247. end;
  248. for a := 0 to FCount - 1 do
  249. FList[ a ].ID := a;
  250. break;
  251. end;
  252. end;
  253. end;
  254. end;
  255. constructor zglCSprite2D.Create( _Manager : zglCSEngine2D; _ID : Integer );
  256. begin
  257. Manager := _Manager;
  258. ID := _ID;
  259. OnInit( nil, 0 );
  260. end;
  261. destructor zglCSprite2D.Destroy;
  262. begin
  263. OnFree();
  264. end;
  265. procedure zglCSprite2D.OnInit( _Texture : zglPTexture; _Layer : Integer );
  266. begin
  267. Texture := _Texture;
  268. Layer := _Layer;
  269. X := 0;
  270. Y := 0;
  271. if Assigned( Texture ) Then
  272. begin
  273. W := Round( ( Texture.FramesCoord[ 1, 1 ].X - Texture.FramesCoord[ 1, 0 ].X ) * Texture.Width );
  274. H := Round( ( Texture.FramesCoord[ 1, 0 ].Y - Texture.FramesCoord[ 1, 2 ].Y ) * Texture.Height );
  275. end else
  276. begin
  277. W := 0;
  278. H := 0;
  279. end;
  280. Angle := 0;
  281. Frame := 1;
  282. Alpha := 255;
  283. FxFlags := FX_BLEND;
  284. end;
  285. procedure zglCSprite2D.OnDraw;
  286. begin
  287. asprite2d_Draw( Texture, X, Y, W, H, Angle, Round( Frame ), Alpha, FxFlags );
  288. end;
  289. procedure zglCSprite2D.OnProc;
  290. begin
  291. end;
  292. procedure zglCSprite2D.OnFree;
  293. begin
  294. end;
  295. end.