PageRenderTime 45ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/raidem-0.3.1-src/src/seborrhea/container-animation.m

#
Objective C | 362 lines | 268 code | 63 blank | 31 comment | 35 complexity | 990042294561cf85e1f9291eb6dc3457 MD5 | raw file
  1. /* container-animation.m,
  2. *
  3. * Animations are files that contain multiple images, which make up an
  4. * animation. All of the frames must have the same dimensions.
  5. */
  6. #include <stdio.h>
  7. #include <assert.h>
  8. #include "seborrhea/container-animation.h"
  9. #include "seborrhea/seborrhea-common.h"
  10. #ifndef ABS
  11. # define ABS(x) (((x) < 0) ? (-x) : (x))
  12. #endif
  13. @implementation SebAnimation
  14. - setFrameDelay:(unsigned int)t LoopMethod:(enum SEB_ANIMATION_LOOP_METHOD)method
  15. {
  16. delay = t;
  17. loop_method = method;
  18. return self;
  19. }
  20. - (unsigned int) frameDelay { return delay; }
  21. - (enum SEB_ANIMATION_LOOP_METHOD) loopMethod { return loop_method; }
  22. - (BOOL) addToList:(Sebum<SebImage> *)frame
  23. {
  24. assert(frame);
  25. if (not [frame conformsToProtocol:@protocol(SebImage)]) {
  26. fprintf(stderr, "[%s:%s] Attempted to add non-image %s (%s)!\n",
  27. [[[self class] className] cString], [self name],
  28. [frame name], [[[frame class] className] cString]);
  29. return NO;
  30. }
  31. if (nelements == 0) {
  32. w = [frame width];
  33. h = [frame height];
  34. }
  35. else if ([frame width] != w || [frame height] != h) {
  36. fprintf(stderr, "[%s:%s] Attempted to add %s, but has differing dimensions!\n",
  37. [[[self class] className] cString], [self name], [frame name]);
  38. return NO;
  39. }
  40. return [super addToList:frame];
  41. }
  42. - (unsigned int) numFrames { return nelements; }
  43. - (Sebum<SebImage> *) getFrame:(int)nth
  44. {
  45. /* Use negative numbers to denote from back of list. */
  46. if (nelements == 0)
  47. return nil;
  48. if (nth < 0)
  49. nth += nelements;
  50. assert((nth >= 0) && ((unsigned)nth < nelements));
  51. return element[nth];
  52. }
  53. - (unsigned int) nextFrame:(unsigned int)curr
  54. {
  55. if (curr+1 >= nelements) /* Loop. */
  56. return 0;
  57. else
  58. return curr+1;
  59. }
  60. - (void) setPivotX:(int)x Y:(int)y
  61. {
  62. unsigned int i;
  63. for (i = 0; i < nelements; i++)
  64. [(<SebImage>)element[i] setPivotX:x Y:y];
  65. }
  66. /* Dimensions. */
  67. - (unsigned int) width { return w; }
  68. - (unsigned int) height { return h; }
  69. /* Draw, with transparency. */
  70. - (void) drawTo:(void *)dest X:(int)x Y:(int)y
  71. {
  72. assert(nelements > 0);
  73. [(<SebImage>)element[0] drawTo:dest X:x Y:y];
  74. }
  75. - (void) drawTo:(void *)dest X:(int)x Y:(int)y Angle:(double)theta
  76. {
  77. assert(nelements > 0);
  78. [(<SebImage>)element[0] drawTo:dest X:x Y:y Angle:theta];
  79. }
  80. - (void) drawTo:(void *)dest X:(int)x Y:(int)y Angle:(double)theta Scale:(double)scale
  81. {
  82. assert(nelements > 0);
  83. [(<SebImage>)element[0] drawTo:dest X:x Y:y Angle:theta Scale:scale];
  84. }
  85. /* Draw, with transparency and translucency. */
  86. - (void) drawTo:(void *)dest X:(int)x Y:(int)y Alpha:(int)alpha
  87. {
  88. assert(nelements > 0);
  89. [(<SebImage>)element[0] drawTo:dest X:x Y:y Alpha:alpha];
  90. }
  91. - (void) drawTo:(void *)dest X:(int)x Y:(int)y Alpha:(int)alpha Angle:(double)theta
  92. {
  93. assert(nelements > 0);
  94. [(<SebImage>)element[0] drawTo:dest X:x Y:y Alpha:alpha Angle:theta];
  95. }
  96. /* Draw, with transparency and tinting. */
  97. - (void) drawTo:(void *)dest X:(int)x Y:(int)y Tint:(int)r :(int)g :(int)b :(int)alpha
  98. {
  99. assert(nelements > 0);
  100. [(<SebImage>)element[0] drawTo:dest X:x Y:y Tint:r:g:b:alpha];
  101. }
  102. - (void) drawTo:(void *)dest X:(int)x Y:(int)y Tint:(int)r :(int)g :(int)b :(int)alpha Angle:(double)theta
  103. {
  104. assert(nelements > 0);
  105. [(<SebImage>)element[0] drawTo:dest X:x Y:y Tint:r:g:b:alpha Angle:theta];
  106. }
  107. /* Draw, without transparency. */
  108. - (void) drawTo:(void *)dest X:(int)x Y:(int)y W:(int)w_ H:(int)h_
  109. {
  110. assert(nelements > 0);
  111. [(<SebImage>)element[0] drawTo:dest X:x Y:y W:w_ H:h_];
  112. }
  113. - (void) drawFromX:(int)sx Y:(int)sy To:(void *)dest X:(int)x Y:(int)y W:(int)w_ H:(int)h_
  114. {
  115. assert(nelements > 0);
  116. [(<SebImage>)element[0] drawFromX:sx Y:sy To:dest X:x Y:y W:w_ H:h_];
  117. }
  118. @end
  119. /*--------------------------------------------------------------*/
  120. /* SebAnimatorManualPoll. */
  121. /*--------------------------------------------------------------*/
  122. @implementation SebAnimatorManual
  123. - (const char *) name { return [anim name]; }
  124. - (SebAnimation *)getAnimation { return anim; }
  125. - resetAnimation
  126. {
  127. frame = 0;
  128. return self;
  129. }
  130. - setAnimation:(SebAnimation *)anime
  131. {
  132. anim = anime;
  133. frame = 0;
  134. loop_method = [anim loopMethod];
  135. return self;
  136. }
  137. - setFrame:(int)frame_
  138. {
  139. frame = frame_;
  140. return self;
  141. }
  142. - setLoopMethod:(enum SEB_ANIMATION_LOOP_METHOD)method
  143. {
  144. loop_method = method;
  145. return self;
  146. }
  147. - (int) currentFrameNumber { return frame; }
  148. - (Sebum<SebImage> *) currentFrame
  149. {
  150. assert(anim && "[SebAnimator] no animation set!\n");
  151. /* ABS corrects the frame for when ping-pong-ing. */
  152. return [anim getFrame:ABS(frame)];
  153. }
  154. - (BOOL) nextFrame
  155. {
  156. if (loop_method == LOOP_NONE) {
  157. int next_frame = [anim nextFrame:frame];
  158. if (next_frame == 0)
  159. return NO;
  160. frame = next_frame;
  161. }
  162. else if (loop_method == LOOP_FORWARD) {
  163. frame = [anim nextFrame:frame];
  164. }
  165. else if (loop_method == LOOP_PING_PONG) {
  166. int num_frames = [anim numFrames];
  167. if (frame+1 >= num_frames)
  168. frame = -num_frames+1;
  169. else
  170. frame++;
  171. }
  172. return YES;
  173. }
  174. - (void) updateFrame
  175. {
  176. /* This is called after each draw routine. It is mainly for use
  177. by SebAnimator. */
  178. }
  179. - (BOOL) animationEnded
  180. {
  181. if (loop_method == LOOP_NONE &&
  182. frame+1 == (int)[anim numFrames])
  183. return YES;
  184. else
  185. return NO;
  186. }
  187. - (void) setPivotX:(int)x Y:(int)y
  188. {
  189. assert(anim);
  190. [anim setPivotX:x Y:y];
  191. }
  192. /* Dimensions. */
  193. - (unsigned int) width { return [anim width]; }
  194. - (unsigned int) height { return [anim height]; }
  195. /* Draw, with transparency. */
  196. - (void) drawTo:(void *)dest X:(int)x Y:(int)y
  197. {
  198. [[self currentFrame] drawTo:dest X:x Y:y];
  199. [self updateFrame];
  200. }
  201. - (void) drawTo:(void *)dest X:(int)x Y:(int)y Angle:(double)theta
  202. {
  203. [[self currentFrame] drawTo:dest X:x Y:y Angle:theta];
  204. [self updateFrame];
  205. }
  206. - (void) drawTo:(void *)dest X:(int)x Y:(int)y Angle:(double)theta Scale:(double)scale
  207. {
  208. [[self currentFrame] drawTo:dest X:x Y:y Angle:theta Scale:scale];
  209. [self updateFrame];
  210. }
  211. /* Draw, with transparency and translucency. */
  212. - (void) drawTo:(void *)dest X:(int)x Y:(int)y Alpha:(int)alpha
  213. {
  214. [[self currentFrame] drawTo:dest X:x Y:y Alpha:alpha];
  215. [self updateFrame];
  216. }
  217. - (void) drawTo:(void *)dest X:(int)x Y:(int)y Alpha:(int)alpha Angle:(double)theta
  218. {
  219. [[self currentFrame] drawTo:dest X:x Y:y Alpha:alpha Angle:theta];
  220. [self updateFrame];
  221. }
  222. /* Draw, with transparency and tinting. */
  223. - (void) drawTo:(void *)dest X:(int)x Y:(int)y Tint:(int)r :(int)g :(int)b :(int)alpha;
  224. {
  225. [[self currentFrame] drawTo:dest X:x Y:y Tint:r:g:b:alpha];
  226. [self updateFrame];
  227. }
  228. - (void) drawTo:(void *)dest X:(int)x Y:(int)y Tint:(int)r :(int)g :(int)b :(int)alpha Angle:(double)theta
  229. {
  230. [[self currentFrame] drawTo:dest X:x Y:y Tint:r:g:b:alpha Angle:theta];
  231. [self updateFrame];
  232. }
  233. /* Draw, without transparency. */
  234. - (void) drawTo:(void *)dest X:(int)x Y:(int)y W:(int)w H:(int)h
  235. {
  236. [[self currentFrame] drawTo:dest X:x Y:y W:w H:h];
  237. [self updateFrame];
  238. }
  239. - (void) drawFromX:(int)sx Y:(int)sy To:(void *)dest X:(int)x Y:(int)y W:(int)w H:(int)h
  240. {
  241. [[self currentFrame] drawFromX:sx Y:sy To:dest X:x Y:y W:w H:h];
  242. [self updateFrame];
  243. }
  244. @end
  245. /*--------------------------------------------------------------*/
  246. /* SebAnimatorManualWithDelay is like SebAnimatorManual, but it
  247. * respects the frame delay set by the animation. */
  248. @implementation SebAnimatorManualWithDelay
  249. - resetAnimation
  250. {
  251. [super resetAnimation];
  252. frame_tics = [anim frameDelay];
  253. return self;
  254. }
  255. - setAnimation:(SebAnimation *)anime
  256. {
  257. [super setAnimation:anime];
  258. frame_tics = [anim frameDelay];
  259. return self;
  260. }
  261. - setFrame:(int)frame_
  262. {
  263. [super setFrame:frame_];
  264. frame_tics = [anim frameDelay];
  265. return self;
  266. }
  267. - (BOOL) nextFrame
  268. {
  269. frame_tics--;
  270. if (frame_tics <= 0) {
  271. if ([super nextFrame]) {
  272. frame_tics = [anim frameDelay];
  273. return YES;
  274. }
  275. }
  276. return NO;
  277. }
  278. - (BOOL) animationEnded
  279. {
  280. if (loop_method == LOOP_NONE &&
  281. frame+1 == (int)[anim numFrames] &&
  282. frame_tics == 0)
  283. return YES;
  284. else
  285. return NO;
  286. }
  287. @end
  288. /*--------------------------------------------------------------*/
  289. /* SebAnimator is like a SebAnimatorManualWithDelay, but there is not
  290. * need to manually update the frame. Each time the sprite is drawn,
  291. * frame tics is decreased. When frame tics reaches zero, it will
  292. * move on to the next frame. Looping method is determined by the
  293. * animation. */
  294. @implementation SebAnimator
  295. - (void) updateFrame
  296. {
  297. [self nextFrame];
  298. }
  299. @end