summary refs log tree commit diff
path: root/src/loader.c
diff options
context:
space:
mode:
authorzlago2024-09-27 10:32:11 +0200
committerzlago2024-09-27 10:32:11 +0200
commitd3dc2389c308278442831f370950b2d25e5fa734 (patch)
treed14270a7706a4f80a5d2b8110bf0eda136e89494 /src/loader.c
parentba5b241f672cce00d1fe9521da445aa8d7f918b0 (diff)
tile collision
Diffstat (limited to 'src/loader.c')
-rw-r--r--src/loader.c103
1 files changed, 102 insertions, 1 deletions
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
 }