comparison src/core/map.c @ 98:c7e993455985

map: split the map structure into two definitions While here, add some macros to increase map_state readability.
author David Demelier <markand@malikania.fr>
date Mon, 30 Mar 2020 20:30:00 +0200
parents 58133933ea17
children
comparison
equal deleted inserted replaced
97:58133933ea17 98:c7e993455985
29 #include "sprite.h" 29 #include "sprite.h"
30 #include "sys.h" 30 #include "sys.h"
31 #include "texture.h" 31 #include "texture.h"
32 #include "window.h" 32 #include "window.h"
33 33
34 #include <SDL.h>
35
36 /* Create %<v>c string literal for scanf */ 34 /* Create %<v>c string literal for scanf */
37 #define MAX_F(v) MAX_F_(v) 35 #define MAX_F(v) MAX_F_(v)
38 #define MAX_F_(v) "%" #v "c" 36 #define MAX_F_(v) "%" #v "c"
39 37
40 static void 38 static void
41 parse_layer(struct map *map, const char *line, FILE *fp) 39 parse_layer(struct map_data *data, const char *line, FILE *fp)
42 { 40 {
43 char layer_name[32 + 1] = { 0 }; 41 char layer_name[32 + 1] = { 0 };
44 struct map_layer *layer; 42 struct map_layer *layer;
45 size_t amount, current; 43 size_t amount, current;
46 44
47 /* Determine layer. */ 45 /* Determine layer. */
48 if (sscanf(line, "layer|%32s", layer_name) <= 0) 46 if (sscanf(line, "layer|%32s", layer_name) <= 0)
49 return; 47 return;
50 if (strcmp(layer_name, "background") == 0) 48 if (strcmp(layer_name, "background") == 0)
51 layer = &map->layers[0]; 49 layer = &data->layers[0];
52 else if (strcmp(layer_name, "foreground") == 0) 50 else if (strcmp(layer_name, "foreground") == 0)
53 layer = &map->layers[1]; 51 layer = &data->layers[1];
54 else 52 else
55 return; 53 return;
56 54
57 /* Check if weight/height has been specified. */ 55 /* Check if weight/height has been specified. */
58 if (map->width == 0 || map->height == 0) 56 if (data->w == 0 || data->h == 0)
59 return; 57 return;
60 58
61 amount = map->width * map->height; 59 amount = data->w * data->h;
62 current = 0; 60 current = 0;
63 61
64 if (!(layer->tiles = calloc(amount, sizeof (unsigned short)))) 62 if (!(layer->tiles = calloc(amount, sizeof (unsigned short))))
65 return; 63 return;
66 64
67 for (int tile; fscanf(fp, "%d", &tile) && current < amount; ++current) 65 for (int tile; fscanf(fp, "%d", &tile) && current < amount; ++current)
68 layer->tiles[current] = tile; 66 layer->tiles[current] = tile;
69 } 67 }
70 68
71 static void 69 static void
72 parse_tileset(struct map *map, const char *line) 70 parse(struct map_data *data, const char *line, FILE *fp)
73 {
74 char filename[128 + 1] = { 0 };
75
76 sscanf(line, "tileset|%128s", filename);
77
78 if (map->tilewidth == 0 || map->tileheight == 0)
79 return;
80 if (!(image_open(&map->tileset, sys_datapath("tilesets/%s", filename))))
81 return;
82 }
83
84 static void
85 parse(struct map *map, const char *line, FILE *fp)
86 { 71 {
87 if (strncmp(line, "title", 5) == 0) 72 if (strncmp(line, "title", 5) == 0)
88 sscanf(line, "title|" MAX_F(MAP_TITLE_MAX), map->title); 73 sscanf(line, "title|" MAX_F(MAP_TITLE_MAX), data->title);
89 else if (strncmp(line, "width", 5) == 0) 74 else if (strncmp(line, "width", 5) == 0)
90 sscanf(line, "width|%u", &map->width); 75 sscanf(line, "width|%u", &data->w);
91 else if (strncmp(line, "height", 6) == 0) 76 else if (strncmp(line, "height", 6) == 0)
92 sscanf(line, "height|%u", &map->height); 77 sscanf(line, "height|%u", &data->h);
93 else if (strncmp(line, "tilewidth", 9) == 0) 78 else if (strncmp(line, "tilewidth", 9) == 0)
94 sscanf(line, "tilewidth|%hu", &map->tilewidth); 79 sscanf(line, "tilewidth|%hu", &data->tile_w);
95 else if (strncmp(line, "tileheight", 10) == 0) 80 else if (strncmp(line, "tileheight", 10) == 0)
96 sscanf(line, "tileheight|%hu", &map->tileheight); 81 sscanf(line, "tileheight|%hu", &data->tile_h);
97 else if (strncmp(line, "origin", 6) == 0) 82 else if (strncmp(line, "origin", 6) == 0)
98 sscanf(line, "origin|%d|%d", &map->origin_x, &map->origin_y); 83 sscanf(line, "origin|%d|%d", &data->origin_x, &data->origin_y);
99 else if (strncmp(line, "tileset", 7) == 0) 84 else if (strncmp(line, "tileset", 7) == 0)
100 parse_tileset(map, line); 85 sscanf(line, "tileset|" MAX_F(MAP_TILESET_MAX), data->tileset);
101 else if (strncmp(line, "layer", 5) == 0) 86 else if (strncmp(line, "layer", 5) == 0)
102 parse_layer(map, line, fp); 87 parse_layer(data, line, fp);
103 } 88 }
104 89
105 static bool 90 static bool
106 check(struct map *map) 91 check(struct map_data *data)
107 { 92 {
108 if (strlen(map->title) == 0) 93 if (strlen(data->title) == 0)
109 return error_printf("map has no title"); 94 return error_printf("data has no title");
110 if (!map->tileset.w || !map->tileset.h) 95 if (data->w == 0 || data->h == 0)
111 return error_printf("unable to open tileset"); 96 return error_printf("data has null sizes");
112 if (map->width == 0 || map->height == 0) 97 if (data->tile_w == 0 || data->tile_h == 0)
113 return error_printf("map has null sizes"); 98 return error_printf("data has null tile sizes");
114 if (map->tilewidth == 0 || map->tileheight == 0) 99 if (!data->layers[0].tiles || !data->layers[1].tiles)
115 return error_printf("map has null tile sizes");
116 if (!map->layers[0].tiles || !map->layers[1].tiles)
117 return error_printf("could not allocate data"); 100 return error_printf("could not allocate data");
118 101
119 return true; 102 return true;
120 } 103 }
121 104
126 assert(layer); 109 assert(layer);
127 110
128 struct sprite sprite; 111 struct sprite sprite;
129 int x = 0, y = 0; 112 int x = 0, y = 0;
130 113
131 sprite_init(&sprite, &map->tileset, map->tilewidth, map->tileheight); 114 sprite_init(&sprite, &map->tileset, map->data->tile_w, map->data->tile_h);
132 115
133 for (unsigned int r = 0; r < map->width; ++r) { 116 for (unsigned int r = 0; r < map->data->w; ++r) {
134 for (unsigned int c = 0; c < map->height; ++c) { 117 for (unsigned int c = 0; c < map->data->h; ++c) {
135 unsigned int si = r * map->width + c; 118 unsigned int si = r * map->data->w + c;
136 unsigned int sr = (layer->tiles[si] - 1) / sprite.ncols; 119 unsigned int sr = (layer->tiles[si] - 1) / sprite.ncols;
137 unsigned int sc = (layer->tiles[si] - 1) % sprite.nrows; 120 unsigned int sc = (layer->tiles[si] - 1) % sprite.nrows;
138 121
139 if (layer->tiles[si] != 0) 122 if (layer->tiles[si] != 0)
140 sprite_draw(&sprite, sr, sc, x, y); 123 sprite_draw(&sprite, sr, sc, x, y);
141 124
142 x += map->tilewidth; 125 x += map->data->tile_w;
143 } 126 }
144 127
145 x = 0; 128 x = 0;
146 y += map->tileheight; 129 y += map->data->tile_h;
147 } 130 }
148 } 131 }
149 132
150 bool 133 bool
151 map_open(struct map *map, const char *path) 134 map_data_open(struct map_data *data, const char *path)
152 { 135 {
153 assert(map); 136 assert(data);
154 assert(path); 137 assert(path);
155 138
156 memset(map, 0, sizeof (struct map)); 139 memset(data, 0, sizeof (*data));
157 140
158 FILE *fp = fopen(path, "r"); 141 FILE *fp = fopen(path, "r");
159 char line[BUFSIZ]; 142 char line[BUFSIZ];
160 143
161 if (!fp) 144 if (!fp)
162 return false; 145 return false;
163 146
164 while (fgets(line, sizeof (line), fp)) { 147 while (fgets(line, sizeof (line), fp)) {
165 /* Remove \n if any */ 148 /* Remove \n if any */
166 line[strcspn(line, "\n")] = '\0'; 149 line[strcspn(line, "\n")] = '\0';
167 parse(map, line, fp); 150 parse(data, line, fp);
168 } 151 }
169 152
170 fclose(fp); 153 fclose(fp);
171 154
172 if (!check(map)) { 155 if (!check(data)) {
173 map_finish(map); 156 map_data_finish(data);
174 return false; 157 return false;
175 } 158 }
176 159
177 size_t pw = map->width * map->tilewidth; 160 /* Compute real size. */
178 size_t ph = map->height * map->tileheight; 161 data->real_w = data->w * data->tile_w;
179 162 data->real_h = data->h * data->tile_h;
180 if (!(texture_new(&map->picture, pw, ph)))
181 return error_sdl();
182 163
183 return true; 164 return true;
184 } 165 }
185 166
186 void 167 void
168 map_data_finish(struct map_data *data)
169 {
170 assert(data);
171
172 free(data->layers[0].tiles);
173 free(data->layers[1].tiles);
174
175 memset(data, 0, sizeof (*data));
176 }
177
178 bool
179 map_init(struct map *map, struct map_data *data)
180 {
181 assert(map);
182 assert(data);
183
184 if (!(image_open(&map->tileset, sys_datapath("tilesets/%s", data->tileset))))
185 goto failure;
186 if (!(texture_new(&map->picture, data->real_w, data->real_h)))
187 goto failure;
188
189 map->data = data;
190 map_repaint(map);
191
192 return true;
193
194 failure:
195 map_data_finish(data);
196
197 return false;
198 }
199
200 void
187 map_draw(struct map *map, int srcx, int srcy) 201 map_draw(struct map *map, int srcx, int srcy)
188 { 202 {
189 texture_scale( 203 texture_scale(&map->picture, srcx, srcy, window.w, window.h,
190 &map->picture, 204 0, 0, window.w, window.h, 0.0);
191 srcx,
192 srcy,
193 window.w,
194 window.h,
195 0,
196 0,
197 window.w,
198 window.h,
199 0
200 );
201 } 205 }
202 206
203 void 207 void
204 map_repaint(struct map *map) 208 map_repaint(struct map *map)
205 { 209 {
206 PAINTER_BEGIN(&map->picture); 210 PAINTER_BEGIN(&map->picture);
207 draw_layer(map, &map->layers[0]); 211 draw_layer(map, &map->data->layers[0]);
208 draw_layer(map, &map->layers[1]); 212 draw_layer(map, &map->data->layers[1]);
209 PAINTER_END(); 213 PAINTER_END();
210 } 214 }
211 215
212 void 216 void
213 map_finish(struct map *map) 217 map_finish(struct map *map)
215 assert(map); 219 assert(map);
216 220
217 texture_finish(&map->tileset); 221 texture_finish(&map->tileset);
218 texture_finish(&map->picture); 222 texture_finish(&map->picture);
219 223
220 free(map->layers[0].tiles); 224 memset(map, 0, sizeof (*map));
221 free(map->layers[1].tiles); 225 }
222
223 memset(map, 0, sizeof (struct map));
224 }