1 /*------------------------------------------------------------------. 2 | Copyright 2001, 2002 Alexandre Duret-Lutz <duret_g@epita.fr> | 3 | | 4 | This file is part of Heroes. | 5 | | 6 | Heroes is free software; you can redistribute it and/or modify it | 7 | under the terms of the GNU General Public License version 2 as | 8 | published by the Free Software Foundation. | 9 | | 10 | Heroes is distributed in the hope that it will be useful, but | 11 | WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 13 | General Public License for more details. | 14 | | 15 | You should have received a copy of the GNU General Public License | 16 | along with this program; if not, write to the Free Software | 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | 18 | 02111-1307 USA | 19 `------------------------------------------------------------------*/ 20 21 #ifndef HEROES__LVL__H 22 #define HEROES__LVL__H 23 24 /* Tiles are units of 24x20 pixels, squares are units of 12x10 pixels. 25 There is 4 squares per tiles. 26 27 Functions can use squares or tiles, depending on the resolution 28 with which entities are stored. For instance the bonuses are 29 stored in a tile-sized array, while the vehicules are stored in an 30 squares-sized array. 31 32 Those types are defined for better readability. The a_*_coord 33 types are used to designate a coordinate (either X, or Y), while 34 the a_*_index are used for square numbers (indices in one 35 dimensional arrays: index = y_coord * width + x_coord). */ 36 typedef unsigned int a_square_coord; 37 typedef unsigned int a_square_index; 38 typedef unsigned int a_tile_coord; 39 typedef unsigned int a_tile_index; 40 #define INVALID_INDEX (~0u) 41 42 typedef struct a_square_corrd_pair a_square_corrd_pair; 43 struct a_square_corrd_pair { 44 a_square_coord y, x; 45 }; 46 47 typedef struct a_tile_coord_pair a_tile_coord_pair; 48 struct a_tile_coord_pair { 49 a_tile_coord y, x; 50 }; 51 52 /* Direction constants. */ 53 typedef enum a_dir a_dir; 54 enum a_dir { D_UP = 0, 55 D_RIGHT = 1, 56 D_DOWN = 2, 57 D_LEFT = 3 }; 58 typedef a_u8 a_dir8; /* Hold the same values, on 8bits. */ 59 #define REVERSE_DIR(d) ((d) ^ 2) 60 61 /* Two direction on one byte (used for trails). 62 Don't change the encoding, this the resulting value is used 63 to lookup sprites to draw the trail. */ 64 typedef a_u8 a_dir8_pair; 65 #define DIR8_TAIL(X) ((X) >> 2) 66 #define DIR8_HEAD(X) ((X) & 0x3) 67 #define DIR8_PAIR(H, T) (((T) << 2) | (H)) 68 69 70 /* Number of directions, 71 unless Heroes goes 3D this is unlikely to change :) */ 72 #define DIR_MAX 4 73 74 /* Similar constants, but OR-able, to indicate multiple directions. */ 75 typedef enum a_dir_mask a_dir_mask; 76 enum a_dir_mask { DM_UP = 1, 77 DM_RIGHT = 2, 78 DM_DOWN = 4, 79 DM_LEFT = 8 }; 80 typedef a_u8 a_dir_mask8; /* Hold the same values, on 8bits. */ 81 #define DM_ALL (DM_UP | DM_RIGHT | DM_DOWN | DM_LEFT) 82 #define DIR_TO_DIRMASK(dir) (1 << (dir)) 83 84 /* Tile type constants. */ 85 typedef enum a_tile_type a_tile_type; 86 enum a_tile_type { T_NONE = 0, 87 T_STOP = 1, 88 T_SPEED = 2, 89 T_TUNNEL = 3, 90 T_BOOM = 4, 91 T_ANIM = 5, 92 T_ICE = 6, 93 T_DUST = 7, 94 T_OUTWAY = 8, 95 T_MAXTYPE /* Keep this upper bound last in the enum. */}; 96 typedef a_u8 a_tile_type8; /* Hold the same values, on 8bits. */ 97 98 99 typedef struct a_level a_level; /* An Heroes level. */ 100 typedef struct a_level_bits a_level_bits; /* Hiden details about levels. */ 101 102 103 /* The pointers in the a_level structure should point to constant 104 data. But from the level loading code the data need to be mutable. 105 So we allow const to be removed by defining LVL_MUTABLE. */ 106 107 #ifndef LVL_MUTABLE 108 # define LVL_MUTABLE const 109 #endif 110 111 struct a_level { 112 /*-------------. 113 | Dimensions. | 114 `-------------*/ 115 116 /* We store the dimensions in those two units, so that they are 117 directly available. */ 118 a_tile_coord tile_height; 119 a_tile_coord tile_width; 120 a_square_coord square_height; 121 a_square_coord square_width; 122 123 /* Some levels are wrapped: when the vehicle reach the right edge of 124 the level, they continue as if they were entering the level from 125 the left edge, and vice-versa. Of course this can also be set 126 for the top and bottom. 127 128 The _wrap members should be ANDed with a coordinate to wrap it. 129 For instance a wrapped level with a width of 32 will have 130 `tile_width_wrap' set to 31. That way an y coordinate of 35 will 131 be mapped to 3 (== 35 & 31). Non-wrapped level set this value to 132 `~0u' (== DONT_WRAP) so that ANDing is no-op. */ 133 a_tile_coord tile_height_wrap; 134 a_tile_coord tile_width_wrap; 135 a_square_coord square_height_wrap; 136 a_square_coord square_width_wrap; 137 138 /* Most maps are allocated as one-dimensional arrays. So we define 139 to more constants used for the size of the arrays. */ 140 a_tile_index tile_count; /* == tile_width * tile_height */ 141 a_square_index square_count; /* == square_width * square_height */ 142 143 /*----------------------------------------------------------------. 144 | The following arrays are initialized only if the level body has | 145 | been loaded. See the load_body argument of lvl_load_file. | 146 `----------------------------------------------------------------*/ 147 148 /* Type of each square. */ 149 LVL_MUTABLE a_tile_type8 *square_type; 150 /* Set of blocked directions for each square. If the entry is set 151 to DM_UP|DM_LEFT, it means a vehicle cannot *leave* the square 152 by the top or left edges. */ 153 LVL_MUTABLE a_dir_mask8 *square_walls_out; 154 /* Directions for squares for which it matters (i.e., T_SPEED, and 155 T_TUNNEL). */ 156 LVL_MUTABLE a_dir8 *square_direction; 157 /* square_move[D_UP][SQR] is the square that a vehicle shoud go into 158 when it leave SQR by the top edge. */ 159 LVL_MUTABLE a_square_index *square_move[DIR_MAX]; 160 161 /*-------------------------------------------------------------. 162 | Opaque structure to hide the remaining data. Use one of the | 163 | following functions to access anything relevant in there. | 164 `-------------------------------------------------------------*/ 165 166 LVL_MUTABLE a_level_bits *private; 167 }; 168 169 #ifndef DONT_WRAP 170 # define DONT_WRAP (~0u) /* Used for non wrapping directions. */ 171 #endif 172 173 /* Load a level from FILENAME to OUT. Return 0 on success, !0 174 otherwise. If LOAD_BODY is true, parse the body, and compute the 175 various constant square_* maps declared in a_level. If LOAD_BODY 176 is false, only the header of the level will be loaded. */ 177 int lvl_load_file (const char *filename, a_level *out, bool load_body); 178 int lvl_save_file (const char *filename, const a_level *out); 179 /* Free any data associated to LVL. */ 180 void lvl_free (a_level *lvl); 181 182 /* These two functions return a pointer to a string allocated for LVL, 183 and freed by lvl_free(). You should not free them yourself, and 184 you should not use these results after a call to lvl_free(). */ 185 const char *lvl_sound_track (const a_level *lvl); 186 const char *lvl_tile_sprite_map_basename (const a_level *lvl); 187 188 /* Initialize COORD, and DIR, with the starting position for PLAYER. */ 189 void lvl_start_position (const a_level *lvl, unsigned int player, 190 a_square_corrd_pair *coord, a_dir *dir); 191 192 /*--------------------------------------------------------------------. 193 | NOTE: The following function will fail if the body of the level | 194 | has not been loaded (see the load_body argument of lvl_load_file). | 195 `--------------------------------------------------------------------*/ 196 197 /* Return the type of tile TILE on level LVL. */ 198 a_tile_type lvl_tile_type (const a_level *lvl, a_tile_index tile); 199 200 /* Return the output direction of a tunnel on tile TILE. This function 201 should only be called on tiles of type T_TUNNEL. */ 202 a_dir lvl_tunnel_output_dir (const a_level *lvl, a_tile_index tile); 203 204 /* Return the offset (to the first pixel) of the sprite used to draw TILE. */ 205 unsigned int lvl_tile_sprite_offset (const a_level *lvl, 206 a_tile_index tile); 207 /* Return the offset (to the first pixel) of the overlay sprite to 208 draw on TILE. */ 209 unsigned int lvl_tile_sprite_overlay_offset (const a_level *lvl, 210 a_tile_index tile); 211 212 /* Kind of animation. */ 213 typedef enum an_anim_kind an_anim_kind; 214 enum an_anim_kind { A_NONE, A_LOOP, A_PINGPONG }; 215 216 /* Return information about a possible animation on tile TILE. 217 FRAME_COUNT is the number of frames to display, and DELAY a number 218 of 1/70sec to wait between each frame. Actually, FRAME_COUNT is 219 the number of sprites to display: FRAME_COUNT sprites starting at 220 the sprite index for the current tile should be displayed. 221 222 There is no animation if FRAME_COUNT is set to 0. */ 223 void lvl_animation_info (const a_level *lvl, a_tile_index tile, 224 unsigned int *frame_count, unsigned int *delay, 225 an_anim_kind *kind); 226 227 /*----------------. 228 | Useful macros. | 229 `----------------*/ 230 231 /* Moving to neighbor squares. */ 232 #define SQR_COORD_LEFT(lvl_ptr, sqr_x_coord) \ 233 (((sqr_x_coord) - 1) & (lvl_ptr)->square_width_wrap) 234 #define SQR_COORD_RIGHT(lvl_ptr, sqr_x_coord) \ 235 (((sqr_x_coord) + 1) & (lvl_ptr)->square_width_wrap) 236 #define SQR_COORD_UP(lvl_ptr, sqr_y_coord) \ 237 (((sqr_y_coord) - 1) & (lvl_ptr)->square_height_wrap) 238 #define SQR_COORD_DOWN(lvl_ptr, sqr_y_coord) \ 239 (((sqr_y_coord) + 1) & (lvl_ptr)->square_height_wrap) 240 241 /* Checking square coordinates. */ 242 #define SQR_COORD_X_VALID(lvl_ptr, sqr_coord_x) \ 243 (((sqr_coord_x) < (lvl_ptr)->square_width)) 244 #define SQR_COORD_Y_VALID(lvl_ptr, sqr_coord_y) \ 245 (((sqr_coord_y) < (lvl_ptr)->square_height)) 246 #define SQR_COORD_VALID(lvl_ptr, sqr_coord_y, sqr_coord_x) \ 247 (SQR_COORD_Y_VALID (lvl_ptr, sqr_coord_y) \ 248 && SQR_COORD_X_VALID (lvl_ptr, sqr_coord_x)) 249 250 /* Index to coordinate conversions. */ 251 #define SQR_INDEX_TO_COORD_X(lvl_ptr, sqr_index) \ 252 ((sqr_index) % (lvl_ptr)->square_width) 253 #define SQR_INDEX_TO_COORD_Y(lvl_ptr, sqr_index) \ 254 ((sqr_index) / (lvl_ptr)->square_width) 255 #define SQR_COORDS_TO_INDEX(lvl_ptr, sqr_y, sqr_x) \ 256 ((lvl_ptr)->square_width * (sqr_y) + (sqr_x)) 257 258 #define TILE_INDEX_TO_COORD_X(lvl_ptr, tile_index) \ 259 ((tile_index) % (lvl_ptr)->tile_width) 260 #define TILE_INDEX_TO_COORD_Y(lvl_ptr, tile_index) \ 261 ((tile_index) / (lvl_ptr)->tile_width) 262 #define TILE_COORDS_TO_INDEX(lvl_ptr, tile_y, tile_x) \ 263 ((lvl_ptr)->tile_width * (tile_y) + (tile_x)) 264 265 266 /* Tile indexes to square indexes conversions. */ 267 #define TILE_INDEX_TO_SQR_INDEX(lvl_ptr, tile_index) \ 268 (TILE_INDEX_TO_COORD_Y ((lvl_ptr), (tile_index)) * 2 \ 269 * (lvl_ptr)->square_width \ 270 + TILE_INDEX_TO_COORD_X ((lvl_ptr), (tile_index)) * 2) 271 272 #define SQR_INDEX_TO_TILE_INDEX(lvl_ptr, sqr_index) \ 273 ((SQR_INDEX_TO_COORD_Y ((lvl_ptr), (sqr_index)) / 2) \ 274 * (lvl_ptr)->tile_width \ 275 + (SQR_INDEX_TO_COORD_X ((lvl_ptr), (sqr_index)) / 2)) 276 277 /* Given the index of the top left square of a tile, 278 compute the index for each square in the tile. */ 279 #define SQR0(lvl_ptr, sqr0) (sqr0) 280 #define SQR1(lvl_ptr, sqr0) ((sqr0) + 1) 281 #define SQR2(lvl_ptr, sqr0) ((sqr0) + (lvl_ptr)->square_width) 282 #define SQR3(lvl_ptr, sqr0) ((sqr0) + (lvl_ptr)->square_width + 1) 283 #define SQRX(lvl_ptr, sqr0, x) \ 284 ((sqr0) + (((x) & 2) ? (lvl_ptr)->square_width : 0) + ((x) & 1)) 285 286 287 #endif /* HEROES__LVL__H */ 288