tile.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666
  1. #include "eruta.h"
  2. #include "mem.h"
  3. #include "dynar.h"
  4. #include "silut.h"
  5. #include "tile.h"
  6. #include "monolog.h"
  7. #ifndef TILE_MAXFRAME
  8. #define TILE_MAXFRAME 32
  9. #endif
  10. #ifndef TILE_MAXPROGRAM
  11. #define TILE_MAXPROGRAM 64
  12. #endif
  13. /**
  14. * A tile set
  15. */
  16. struct Tileset_ {
  17. Dynar * tiles;
  18. // Tile * tiles;
  19. Image * sheet;
  20. // size_t size;
  21. size_t last;
  22. int w;
  23. int h;
  24. /* Offset of tile set in TMX map file. Used to calculate correct tile offsets. */
  25. int firstgid;
  26. };
  27. typedef struct TileFrame_ TileFrame;
  28. /**
  29. * A Tiled-style animation fames of a tile.
  30. */
  31. struct TileFrame_ {
  32. /* Tile set index for this frame of animation. */
  33. int index;
  34. /* Time this animation frame is shown. */
  35. double duration;
  36. };
  37. /**
  38. * A single tile from a tile map.
  39. * Tiles can be animated. This works like this: a tile has an animation
  40. * pointer and offset which points to the next tile to be drawn in the tileset.
  41. *
  42. * A tile can only hold up to TILE_FRAMES tiles pointers in itself.
  43. */
  44. struct Tile_ {
  45. Tileset * set;
  46. int index;
  47. /* Tileset this tile belongs to + index in the tile set. */
  48. int flags;
  49. /* Information about the tile's properties. */
  50. int kind;
  51. /* Index of currently active animation pointer for this tile. */
  52. int anim;
  53. /* Offset to the tile to skip to when animating. If this is
  54. 0 the tile is not animated. If nonzero, the tile will skip to
  55. the tile in the same tile set set with index index + anim.
  56. May be negative to "roll back" an animation to it's begin. */
  57. int active;
  58. /* For unanimated tiles, active is set to the index of the tile itself.
  59. For animated tiles, it is set to the index of tile that currently should
  60. be displayed in stead of this tile due to animation.
  61. */
  62. double wait;
  63. /* Time in s to wait before jumping to the next frame of this tile. */
  64. double time;
  65. /* Time since last animation in s. */
  66. /* Sub-position in the tile sheet image of the tileset. */
  67. Point now;
  68. /* Automatic blending activation and priority. */
  69. int blend;
  70. /* Mask number to use for automatic blending, if any. */
  71. int blend_mask;
  72. /* Automatic lighting activation flag. */
  73. int light;
  74. /* Automatic lighting mask nuymber. */
  75. int light_mask;
  76. /* Automatic shadow activation flag. */
  77. int shadow;
  78. /* Automatic shadow mask number. */
  79. int shadow_mask;
  80. /* Tiled-style animation frames. */
  81. Dynar * frames;
  82. /* Active frame for TMX-style animations. */
  83. int active_frame;
  84. };
  85. /* NOTE: Tiles could be implemented using sub bitmaps as they seem to be
  86. * slightly faster if they are preallocated. however the speed gain would
  87. * be around 2%, so it's not a priority yet. It could simplify some of
  88. * the code, though.
  89. */
  90. /* Cleans up a tile. */
  91. void tile_done(Tile * tile) {
  92. if (!tile) return;
  93. if (tile->frames) {
  94. dynar_free(tile->frames);
  95. }
  96. tile->frames = NULL;
  97. }
  98. /* for dynar_destroy */
  99. void * tile_destroy(void * tile) {
  100. tile_done(tile);
  101. return NULL;
  102. }
  103. /** Cleans up a tileset, and empties it. */
  104. void tileset_done(Tileset * set) {
  105. Tile * tile;
  106. if(!set) return;
  107. if (set->tiles) {
  108. al_destroy_bitmap(set->sheet);
  109. set->sheet = NULL;
  110. dynar_destroy_structs_and_free(set->tiles, tile_destroy);
  111. set->tiles = NULL;
  112. set->w = -1;
  113. set->h = -1;
  114. }
  115. }
  116. /** Deallocates a tileset */
  117. void tileset_free(Tileset * set) {
  118. if(!set) return;
  119. tileset_done(set);
  120. mem_free(set);
  121. }
  122. /** Retuns the amount of tiles in the tile set. */
  123. int tileset_size(Tileset * set) {
  124. return dynar_size(set->tiles);
  125. }
  126. /* Returns the firstgid of the tile set, useful for TMX maps. */
  127. int tileset_firstgid(Tileset * set) {
  128. return set->firstgid;
  129. }
  130. /** Initializes a given tileset with a given bitmap tile sheet and firstgid */
  131. Tileset * tileset_init(Tileset * set, Image * sheet, int firstgid) {
  132. int size = 0, index = 0;
  133. if(!set) return NULL;
  134. set->sheet = sheet;
  135. set->firstgid = firstgid;
  136. if(!set->sheet) {
  137. set->w = -1;
  138. set->h = -1;
  139. set->tiles = NULL;
  140. return NULL;
  141. }
  142. // allow re-init
  143. if (set->tiles) {
  144. tileset_done(set);
  145. }
  146. set->w = image_w(set->sheet);
  147. set->h = image_h(set->sheet);
  148. size = (set->w / TILE_W) * (set->h / TILE_H);
  149. set->tiles = dynar_new(size, sizeof(Tile));
  150. set->last = 0;
  151. // set->tiles = mem_alloc(sizeof(Tile) * set->size);
  152. if (!set->tiles) {
  153. set->w = -1;
  154. set->h = -1;
  155. return NULL;
  156. }
  157. // now set up the tiles
  158. for(index = 0; index < dynar_size(set->tiles); index ++) {
  159. tile_init(tileset_get(set, index), set, index);
  160. }
  161. return set;
  162. }
  163. /** Creates a new tileset with the given tile sheet image. */
  164. Tileset * tileset_new(Image * sheet, int firstgid) {
  165. Tileset * set, * result;
  166. set = STRUCT_ALLOC(Tileset);
  167. if(!set) return NULL;
  168. result = tileset_init(set, sheet, firstgid);
  169. if(!result) {
  170. tileset_free(set);
  171. return NULL;
  172. }
  173. return result;
  174. }
  175. /*Macros that calculate the position of a tile in a tile set's sheet. */
  176. #define TILE_SHEET_Y(TILE, SET)\
  177. (((TILE->active * TILE_W) / ((SET)->w)) * TILE_H)
  178. #define TILE_SHEET_X(TILE, SET)\
  179. ((TILE->active * TILE_W) % ((SET)->w))
  180. /** Recalculates the tile's position (now) in it's tile set. */
  181. Tile * tile_recalculate(Tile * tile) {
  182. double x, y;
  183. // LOG_NOTE("Tile Recalculate: %p \n", tile);
  184. if (!tile) return NULL;
  185. // LOG_NOTE("Tile Recalculate: %p %d\n", tile->set, tile->active);
  186. if (!tile->set) return NULL;
  187. // LOG_NOTE("Tile Recalculate set: %d %d\n", tile->set->w, tile->set->h);
  188. x = (double)TILE_SHEET_X(tile, tile->set);
  189. y = (double)TILE_SHEET_Y(tile, tile->set);
  190. // LOG_NOTE("Tile Recalculate: %lf, %lf -> %lf, %lf\n", tile->now.x, tile->now.y, x, y);
  191. tile->now = bevec(x, y);
  192. return tile;
  193. }
  194. /** Initializes a tile to belong to a given tile set. */
  195. Tile * tile_init(Tile * tile, Tileset * set, int index) {
  196. if(!tile) return NULL;
  197. if(!set) return NULL;
  198. tile->flags = 0;
  199. tile->kind = 0;
  200. tile->index = index;
  201. tile->set = set;
  202. tile->anim = 0;
  203. tile->time = 0.0;
  204. tile->wait = 0.250;
  205. tile->active = index;
  206. tile->blend = 0;
  207. tile->blend_mask = 0;
  208. tile->light = 0;
  209. tile->light_mask = 0;
  210. tile->shadow = 0;
  211. tile->shadow_mask = 0;
  212. tile->frames = NULL;
  213. tile->active_frame= 0;
  214. tile_recalculate(tile);
  215. return tile;
  216. }
  217. /** Gets a tile from a tile set by it's tile id. **/
  218. Tile * tileset_get(Tileset * set, int index) {
  219. if(!set) return NULL;
  220. if (index < 0) return NULL;
  221. return dynar_getdata(set->tiles, index);
  222. }
  223. /** Sets the animation parameter of this tile */
  224. Tile * tile_anim_(Tile * tile, int anim) {
  225. if(!tile) return NULL;
  226. tile->anim = anim;
  227. return tile;
  228. }
  229. /** Gets the animation parameter of this tile, or 0 if NULL */
  230. int tile_anim(Tile * tile) {
  231. if(!tile) return 0;
  232. return tile->anim;
  233. }
  234. /** Sets the wait parameter of this tile in ms */
  235. Tile * tile_wait_(Tile * tile, int wait) {
  236. if(!tile) return NULL;
  237. tile->wait = (double)wait / 1000.0;
  238. return tile;
  239. }
  240. /** Gets the wait parameter of this tile in ms, or -1 if NULL */
  241. int tile_wait(Tile * tile) {
  242. if(!tile) return -1;
  243. return (int)(tile->wait * 1000.0);
  244. }
  245. /* Helper lookup table for the tile flag names */
  246. static Silut tile_flagnames[] = {
  247. { TILE_WALL , "wall" },
  248. { TILE_WATER , "water" },
  249. { TILE_LEDGE , "ledge" },
  250. { TILE_STAIR , "stair" },
  251. { TILE_PUSH , "push" },
  252. { TILE_NORTH , "north" },
  253. { TILE_SOUTH , "south" },
  254. { TILE_EAST , "east" },
  255. { TILE_WEST , "west" },
  256. { TILE_ICE , "ice" },
  257. SILUT_DONE
  258. };
  259. /** Gets the value of the flags of a tile. */
  260. int tile_flags(Tile * tile) {
  261. if(!tile) return 0;
  262. return tile->flags;
  263. }
  264. /** Sets the flags on a tile. */
  265. Tile * tile_flags_(Tile * tile, int flags) {
  266. if(!tile) return NULL;
  267. tile->flags = flags;
  268. return tile;
  269. }
  270. /** Sets a single flag on a tile. */
  271. Tile * tile_setflag(Tile * tile, int flag) {
  272. if(!tile) return NULL;
  273. tile->flags = BIT_SETFLAG(tile->flags, flag);
  274. return tile;
  275. }
  276. /** Removes a single flag on a tile. */
  277. Tile * tile_unflag(Tile * tile, int flag) {
  278. if(!tile) return NULL;
  279. tile->flags = BIT_UNFLAG(tile->flags, flag);
  280. return tile;
  281. }
  282. /** Checks a single flag on a tile. */
  283. int tile_isflag(Tile * tile, int flag) {
  284. if(!tile) return 0;
  285. return BIT_ISFLAG(tile->flags, flag);
  286. }
  287. /** Sets a tile's flags from a property string.
  288. * This uses an internal lookup table.
  289. */
  290. Tile * tile_property_(Tile * tile, char * property) {
  291. if(!tile) return NULL;
  292. Silut * aid = silut_lsearchcstr(tile_flagnames, property);
  293. if(!aid) return NULL;
  294. return tile_setflag(tile, aid->integer);
  295. }
  296. /** Initializes a tile's frame of animation. */
  297. TileFrame * tileframe_init(TileFrame * me, int index, double duration) {
  298. if (!me) return NULL;
  299. me->index = index;
  300. me->duration = duration;
  301. return me;
  302. }
  303. /** Gets the nth frame of Tiled style animations for this tile
  304. * or NULL if no such animation frame. */
  305. TileFrame * tile_frame(Tile * tile, int index) {
  306. if (!tile) return NULL;
  307. if (!tile->frames) return NULL;
  308. return dynar_getdata(tile->frames, index);
  309. }
  310. /** Gets the amount of Tiled style animations for this tile, or 0 if none. */
  311. int tile_frame_count(Tile * tile) {
  312. if (!tile) return 0;
  313. if (!tile->frames) return 0;
  314. return dynar_size(tile->frames);
  315. }
  316. /** Adds a Tiled-style animation frame to the tile. */
  317. Tile * tile_add_animation_frame(Tile * tile, int index, double duration) {
  318. if (tile->frames) {
  319. int size;
  320. size = dynar_size(tile->frames);
  321. if (!dynar_size_(tile->frames, size + 1)) return NULL;
  322. tileframe_init(dynar_getdata(tile->frames, size), index, duration);
  323. } else {
  324. tile->frames = dynar_new(1, sizeof(struct TileFrame_));
  325. if (!tile->frames) return NULL;
  326. tileframe_init(dynar_getdata(tile->frames, 0), index, duration);
  327. }
  328. return tile;
  329. }
  330. /** Rewinds a tile's animations. */
  331. void tile_rewindanime(Tile * tile) {
  332. if (!tile) return;
  333. tile->active = tile->index;
  334. tile->active_frame = 0;
  335. // Finally recalculate tile position.
  336. tile_recalculate(tile);
  337. }
  338. /** Updates a tile to animate it using classic style animation.*/
  339. void tile_update_classic(Tile * tile, double dt) {
  340. int active = 0;
  341. Tile * aidtile = NULL;
  342. Tile * nowtile = tileset_get(tile->set, tile->active);
  343. // nowtile is the tile that is currently active, that is shown.
  344. // in stead of ourself, but it also may be ourself.
  345. if(!nowtile) return;
  346. tile->time += dt; // advance animation time of tile.
  347. // Don't animate if not enough time has passed
  348. if(tile->time < tile->wait) return;
  349. // if we get here, reset animation time.
  350. tile->time = 0.0;
  351. // take the animation parameter and add it to the active
  352. active = tile->active + nowtile->anim;
  353. aidtile = tileset_get(tile->set, active);
  354. // Check if there is such a tile.
  355. if(!aidtile) return;
  356. // If there is no such tile, don't change the active tile of this tile.
  357. tile->active = active;
  358. // Finally recalculate tile position.
  359. tile_recalculate(tile);
  360. }
  361. /** Updates a tile to anmate it using TMX style animation. */
  362. void tile_update_tmx(Tile * tile, double dt) {
  363. int active = 0;
  364. TileFrame * frame = NULL;
  365. Tile * aidtile = NULL;
  366. frame = tile_frame(tile, tile->active_frame);
  367. if (!frame) { /* Animation overshoit itself somehow??? */
  368. tile->active_frame = 0;
  369. frame = tile_frame(tile, tile->active_frame);
  370. if (!frame) return;
  371. }
  372. tile->time += dt; // advance animation time of tile.
  373. // Don't animate if not enough time has passed
  374. if(tile->time < frame->duration) return;
  375. // advance the animation frame, loop it around if needed.
  376. tile->active_frame++;
  377. if (tile->active_frame >= tile_frame_count(tile)) {
  378. tile->active_frame = 0;
  379. }
  380. // Get new tile frame
  381. frame = tile_frame(tile, tile->active_frame);
  382. // If we get here, reset animation time.
  383. tile->time = 0.0;
  384. if (!frame) return;
  385. // Get the active tile t use from the animation frame
  386. active = frame->index;
  387. aidtile = tileset_get(tile->set, active);
  388. // Check if there is such a tile.
  389. if(!aidtile) return;
  390. // If there is no such tile, don't change the active tile of this tile.
  391. tile->active = active;
  392. // Finally recalculate tile position.
  393. tile_recalculate(tile);
  394. // tile->now = aidtile->now;
  395. // LOG_NOTE("TMX Anim: %d (%d: set(%d, %d)): (x,y)=(%lf, %lf)\n", tile->index, tile->active, tile->set->w, tile->set->h, tile->now.x, tile->now.y);
  396. }
  397. /* Animates the tile. If it has a TMX style animation, that takes
  398. * precedence, otherwise, use the classic style animation. */
  399. void tile_update(Tile * tile, double dt) {
  400. if (tile->frames) {
  401. tile_update_tmx(tile, dt);
  402. } else {
  403. tile_update_classic(tile, dt);
  404. }
  405. }
  406. /** Updates all tiles in a tile set so they all get animated. */
  407. void tileset_update(Tileset * set, double dt) {
  408. int index, size;
  409. if (!set) return;
  410. if (!set->tiles) return;
  411. size = tileset_size(set);
  412. for (index = 0; index < size; index++) {
  413. Tile * tile = tileset_get(set, index);
  414. tile_update(tile, dt);
  415. }
  416. }
  417. /** Draw a tile to the current active drawing target at the
  418. given coordinates. Does nothing if tile is NULL. */
  419. void tile_draw(Tile * tile, int x, int y, int drawflags) {
  420. Tileset * set;
  421. Image * sheet;
  422. Color dcolor = al_map_rgb(0xee, 0xee, 0x00);
  423. if (!tile) return;
  424. set = tile->set;
  425. sheet = set->sheet;
  426. float dx = (float) x;
  427. float dy = (float) y;
  428. float sx = (float) tile->now.x;
  429. float sy = (float) tile->now.y;
  430. float sw = (float) TILE_W;
  431. float sh = (float) TILE_H;
  432. al_draw_bitmap_region(sheet, sx, sy, sw, sh, dx, dy, drawflags);
  433. // debugging solid tiles
  434. #ifdef TILE_SHOW_SOLID
  435. if (tile_isflag(tile, TILE_WALL)) {
  436. al_draw_rectangle(dx, dy, dx+TILE_W, dy+TILE_H, dcolor, 2);
  437. }
  438. #endif // TILE_SHOW_SOLID
  439. // al_draw_bitmap(sheet, dx, dy, 0);
  440. }
  441. /* Used for drawing masked tiles. */
  442. static Image * tile_mask_buffer = NULL;
  443. /** Draw a tile into the given bitmap, which should be of size TILE_W, TILE_H
  444. * applying the given mask bitmap, where the mask will
  445. be flipped and rotated as per the given mask_flags. The mask bitmap
  446. should be white, but with different alpha levels on the white
  447. which will be applied as the mask. Does nothing if tile is NULL.
  448. This requires al_hold_bitmap_drawing to be turned off!
  449. */
  450. void tile_draw_masked_to
  451. (Image * result, Tile * tile, Image * mask, float angle, int mask_flags) {
  452. /* This function need a mask buffer. */
  453. Tileset * set;
  454. Image * sheet;
  455. ALLEGRO_BITMAP * target;
  456. Color dcolor = al_map_rgb(0xee, 0x00, 0xee);
  457. float dx, dy, sx, sy, sw, sh;
  458. int bmpflags;
  459. if (!tile) return;
  460. /* Create a 32x32 tile bitmap that will be reused thanks to
  461. it being static. And leaked at program shutdown, but I don't care :p. */
  462. if (!tile_mask_buffer) {
  463. bmpflags = al_get_new_bitmap_flags();
  464. al_set_new_bitmap_flags(ALLEGRO_CONVERT_BITMAP);
  465. tile_mask_buffer = al_create_bitmap(TILE_W, TILE_H);
  466. al_set_new_bitmap_flags(bmpflags);
  467. }
  468. /* Keep the target bitmap. */
  469. target = al_get_target_bitmap();
  470. /* Copy the tile into the buffer. */
  471. al_set_target_bitmap(tile_mask_buffer);
  472. set = tile->set;
  473. sheet = set->sheet;
  474. dx = 0.0;
  475. dy = 0.0;
  476. sx = (float) tile->now.x;
  477. sy = (float) tile->now.y;
  478. sw = (float) TILE_W;
  479. sh = (float) TILE_H;
  480. /* Set blender to copy mode. */
  481. // al_clear_to_color(al_map_rgba_f(0,0,0,0));
  482. al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
  483. al_draw_bitmap_region(sheet, sx, sy, sw, sh, 0, 0, 0);
  484. /* Draw the mask over the tile, taking the alpha of the mask */
  485. al_set_blender(ALLEGRO_ADD, ALLEGRO_ZERO, ALLEGRO_ALPHA);
  486. al_draw_bitmap(mask, 0, 0, mask_flags);
  487. /* Restore normal Allegro blending. */
  488. al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
  489. sx = 0.0;
  490. sy = 0.0;
  491. if (angle != 0.0) {
  492. sx = TILE_H / 2.0;
  493. sy = TILE_W / 2.0;
  494. dx += sx;
  495. dy += sy;
  496. }
  497. /* Draw the tile mask buffer to the result bitmap */
  498. al_set_target_bitmap(result);
  499. al_draw_rotated_bitmap(tile_mask_buffer, sx, sy, dx, dy, angle, 0);
  500. /* And restore the target bitmap. */
  501. al_set_target_bitmap(target);
  502. }
  503. /** Tile's index. Returns -1 if tile is NULL; */
  504. int tile_index(Tile * tile) {
  505. if (!tile) return -1;
  506. return tile->index;
  507. }
  508. /** Information about the tile's properties. Return -1 if tile is NULL. */
  509. int tile_kind(Tile * tile) {
  510. if (!tile) return -1;
  511. return tile->kind;
  512. }
  513. /** Information about tile's blending properties and priority.
  514. * Zero means no blending, positive is a blend priority.
  515. */
  516. int tile_blend(Tile * tile) {
  517. if (!tile) return 0;
  518. return tile->blend;
  519. }
  520. /** Set the tile's blending and priority */
  521. int tile_blend_(Tile * tile, int priority) {
  522. if (!tile) return 0;
  523. return tile->blend = priority;
  524. }
  525. /** Information about tile's blending mask
  526. * Returns 0 for the default mask if not set.
  527. */
  528. int tile_blend_mask(Tile * tile) {
  529. if (!tile) return 0;
  530. return tile->blend_mask;
  531. }
  532. /** Set the tile's blending mask */
  533. int tile_blend_mask_(Tile * tile, int mask) {
  534. if (!tile) return 0;
  535. if (mask < 0) mask = 0;
  536. if (mask > 2) mask = 0;
  537. return tile->blend_mask = mask;
  538. }
  539. /** Get the tile's light flag. Zero means no lighting. */
  540. int tile_light(Tile * tile) {
  541. if (!tile) return 0;
  542. return tile->light;
  543. }
  544. /** Set the tile's light flag */
  545. int tile_light_(Tile * tile, int value) {
  546. if (!tile) return 0;
  547. return tile->light = value;
  548. }
  549. /** Information about tile's lighting mask
  550. * Returns 0 for the default mask if not set.
  551. */
  552. int tile_light_mask(Tile * tile) {
  553. if (!tile) return 0;
  554. return tile->light_mask;
  555. }
  556. /** Set the tile's light mask */
  557. int tile_light_mask_(Tile * tile, int mask) {
  558. if (!tile) return 0;
  559. if (mask < 0) mask = 0;
  560. return tile->light_mask = mask;
  561. }
  562. /** Get the tile's shadow flag. Zero means no autoshadow. */
  563. int tile_shadow(Tile * tile) {
  564. if (!tile) return 0;
  565. return tile->shadow;
  566. }
  567. /** Set the tile's light flag */
  568. int tile_shadow_(Tile * tile, int value) {
  569. if (!tile) return 0;
  570. return tile->shadow = value;
  571. }
  572. /** Information about tile's shadow mask
  573. * Returns 0 for the default mask if not set.
  574. */
  575. int tile_shadow_mask(Tile * tile) {
  576. if (!tile) return 0;
  577. return tile->shadow_mask;
  578. }
  579. /** Set the tile's shadow mask */
  580. int tile_shadow_mask_(Tile * tile, int mask) {
  581. if (!tile) return 0;
  582. if (mask < 0) mask = 0;
  583. return tile->shadow_mask = mask;
  584. }