From d3dc2389c308278442831f370950b2d25e5fa734 Mon Sep 17 00:00:00 2001 From: zlago Date: Fri, 27 Sep 2024 10:32:11 +0200 Subject: tile collision --- src/loader.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) (limited to 'src/loader.c') diff --git a/src/loader.c b/src/loader.c index 985f4b7..6a50341 100644 --- a/src/loader.c +++ b/src/loader.c @@ -11,6 +11,7 @@ #include "loader.h" #include "util.h" #include "main.h" +#include "collision.h" static void *inflateWrapped(void *const restrict data, uint32_t const outsize); @@ -18,6 +19,7 @@ typedef enum { FILE_EXT_UNKNOWN, FILE_EXT_TEXTURE, FILE_EXT_MAP, + FILE_EXT_COLLISION, } ext_T; ext_T get_extension_type(char *extension, int length); @@ -35,7 +37,7 @@ struct blob_collection { struct blob blob; name_T name; } items[]; -} *textures = NULL, *maps = NULL; +} *textures = NULL, *maps = NULL, *collisions = NULL; static int name_compare(name_T a, name_T b) { return strcmp(a, b); @@ -85,6 +87,16 @@ void res_init_map(void) { maps = res_init_blobs(); } +void res_init_collision(void) { + collisions = res_init_blobs(); +} + +void res_init(void) { + res_init_texture(); + res_init_map(); + res_init_collision(); +} + void res_free_texture(void) { for (size_t i = 0; i < textures->count; i++) { SDL_DestroyTexture(textures->items[i].blob.data); @@ -107,6 +119,11 @@ void res_free_map(void) { maps = NULL; } +void res_free_collision(void) { + res_free_blobs(maps); + collisions = NULL; +} + static int res_compare_blobs(void const *a, void const *b) { struct blob_item const *aa = a, *bb = b; return name_compare(aa->name, bb->name); @@ -139,6 +156,10 @@ struct blob res_get_map(name_T const name) { return res_get_blob(name, maps); } +struct blob res_get_collision(name_T const name) { + return res_get_blob(name, collisions); +} + static struct blob_collection *res_push_blob(struct blob *blob, name_T name, struct blob_collection *collection, void (*freeFunc)(void *)) { int found; struct blob_item new = {.blob = *blob, .name = name}; @@ -181,6 +202,10 @@ void res_push_map(struct blob *blob, name_T name) { maps = res_push_blob(blob, name, maps, blob_free_func); } +void res_push_collision(struct blob *blob, name_T name) { + collisions = res_push_blob(blob, name, collisions, blob_free_func); +} + int loadResources(char *filename) { // open the file FILE *zip = fopen(filename, "rb"); @@ -285,6 +310,81 @@ int loadResources(char *filename) { blob = (struct blob) {.data = chaos_file->data, .size = chaos_file->size}; res_push_map(&blob, chaos_file->name); break; + + case FILE_EXT_COLLISION:; + char const *props = chaos_file->data; + size_t remaining = chaos_file->size; + if (props[remaining - 1] != '\n') { + fprintf(stderr, "warn: will not load %s.col (missing trailing newline)\n", chaos_file->name); + free(chaos_file->name); + free(chaos_file->data); + break; + } + int tiles = 0; + for (size_t i = 0; i < remaining; i++) { + if (props[i] == '\n') { + tiles++; + } + } + //fprintf(stderr, "allocating %u tiles\n", tiles); + collision_T *const data = calloc(tiles, sizeof (collision_T)); + for (int tile = 0; tile < tiles; tile++) { + char const *tmp = memchr(props, '\n', remaining); + size_t tile_remaining = tmp - props; + //fprintf(stderr, "tile %u (%zu):", tile, tile_remaining); + char const *tile_props = props; + props += tile_remaining + 1; + while (true) { + char const *tile_prop = memchr(tile_props, ',', tile_remaining); + char const *const str = tile_props; + size_t len; + if (tile_prop == NULL) { + len = tile_remaining; + //fprintf(stderr, " '%.*s'", len, tile_props); + //fprintf(stderr, " '%u'", len); + } else { + len = tile_prop - tile_props; + //fprintf(stderr, " '%.*s'", len, tile_props); + //fprintf(stderr, " '%u'", len); + tile_props += len + 1; + tile_remaining -= len + 1; + } + + if (len == 0) { + break; + } + + #define t(a, b)\ + else if (len == sizeof (a) - 1 && memcmp(str, a, sizeof (a) - 1) == 0) {\ + data[tile] |= b;\ + } + t("solid", 1 << COLLISION_SOLID | 1 << COLLISION_FLOOR) + t("hazard", 1 << COLLISION_HAZARD) + t("semisolid", 1 << COLLISION_FLOOR) + #undef t + #if 0 + if (len == 5 && memcmp(str, "solid", 5) == 0) { + data[tile] |= 1 << COLLISION_SOLID | 1 << COLLISION_FLOOR; + } else if (len == 6 && memcmp(str, "hazard", 6) == 0) { + data[tile] |= 1 << COLLISION_HAZARD; + } else if (len == 9 && memcmp(str, "semisolid", 9) == 0) { + data[tile] |= 1 << COLLISION_FLOOR; + } + #endif + else { + fprintf(stderr, "warn: %s: unrecognized property '%.*s'\n", chaos_file->name, (int) len, str); + } + + if (tile_prop == NULL) { + break; + } + } + //fprintf(stderr, " %b\n", data[tile]); + } + free(chaos_file->data); + blob = (struct blob) {.data = data, .size = tiles}; + res_push_collision(&blob, chaos_file->name); + break; default: free(chaos_file->data), chaos_file->data = NULL; @@ -310,6 +410,7 @@ ext_T get_extension_type(char *extension, int length) { ext("jpg", FILE_EXT_TEXTURE); ext("gif", FILE_EXT_TEXTURE); ext("map", FILE_EXT_MAP); + ext("col", FILE_EXT_COLLISION); return FILE_EXT_UNKNOWN; #undef ext } -- cgit 1.4.1-2-gfad0