From b32bffdf8fc10db7875ce1bbf4fed2a23a160653 Mon Sep 17 00:00:00 2001 From: P. J. McDermott Date: Sun, 17 Feb 2013 16:04:04 -0500 Subject: Support objectgroups and map exits. --- diff --git a/src/main.c b/src/main.c index abf515e..83d4c5a 100644 --- a/src/main.c +++ b/src/main.c @@ -10,6 +10,7 @@ main(void) struct map *map; struct image *img; struct map_tileset *ts; + struct map_exit *e; SDL_Rect imgrect, surfacerect; init(); @@ -20,6 +21,12 @@ main(void) debug("Tileset name: %s", ts->tileset->name); debug("Tileset firstgid: %d", ts->firstgid); } + for (e = map->map_exits_head; e != NULL; e = e->next) { + debug("Exit target: map %s (size %dx%d) at (%d,%d)", + e->target_map_name, + e->target_map->width, e->target_map->height, + e->target_x_coord, e->target_y_coord); + } img = img_png_get("../forest-6-layer-test_ground.png"); img_png_free(img); diff --git a/src/resources/map.c b/src/resources/map.c index 7eda415..800a272 100644 --- a/src/resources/map.c +++ b/src/resources/map.c @@ -26,6 +26,17 @@ static void XMLCALL tmx_layer_el_start(void *, const char *, const char **); static void XMLCALL tmx_layer_end(void *, const char *); static void XMLCALL tmx_data_end(void *, const char *); static void XMLCALL tmx_data_cdata(void *, const char *, int); +static void XMLCALL tmx_objectgroup_el_start(void *, const char *, + const char **); +static void XMLCALL tmx_objectgroup_end(void *, const char *); +static void XMLCALL tmx_object_exit_el_start(void *, const char *, + const char **); +static void XMLCALL tmx_object_exit_end(void *, const char *); +static void XMLCALL tmx_object_spawn_el_start(void *, const char *, + const char **); +static void XMLCALL tmx_object_spawn_end(void *, const char *); +static void XMLCALL tmx_object_exit_property_start(void *, const char *, + const char **); static void XMLCALL tmx_unused_start(void *, const char *, const char **); static void XMLCALL tmx_unused_end(void *, const char *); static void XMLCALL tmx_invalid_start(void *, const char *, const char **); @@ -146,6 +157,18 @@ map_get_layer(struct map *m, const char *name) } } +void +map_add_exit(struct map *m, struct map_exit *e) +{ + e->next = NULL; + if (m->map_exits_head == NULL) { + m->map_exits_head = e; + } else { + m->map_exits_tail->next = e; + } + m->map_exits_tail = e; +} + static struct tileset * tileset_get(const char *path, const char *basedir) { @@ -308,6 +331,9 @@ tmx_map_el_start(void *pv, const char *name, const char **attr) free(ly_name); ly->map = m; xml_node_push(p, ly, tmx_layer_el_start, tmx_layer_end, NULL); + } else if (xml_check_tag(name, "objectgroup")) { + xml_node_push(p, m, tmx_objectgroup_el_start, + tmx_objectgroup_end, NULL); } else { xml_unexpected_start_tag(p, name, "properties, tileset, layer, or objectgroup"); @@ -391,13 +417,15 @@ tmx_tileset_el_start(void *pv, const char *name, const char **attr) img = img_png_get(path); free(source); xml_node_push(p, img, tmx_invalid_start, tmx_image_end, NULL); -#if 0 } else if (xml_check_tag(name, "tile")) { + /* TODO */ + xml_node_push(p, NULL, tmx_unused_start, tmx_unused_end, NULL); +#if 0 xml_node_push(p, img, tmx_tile_properties_start, tmx_tile_end, NULL); #endif } else { - xml_unexpected_start_tag(p, name, "image"); + xml_unexpected_start_tag(p, name, "tileoffset, image, tile"); } } @@ -441,7 +469,7 @@ tmx_layer_el_start(void *pv, const char *name, const char **attr) xml_node_push(p, ly, tmx_invalid_start, tmx_data_end, tmx_data_cdata); } else { - xml_unexpected_start_tag(p, name, "layer"); + xml_unexpected_start_tag(p, name, "properties or data"); } } @@ -556,6 +584,204 @@ tmx_data_cdata(void *pv, const char *s, int len) } static void XMLCALL +tmx_objectgroup_el_start(void *pv, const char * name, const char **attr) +{ + XML_Parser p = (XML_Parser) pv; + struct map *m; + char *type; + struct map_exit *e; + struct map_spawn *s; + + debug("<%s> (objectgroup child)", name); + + m = xml_node_peek(p); + + if (xml_check_tag(name, "properties")) { + /* Not used by engine. */ + xml_node_push(p, NULL, tmx_unused_start, tmx_unused_end, NULL); + } else if (xml_check_tag(name, "object")) { + type = NULL; + xml_get_string_attr(p, attr, "type", &type, 0); + if (type == NULL) { + xml_node_push(p, NULL, tmx_unused_start, tmx_unused_end, + NULL); + } else if (strcmp(type, "exit") == 0) { + e = malloc(sizeof(*e)); + if (e == NULL) { + return; + } + e->map = m; + xml_get_int_attr(p, attr, "x", &e->x, 1); + xml_get_int_attr(p, attr, "y", &e->y, 1); + xml_get_int_attr(p, attr, "width", &e->width, 1); + xml_get_int_attr(p, attr, "height", &e->height, 1); + xml_node_push(p, e, tmx_object_exit_el_start, + tmx_object_exit_end, NULL); + } else if (strcmp(type, "spawn") == 0) { + s = malloc(sizeof(*s)); + if (s == NULL) { + return; + } + s->map = m; + xml_get_int_attr(p, attr, "x", &s->x, 1); + xml_get_int_attr(p, attr, "y", &s->y, 1); + xml_get_int_attr(p, attr, "width", &s->width, 1); + xml_get_int_attr(p, attr, "height", &s->height, 1); + xml_node_push(p, s, tmx_object_spawn_el_start, + tmx_object_spawn_end, NULL); + } else { + xml_node_push(p, NULL, tmx_unused_start, tmx_unused_end, + NULL); + } + } else { + xml_unexpected_start_tag(p, name, "properties or object"); + } +} + +static void XMLCALL +tmx_objectgroup_end(void *pv, const char *name) +{ + XML_Parser p = (XML_Parser) pv; + + debug(" (objectgroup)", name); + + if (xml_check_tag(name, "objectgroup")) { + xml_node_pop(p); + } else { + xml_unexpected_end_tag(p, name, "objectgroup"); + } +} + +static void XMLCALL +tmx_object_exit_el_start(void *pv, const char * name, const char **attr) +{ + XML_Parser p = (XML_Parser) pv; + struct map_exit *e; + + debug("<%s> (object type=\"exit\" child)", name); + + e = xml_node_peek(p); + + if (xml_check_tag(name, "properties")) { + /* has no attributes, but GCC warns of an + * "unused parameter ‘attr’". */ + for (; 0; ++attr); + xml_node_push(p, e, tmx_object_exit_property_start, + tmx_unused_end, NULL); + } else if (xml_check_tag(name, "polygon")) { + /* Not used by engine. */ + xml_node_push(p, NULL, tmx_unused_start, tmx_unused_end, NULL); + } else if (xml_check_tag(name, "polyline")) { + /* Not used by engine. */ + xml_node_push(p, NULL, tmx_unused_start, tmx_unused_end, NULL); + } else { + xml_unexpected_start_tag(p, name, + "properties, polygon, or polyline"); + } +} + +static void XMLCALL +tmx_object_exit_end(void *pv, const char *name) +{ + XML_Parser p = (XML_Parser) pv; + struct map_exit *e; + struct map *m; + + debug(" (object type=\"exit\")", name); + + if (xml_check_tag(name, "object")) { + e = xml_node_pop(p); + m = xml_node_peek(p); + map_add_exit(m, e); + } else { + xml_unexpected_end_tag(p, name, "object"); + } +} + +static void XMLCALL +tmx_object_exit_property_start(void *pv, const char *name, const char **attr) +{ + XML_Parser p = (XML_Parser) pv; + struct map_exit *e; + char *attr_name; + char *attr_value; + char *path; + + debug("<%s> (object type=\"exit\" property)", name); + + e = xml_node_peek(p); + + if (xml_check_tag(name, "property")) { + xml_get_string_attr(p, attr, "name", &attr_name, 1); + xml_get_string_attr(p, attr, "value", &attr_value, 1); + if (strcmp(attr_name, "map") == 0) { + e->target_map_name = strdup(attr_value); + /* TODO: Lazily get map. We don't need to load the + * entire world immediately. */ + path = malloc(strlen(e->map->dirname) + + strlen(attr_value) + 6); + if (path == NULL) { + return; + } + sprintf(path, "%s/%s.tmx", e->map->dirname, attr_value); + e->target_map = map_get(path); + free(path); + /* Yeah, don't do that yet. ^ */ + } else if (strcmp(attr_name, "coords") == 0) { + sscanf(attr_value, "%d,%d", + &e->target_x_coord, &e->target_y_coord); + } + free(attr_name); + free(attr_value); + xml_node_push(p, NULL, tmx_invalid_start, tmx_unused_end, NULL); + } else { + xml_unexpected_start_tag(p, name, "property"); + } +} + +static void XMLCALL +tmx_object_spawn_el_start(void *pv, const char * name, const char **attr) +{ + XML_Parser p = (XML_Parser) pv; + struct map_spawn *s; + + debug("<%s> (object type=\"spawn\" child)", name); + + s = xml_node_peek(p); + + if (xml_check_tag(name, "properties")) { + /* has no attributes, but GCC warns of an + * "unused parameter ‘attr’". */ + for (; 0; ++attr); + /* TODO */ + xml_node_push(p, s, tmx_unused_start, tmx_unused_end, NULL); + } else if (xml_check_tag(name, "polygon")) { + /* Not used by engine. */ + xml_node_push(p, NULL, tmx_unused_start, tmx_unused_end, NULL); + } else if (xml_check_tag(name, "polyline")) { + /* Not used by engine. */ + xml_node_push(p, NULL, tmx_unused_start, tmx_unused_end, NULL); + } else { + xml_unexpected_start_tag(p, name, + "properties, polygon, or polyline"); + } +} + +static void XMLCALL +tmx_object_spawn_end(void *pv, const char *name) +{ + XML_Parser p = (XML_Parser) pv; + + debug(" (object type=\"spawn\")", name); + + if (xml_check_tag(name, "object")) { + xml_node_pop(p); + } else { + xml_unexpected_end_tag(p, name, "object"); + } +} + +static void XMLCALL tmx_unused_start(void *pv, const char *name, const char **attr) { XML_Parser p = (XML_Parser) pv; diff --git a/src/resources/map.h b/src/resources/map.h index 11ba808..bf225de 100644 --- a/src/resources/map.h +++ b/src/resources/map.h @@ -35,9 +35,33 @@ struct layer { char *compression; char *raw_data; }; +struct map_exit { + struct map *map; + int x; + int y; + int width; + int height; + char *target_map_name; + struct map *target_map; + int target_x_coord; + int target_y_coord; + struct map_exit *next; +}; +struct map_spawn { + struct map *map; + int x; + int y; + int width; + int height; + int player; + struct map_spawn *next; +}; struct map { struct resource res; char *dirname; + /* TODO: map_get() should take a name, not a path. + char *name; + */ int width; int height; int tilewidth; @@ -46,6 +70,8 @@ struct map { struct map_tileset *tilesets_tail; struct layer layers[LAYERS_MAX]; Uint8 *collision; + struct map_exit *map_exits_head; + struct map_exit *map_exits_tail; int cur_ts_firstgid; }; @@ -53,5 +79,6 @@ struct map *map_get(const char *path); void map_free(struct map *map); void map_add_tileset(struct map *m, struct tileset *t, int firstgid); struct layer *map_get_layer(struct map *m, const char *name); +void map_add_exit(struct map *m, struct map_exit *e); #endif -- cgit v0.9.1