spritestate.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. #include "eruta.h"
  2. #include "mem.h"
  3. #include "sprite.h"
  4. #include "spritestate.h"
  5. #include "bad.h"
  6. #include "monolog.h"
  7. #include "callrb.h"
  8. /* Sprite state layer functions. */
  9. SpriteStateLayer * spritestatelayer_init_empty(SpriteStateLayer * me) {
  10. if (!me) return NULL;
  11. me->flags = 0;
  12. me->tint = al_map_rgba(1.0, 1.0, 1.0, 0.0);
  13. return me;
  14. }
  15. /* Sprite state action functions. */
  16. SpriteStateAction * spritestateaction_init_empty(SpriteStateAction * me) {
  17. if (!me) return NULL;
  18. me->done = FALSE;
  19. me->loop = SPRITESTATE_ACTION_LOOP;
  20. me->next_action = -1;
  21. return me;
  22. }
  23. /* Sprite state functions. */
  24. SpriteState * spritestate_alloc() {
  25. return STRUCT_ALLOC(SpriteState);
  26. }
  27. Sprite * spritestate_sprite_(SpriteState * self, Sprite * sprite) {
  28. int index;
  29. if(!self) return NULL;
  30. self->sprite = sprite;
  31. self->action_index = -1;
  32. self->action_now = NULL;
  33. self->frame_now = NULL;
  34. self->frame_index = -1;
  35. self->time = 0.0;
  36. self->pose_now = SPRITE_STAND;
  37. self->direction_now = SPRITE_ALL;
  38. /* No cleanup of sprite as it is not owned by the sprite state. */
  39. return self->sprite;
  40. }
  41. /* Clean up the sprite state.
  42. * No cleanup of the sprite itself since the Sprite * is owned by the sprite
  43. * list.
  44. */
  45. SpriteState * spritestate_done(SpriteState * self) {
  46. int index;
  47. return self;
  48. }
  49. SpriteState * spritestate_free(SpriteState * self) {
  50. spritestate_done(self);
  51. return mem_free(self);
  52. }
  53. Sprite * spritestate_sprite(SpriteState * self) {
  54. if(!self) return NULL;
  55. return self->sprite;
  56. }
  57. /** Thing is passed as a void data pointer to avoid dependencies. */
  58. SpriteState * spritestate_init(SpriteState * self, Sprite * sprite, void * data) {
  59. int index;
  60. if(!self) return NULL;
  61. spritestate_sprite_(self, sprite);
  62. self->speedup = 1.0;
  63. for (index = 0 ; index < SPRITESTATE_LAYER_MAX; index ++) {
  64. spritestatelayer_init_empty(self->layers + index);
  65. }
  66. for (index = 0 ; index < SPRITESTATE_ACTION_MAX; index ++) {
  67. spritestateaction_init_empty(self->actions + index);
  68. }
  69. self->data = data;
  70. return self;
  71. }
  72. void * spritestate_data(SpriteState * self) {
  73. if (!self) return NULL;
  74. return self->data;
  75. }
  76. double spritestate_speedup(SpriteState * self) {
  77. if (!self) return 0.0;
  78. return self->speedup;
  79. }
  80. double spritestate_speedup_(SpriteState * self, double speedup) {
  81. if (!self) return 0.0;
  82. return self->speedup = speedup;
  83. }
  84. SpriteState * spritestate_new(Sprite * sprite, void * data) {
  85. return spritestate_init(spritestate_alloc(), sprite, data);
  86. }
  87. /** Returns whether or not the sprite state can be drawn or not. */
  88. int spritestate_can_draw_p(SpriteState * self) {
  89. if (!self) return FALSE;
  90. if (!(self->frame_now)) return FALSE;
  91. return TRUE;
  92. }
  93. /* Draws the given layer of the sprite using the sprite state.
  94. */
  95. void spritestate_draw_frame(SpriteState * me, SpriteFrame * frame, Point * at)
  96. {
  97. int index, stop;
  98. SpriteCell * cell;
  99. Color * tint;
  100. if (!me) return;
  101. if (!frame) {
  102. /* Draw a red box to show the missing frame */
  103. al_draw_filled_rectangle(at->x, at->y, at->x+16, at->y+16, al_map_rgb(255, 64, 64));
  104. return;
  105. };
  106. al_hold_bitmap_drawing(true);
  107. stop = spriteframe_maxlayers(frame);
  108. for (index = 0; index < stop ; index++) {
  109. if ((BIT_ISFLAG(me->layers[index].flags, SPRITESTATE_LAYER_HIDDEN))) {
  110. continue; /* Skip invisible layers. */
  111. }
  112. cell = spriteframe_cell(frame, index);
  113. tint = spritestate_get_layer_tint(me, index);
  114. if (tint) {
  115. spritecell_draw_tinted(cell, at, (*tint));
  116. } else {
  117. spritecell_draw(cell, at);
  118. }
  119. }
  120. al_hold_bitmap_drawing(false);
  121. }
  122. /* Draw the SpriteState at the given location. This takes
  123. the current action, frame, layers and offsets into consideration. */
  124. void spritestate_draw(SpriteState * self, Point * at) {
  125. if (!self) return;
  126. if (!self->sprite) return;
  127. spritestate_draw_frame(self, self->frame_now, at);
  128. }
  129. /* Sets the spritestate's current action and current frame. Returns
  130. self if ok, NULL if out of bounds. */
  131. SpriteState *
  132. spritestate_now_(SpriteState * self, int actionnow, int framenow) {
  133. SpriteAction * action;
  134. SpriteFrame * frame;
  135. Sprite * sprite;
  136. if (!self) return NULL;
  137. sprite = self->sprite;
  138. if (!sprite) return NULL;
  139. if (bad_outofboundsi(actionnow, 0, sprite_maxactions(sprite))) return NULL;
  140. frame = sprite_frame(sprite, actionnow, framenow);
  141. if (!frame) { return NULL; }
  142. self->frame_index = framenow;
  143. self->action_index = actionnow;
  144. self->frame_now = frame;
  145. self->time = 0.0;
  146. return self;
  147. }
  148. /* Advances the frame of the sprite state if needed, depending on the
  149. * looping and stop mode.
  150. */
  151. void spritestate_next_frame(SpriteState * self) {
  152. int next = self->frame_index + 1;
  153. int action;
  154. int action_loop;
  155. /* Loop if needed. */
  156. if (next >= sprite_framesused(self->sprite, self->action_index)) {
  157. action_loop = spritestate_get_action_loop(self, self->action_index);
  158. /* It's a one-shot action. Do NOT cycle. */
  159. if (action_loop & SPRITESTATE_ACTION_ONESHOT) {
  160. /* If it's a stop action, leave it there, otherwise go back to standing pose. */
  161. if (action_loop & SPRITESTATE_ACTION_STOP) {
  162. /* First time at end of a one shot stop action... */
  163. if (!self->actions[self->action_index].done) {
  164. /* Notify scripting of end of this loop. */
  165. callrb_sprite_event(self, action_loop, NULL);
  166. /* Set action to done to prevent double emitting the event above. */
  167. self->actions[self->action_index].done = TRUE;
  168. }
  169. } else {
  170. /* Notify script side. */
  171. callrb_sprite_event(self, action_loop, NULL);
  172. /* Go to back to first frame of standing pose with current direction. */
  173. action = sprite_action_index_for
  174. (self->sprite, SPRITE_WALK, self->direction_now);
  175. spritestate_pose_(self, SPRITE_WALK);
  176. spritestate_now_(self, action, 0);
  177. /* Action to done. */
  178. self->actions[self->action_index].done = TRUE;
  179. }
  180. } else {
  181. /* Loop back to first frame.*/
  182. spritestate_now_(self, self->action_index, 0);
  183. /* Set action to not done. */
  184. self->actions[self->action_index].done = FALSE;
  185. }
  186. } else {
  187. /* Advance to next frame. */
  188. spritestate_now_(self, self->action_index, next);
  189. /* Set action to not done. */
  190. self->actions[self->action_index].done = FALSE;
  191. }
  192. }
  193. /* Updates the spritestate.
  194. * dt is the time passed since the last update in seconds (usuallu around 0.02). */
  195. void spritestate_update(SpriteState * self, double dt) {
  196. Sprite * sprite;
  197. if (!self) return;
  198. sprite = self->sprite;
  199. if (!sprite) return;
  200. if(!self->frame_now) {
  201. int x, y, w, h;
  202. LOG_LEVEL(__FILE__, "NULL current sprite frame!: %d\n", self->action_index);
  203. // try to restore back to first frame if out of whack somehow.
  204. spritestate_now_(self, self->action_index, 0);
  205. return;
  206. }
  207. self->time += (self->speedup * dt);
  208. if(self->time > spriteframe_duration(self->frame_now)) {
  209. spritestate_next_frame(self);
  210. }
  211. }
  212. /* Sets the spritestate's current pose and direction. Will reset the frame to 0.
  213. * Returns negative if the pose could not be found in this sprite;
  214. * Otherwise returns the index of the used sprite action.
  215. * Returns -2 without effect if the pose and direction are identical to the ones
  216. * currently set.
  217. */
  218. int spritestate_posedirection_(SpriteState * self, int pose, int direction) {
  219. int max, index;
  220. SpriteAction * action;
  221. Sprite * sprite;
  222. if (!self) return -1;
  223. sprite = self->sprite;
  224. if (!sprite) return -1;
  225. if ((self->pose_now == pose) && (self->direction_now == direction)) {
  226. /* Do nothing if the pose and ditr are not actually changed. */
  227. return -2;
  228. }
  229. self->pose_now = pose;
  230. self->direction_now = direction;
  231. max = sprite_maxactions(sprite);
  232. for (index = 0; index < max; index ++) {
  233. action = sprite_action(sprite, index);
  234. if (spriteaction_matches_pose(action, pose, direction)) {
  235. spritestate_now_(self, index, 0);
  236. return index;
  237. }
  238. }
  239. return -1;
  240. }
  241. /* Changes the direction but keeps the pose.
  242. * No effect if direction is the current active one.*/
  243. int spritestate_direction_(SpriteState * self, int direction) {
  244. if (!self) return -1;
  245. return spritestate_posedirection_(self, self->pose_now, direction);
  246. }
  247. /* Changes the pose but keeps the direction.
  248. * No effect if pose is the current active one.
  249. */
  250. int spritestate_pose_(SpriteState * self, int pose) {
  251. if (!self) return -1;
  252. return spritestate_posedirection_(self, pose, self->direction_now);
  253. }
  254. /* Returns true if the layer or self are out of bounds, false if not. */
  255. int spritestate_is_bad_layer(SpriteState * self, int layer) {
  256. if (!self) return TRUE;
  257. if (layer < 0) return TRUE;
  258. if (layer > SPRITESTATE_LAYER_MAX) return TRUE;
  259. return FALSE;
  260. }
  261. /* Returns the current active pose of the sprite state.*/
  262. int spritestate_pose(SpriteState * self) {
  263. if (!self) return SPRITE_STAND;
  264. return self->pose_now;
  265. }
  266. /* Returns the current active direction of the sprite state.*/
  267. int spritestate_direction(SpriteState * self) {
  268. if (!self) return SPRITE_NO_DIRECTION;
  269. return self->direction_now;
  270. }
  271. /* Sets the tint color for a layer of the sprite. */
  272. int spritestate_tint_layer(SpriteState * self, int layer, Color color) {
  273. if (spritestate_is_bad_layer(self, layer)) return -1;
  274. self->layers[layer].tint = color;
  275. self->layers[layer].flags = BIT_SETFLAG(self->layers[layer].flags, SPRITESTATE_LAYER_TINTED);
  276. return layer;
  277. }
  278. /** Unsets the tint color for a layer of the sprite. */
  279. int spritestate_remove_tint_layer(SpriteState * self, int layer) {
  280. if (!spritestate_is_layer_tinted(self, layer)) return -1;
  281. self->layers[layer].flags = BIT_UNFLAG(self->layers[layer].flags, SPRITESTATE_LAYER_TINTED);
  282. return layer;
  283. }
  284. /** Returns TRUE if the layer of the sprite is tinted, FALSE if not. */
  285. int spritestate_is_layer_tinted(SpriteState * self, int layer) {
  286. if (spritestate_is_bad_layer(self, layer)) return FALSE;
  287. if (!(BIT_ISFLAG(self->layers[layer].flags, SPRITESTATE_LAYER_TINTED)))
  288. return FALSE;
  289. return TRUE;
  290. }
  291. /** Returns apointer to the tint of the layer or NULL if not tinted or
  292. * if the layer is out of bounds. */
  293. Color * spritestate_get_layer_tint(SpriteState * self, int layer) {
  294. if (!spritestate_is_layer_tinted(self, layer)) return NULL;
  295. return &(self->layers[layer].tint);
  296. }
  297. /** Hides or unhides the given layer of the sprite. */
  298. int spritestate_set_layer_hidden(SpriteState * self, int layer, int hidden) {
  299. if (hidden) {
  300. self->layers[layer].flags = BIT_SETFLAG(self->layers[layer].flags, SPRITESTATE_LAYER_HIDDEN);
  301. } else {
  302. self->layers[layer].flags = BIT_UNFLAG(self->layers[layer].flags, SPRITESTATE_LAYER_HIDDEN);
  303. }
  304. return spritestate_get_layer_hidden(self, layer);
  305. }
  306. /** Returns true if the sprite's layer is hidden false if not. */
  307. int spritestate_get_layer_hidden(SpriteState * self, int layer) {
  308. if (spritestate_is_bad_layer(self, layer)) return TRUE;
  309. return ((BIT_ISFLAG(self->layers[layer].flags, SPRITESTATE_LAYER_HIDDEN)));
  310. }
  311. /* Returns true if the action or self are out of bounds, false if not. */
  312. int spritestate_is_bad_action(SpriteState * self, int action) {
  313. if (!self) return TRUE;
  314. if (action < 0) return TRUE;
  315. if (action > SPRITESTATE_ACTION_MAX) return TRUE;
  316. return FALSE;
  317. }
  318. /** Sets the loop mode for the given action of the sprite. */
  319. int spritestate_set_action_loop(SpriteState * self, int action, int loopmode) {
  320. if (spritestate_is_bad_action(self, action)) return -1;
  321. self->actions[action].loop = loopmode;
  322. return self->actions[action].loop;
  323. }
  324. /** Gets the loop mode for the given action of the sprite. */
  325. int spritestate_get_action_loop(SpriteState * self, int action) {
  326. if (spritestate_is_bad_action(self, action)) return -1;
  327. return self->actions[action].loop;
  328. }
  329. /** Returns true if the last set action is done, false if not. */
  330. int spritestate_is_action_done(SpriteState * self, int action) {
  331. if (spritestate_is_bad_action(self, action)) return -1;
  332. return self->actions[action].done;
  333. }
  334. /** Sets the loop mode for the given pose and direction of the sprite. */
  335. int spritestate_set_pose_direction_loop
  336. (SpriteState * self, int pose, int direction, int loopmode) {
  337. int action = sprite_action_index_for(self->sprite, pose, direction);
  338. return spritestate_set_action_loop(self, action, loopmode);
  339. }
  340. /** Sets the loop mode for the given pose and direction of the sprite. */
  341. int spritestate_get_pose_direction_loop
  342. (SpriteState * self, int pose, int direction) {
  343. int action = sprite_action_index_for(self->sprite, pose, direction);
  344. return spritestate_get_action_loop(self, action);
  345. }