Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 
 
 
 

326 rader
7.1 KiB

  1. /*
  2. * libcucul Unicode canvas library
  3. * Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org>
  4. * All Rights Reserved
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the Do What The Fuck You Want To
  8. * Public License, Version 2, as published by Sam Hocevar. See
  9. * http://sam.zoy.org/wtfpl/COPYING for more details.
  10. */
  11. /** \file sprite.c
  12. * \version \$Id$
  13. * \author Sam Hocevar <sam@zoy.org>
  14. * \brief Sprite loading and blitting
  15. *
  16. * This file contains a small framework for sprite loading and blitting.
  17. */
  18. #include "config.h"
  19. #if defined(HAVE_INTTYPES_H) || defined(_DOXYGEN_SKIP_ME)
  20. # include <inttypes.h>
  21. #else
  22. typedef unsigned char uint8_t;
  23. #endif
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include "cucul.h"
  28. #include "cucul_internals.h"
  29. #if !defined(_DOXYGEN_SKIP_ME)
  30. struct cucul_frame
  31. {
  32. int w, h;
  33. int dx, dy;
  34. char *chars;
  35. int *color;
  36. };
  37. struct cucul_sprite
  38. {
  39. int nf;
  40. struct cucul_frame *frames;
  41. };
  42. #endif
  43. /**
  44. * \brief Allocate a sprite loaded from a file.
  45. *
  46. * \param file The filename.
  47. * \return The sprite, or NULL if an error occured.
  48. */
  49. struct cucul_sprite *cucul_load_sprite(cucul_t *qq, char const *file)
  50. {
  51. char buf[BUFSIZ];
  52. struct cucul_sprite *sprite;
  53. FILE *fd;
  54. fd = fopen(file, "r");
  55. if(fd == NULL)
  56. return NULL;
  57. sprite = malloc(sizeof(struct cucul_sprite));
  58. if(sprite == NULL)
  59. goto sprite_alloc_failed;
  60. sprite->nf = 0;
  61. sprite->frames = NULL;
  62. while(!feof(fd))
  63. {
  64. int x, y;
  65. int w = 0, h = 0, dx = 0, dy = 0;
  66. struct cucul_frame *frame;
  67. /* Get width and height */
  68. if(!fgets(buf, BUFSIZ, fd))
  69. break;
  70. sscanf(buf, "%i %i %i %i", &w, &h, &dx, &dy);
  71. if(w <= 0 || h <= 0 || w > BUFSIZ / 2)
  72. break;
  73. if(sprite->nf)
  74. {
  75. void *tmp = realloc(sprite->frames,
  76. (sprite->nf + 1) * sizeof(struct cucul_frame));
  77. if(tmp == NULL)
  78. goto frame_failed;
  79. sprite->frames = tmp;
  80. sprite->nf++;
  81. }
  82. else
  83. {
  84. sprite->frames = malloc((sprite->nf + 1) * sizeof(struct cucul_frame));
  85. if(sprite->frames == NULL)
  86. goto sprite_failed;
  87. sprite->nf++;
  88. }
  89. frame = &sprite->frames[sprite->nf - 1];
  90. frame->w = w;
  91. frame->h = h;
  92. frame->dx = dx;
  93. frame->dy = dy;
  94. frame->chars = malloc(w * h * sizeof(char));
  95. if(frame->chars == NULL)
  96. {
  97. sprite->nf--;
  98. goto frame_failed;
  99. }
  100. frame->color = malloc(w * h * sizeof(int));
  101. if(frame->color == NULL)
  102. {
  103. free(frame->chars);
  104. sprite->nf--;
  105. goto frame_failed;
  106. }
  107. for(y = 0; y < h; y++)
  108. {
  109. if(!fgets(buf, BUFSIZ, fd))
  110. goto frame_failed;
  111. for(x = 0; x < w && buf[x] && buf[x] != '\r' && buf[x] != '\n'; x++)
  112. frame->chars[w * y + x] = buf[x];
  113. for(; x < w; x++)
  114. frame->chars[w * y + x] = ' ';
  115. }
  116. for(y = 0; y < h; y++)
  117. {
  118. if(!fgets(buf, BUFSIZ, fd))
  119. goto frame_failed;
  120. for(x = 0; x < w && buf[x] && buf[x] != '\r' && buf[x] != '\n'; x++)
  121. frame->color[w * y + x] = buf[x] - 'a';
  122. for(; x < w; x++)
  123. frame->color[w * y + x] = ' ' - 'a';
  124. }
  125. continue;
  126. }
  127. if(sprite->nf == 0)
  128. goto sprite_failed;
  129. fclose(fd);
  130. return sprite;
  131. frame_failed:
  132. while(sprite->nf)
  133. {
  134. free(sprite->frames[sprite->nf - 1].color);
  135. free(sprite->frames[sprite->nf - 1].chars);
  136. sprite->nf--;
  137. }
  138. sprite_failed:
  139. free(sprite);
  140. sprite_alloc_failed:
  141. fclose(fd);
  142. return NULL;
  143. }
  144. /**
  145. * \brief Return the number of frames in a sprite.
  146. *
  147. * \param sprite The sprite.
  148. * \return The number of frames.
  149. */
  150. int cucul_get_sprite_frames(cucul_t *qq, struct cucul_sprite const *sprite)
  151. {
  152. if(sprite == NULL)
  153. return 0;
  154. return sprite->nf;
  155. }
  156. /**
  157. * \brief Return the width of a sprite.
  158. *
  159. * \param sprite The sprite.
  160. * \param f The frame index.
  161. * \return The width of the given frame of the sprite.
  162. */
  163. int cucul_get_sprite_width(cucul_t *qq, struct cucul_sprite const *sprite, int f)
  164. {
  165. if(sprite == NULL)
  166. return 0;
  167. if(f < 0 || f >= sprite->nf)
  168. return 0;
  169. return sprite->frames[f].w;
  170. }
  171. /**
  172. * \brief Return the height of a sprite.
  173. *
  174. * \param sprite The sprite.
  175. * \param f The frame index.
  176. * \return The height of the given frame of the sprite.
  177. */
  178. int cucul_get_sprite_height(cucul_t *qq, struct cucul_sprite const *sprite, int f)
  179. {
  180. if(sprite == NULL)
  181. return 0;
  182. if(f < 0 || f >= sprite->nf)
  183. return 0;
  184. return sprite->frames[f].h;
  185. }
  186. /**
  187. * \brief Return the X coordinate of a sprite's handle.
  188. *
  189. * \param sprite The sprite.
  190. * \param f The frame index.
  191. * \return The X coordinate of the given frame's handle.
  192. */
  193. int cucul_get_sprite_dx(cucul_t *qq, struct cucul_sprite const *sprite, int f)
  194. {
  195. if(sprite == NULL)
  196. return 0;
  197. if(f < 0 || f >= sprite->nf)
  198. return 0;
  199. return sprite->frames[f].dx;
  200. }
  201. /**
  202. * \brief Return the Y coordinate of a sprite's handle.
  203. *
  204. * \param sprite The sprite.
  205. * \param f The frame index.
  206. * \return The Y coordinate of the given frame's handle.
  207. */
  208. int cucul_get_sprite_dy(cucul_t *qq, struct cucul_sprite const *sprite, int f)
  209. {
  210. if(sprite == NULL)
  211. return 0;
  212. if(f < 0 || f >= sprite->nf)
  213. return 0;
  214. return sprite->frames[f].dy;
  215. }
  216. /**
  217. * \brief Draw a sprite's specific frame at the given coordinates. If the
  218. * frame does not exist, nothing is displayed.
  219. *
  220. * \param x The X coordinate.
  221. * \param y The Y coordinate.
  222. * \param sprite The sprite.
  223. * \param f The frame index.
  224. * \return void
  225. */
  226. void cucul_draw_sprite(cucul_t *qq, int x, int y, struct cucul_sprite const *sprite, int f)
  227. {
  228. int i, j;
  229. enum cucul_color oldfg, oldbg;
  230. struct cucul_frame *frame;
  231. if(sprite == NULL)
  232. return;
  233. if(f < 0 || f >= sprite->nf)
  234. return;
  235. frame = &sprite->frames[f];
  236. oldfg = cucul_get_fg_color(qq);
  237. oldbg = cucul_get_bg_color(qq);
  238. for(j = 0; j < frame->h; j++)
  239. {
  240. for(i = 0; i < frame->w; i++)
  241. {
  242. int col = frame->color[frame->w * j + i];
  243. if(col >= 0)
  244. {
  245. cucul_set_color(qq, col, CUCUL_COLOR_BLACK);
  246. cucul_putchar(qq, x + i - frame->dx, y + j - frame->dy,
  247. frame->chars[frame->w * j + i]);
  248. }
  249. }
  250. }
  251. cucul_set_color(qq, oldfg, oldbg);
  252. }
  253. /**
  254. * \brief Free the memory associated with a sprite.
  255. *
  256. * \param sprite The sprite to be freed.
  257. * \return void
  258. */
  259. void cucul_free_sprite(cucul_t *qq, struct cucul_sprite *sprite)
  260. {
  261. int i;
  262. if(sprite == NULL)
  263. return;
  264. for(i = sprite->nf; i--;)
  265. {
  266. struct cucul_frame *frame = &sprite->frames[i];
  267. free(frame->chars);
  268. free(frame->color);
  269. }
  270. free(sprite->frames);
  271. free(sprite);
  272. }