summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorP. J. McDermott <pjm@nac.net>2013-02-17 16:04:04 (EST)
committer P. J. McDermott <pjm@nac.net>2013-02-17 16:04:04 (EST)
commitb32bffdf8fc10db7875ce1bbf4fed2a23a160653 (patch)
tree04d5fc2e22a8f6c987fce88976cb5bb187c22295 /src
parent3f5ba41ed0364268d5a6d10e4ab559b61393edf0 (diff)
downloadoverworld-rpg-b32bffdf8fc10db7875ce1bbf4fed2a23a160653.zip
overworld-rpg-b32bffdf8fc10db7875ce1bbf4fed2a23a160653.tar.gz
overworld-rpg-b32bffdf8fc10db7875ce1bbf4fed2a23a160653.tar.bz2
Support objectgroups and map exits.
Diffstat (limited to 'src')
-rw-r--r--src/main.c7
-rw-r--r--src/resources/map.c232
-rw-r--r--src/resources/map.h27
3 files changed, 263 insertions, 3 deletions
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("</%s> (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")) {
+ /* <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("</%s> (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")) {
+ /* <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("</%s> (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