Mercurial > molko
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 } |