summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/collision.h15
-rw-r--r--src/loader.c103
-rw-r--r--src/loader.h6
-rw-r--r--src/main.c4
-rw-r--r--src/res/autotiles.col2
-rw-r--r--src/res/tileset.col64
-rw-r--r--src/tilemap.c27
-rw-r--r--src/tilemap.h3
8 files changed, 214 insertions, 10 deletions
diff --git a/src/collision.h b/src/collision.h
new file mode 100644
index 0000000..3b7a457
--- /dev/null
+++ b/src/collision.h
@@ -0,0 +1,15 @@
+#pragma once
+
+typedef unsigned collision_T;
+
+enum _collisions {
+	COLLISION_SOLID,
+	COLLISION_HAZARD,
+	COLLISION_FLOOR,
+
+	COLLISION_LENGTH // no. of checked inputs
+};
+
+#define collision_solid(a)   (1 & a >> COLLISION_SOLID)
+#define collision_hazard(a)  (1 & a >> COLLISION_HAZARD)
+#define collision_floor(a)   (1 & a >> COLLISION_FLOOR)
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
 }
diff --git a/src/loader.h b/src/loader.h
index 45a1ac0..6ffb60e 100644
--- a/src/loader.h
+++ b/src/loader.h
@@ -5,6 +5,8 @@ struct blob {
 	size_t size;
 };
 
+void res_init(void);
+
 void res_init_texture(void);
 void res_free_texture(void);
 struct blob res_get_texture(name_T const name);
@@ -13,4 +15,8 @@ void res_init_map(void);
 void res_free_map(void);
 struct blob res_get_map(name_T const name);
 
+void res_init_collision(void);
+void res_free_collision(void);
+struct blob res_get_collision(name_T const name);
+
 int loadResources(char *filename);
diff --git a/src/main.c b/src/main.c
index 394f52c..6da4d9a 100644
--- a/src/main.c
+++ b/src/main.c
@@ -48,9 +48,7 @@ int main(int argc, char **argv) {
 	SDL_RenderSetLogicalSize(renderer, WINDOW_WIDTH, WINDOW_HEIGHT);
 	
 	{
-		res_init_texture();
-		res_init_map();
-		//init_tilemap();
+		res_init();
 		void *a = util_executableRelativePath("assets.res", *argv, 0);
 		puts(a);
 		if (loadResources(a)) {
diff --git a/src/res/autotiles.col b/src/res/autotiles.col
new file mode 100644
index 0000000..bb9556c
--- /dev/null
+++ b/src/res/autotiles.col
@@ -0,0 +1,2 @@
+solid
+solid
diff --git a/src/res/tileset.col b/src/res/tileset.col
new file mode 100644
index 0000000..7e9599d
--- /dev/null
+++ b/src/res/tileset.col
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+solid,hazard
+solid,hazard
+solid,hazard
+solid,hazard
+
+
+
+
+
+
+
+
+
+
+
+
+solid,hazard
+solid,hazard
+solid,hazard
+solid,hazard
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/tilemap.c b/src/tilemap.c
index 5660046..84d2509 100644
--- a/src/tilemap.c
+++ b/src/tilemap.c
@@ -8,6 +8,7 @@
 #include "main.h"
 
 #include "tilemap.h"
+#include "collision.h"
 
 struct tilemap *tilemap = NULL, *next_tilemap = NULL;
 
@@ -58,7 +59,9 @@ struct tilemap *load_tilemap(void *data, size_t size) {
 	SDL_SetRenderTarget(renderer, tilemap->tileset);
 	SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
 	SDL_RenderClear(renderer);
-
+	
+	collision_T collision[256] = {0};
+	
 	for (uint32_t count = sets->tilesets_count; count > 0; count--) {
 		int height = *(uint32_t *) str;
 		str += sizeof (uint32_t);
@@ -67,8 +70,14 @@ struct tilemap *load_tilemap(void *data, size_t size) {
 			goto fail;
 		}
 		void *tex = res_get_texture(str).data;
+		struct blob col = res_get_collision(str);
 		
 		SDL_RenderCopy(renderer, tex, &(SDL_Rect) {0, 0, 128, height}, &(SDL_Rect) {0, y, 128, height});
+		if (col.size + y * 2 > 0xf0) {
+			fprintf(stderr, "warn: '%s' overflows tile properties\n", str);
+			col.size = 0xf0 - y * 2;
+		}
+		memcpy(collision + y * 2, col.data, col.size * sizeof (collision_T));
 		
 		y += height;
 		str += len + 1;
@@ -78,9 +87,11 @@ struct tilemap *load_tilemap(void *data, size_t size) {
 	SDL_SetRenderTarget(renderer, tilemap->wang_tileset);
 	SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
 	SDL_RenderClear(renderer);
-
-	if (sets->tilesets_count) {
+	
+	int wangs = 0;
+	if (sets->wang_count) {
 		int height = *(uint32_t *) str;
+		wangs = height / 8;
 		str += sizeof (uint32_t);
 		size_t len = strnlen(str, size);
 		if (len == size) {
@@ -88,13 +99,19 @@ struct tilemap *load_tilemap(void *data, size_t size) {
 			return NULL;
 		}
 		void *tex = res_get_texture(str).data;
+		struct blob col = res_get_collision(str);
 		
 		SDL_RenderCopy(renderer, tex, &(SDL_Rect) {0, 0, 128, height}, &(SDL_Rect) {0, 0, 128, height});
+		if (col.size > 16) {
+			fprintf(stderr, "warn: '%s' overflows tile properties\n", str);
+			col.size = 16;
+		}
+		memcpy(collision + 0xf0, col.data, col.size * sizeof (collision_T));
 
 		str += len + 1;
 		size -= len + 4 + 1;
 	}
-	
+
 	struct map const *const map = (void *) str;
 	if (map->width * map->height * map->layers > size - sizeof (struct map)) {
 		goto fail;
@@ -121,7 +138,7 @@ struct tilemap *load_tilemap(void *data, size_t size) {
 			}
 		}
 		
-		for (int tile = 0xf0; tile < 0x100; tile++) {
+		for (int tile = 0xf0; tile < 0xf0 + wangs; tile++) {
 			for (int y = 0; y < map->height - 1; y++) {
 				size_t const yy = y * map->width;
 				for (int x = 0; x < map->width - 1; x++) {
diff --git a/src/tilemap.h b/src/tilemap.h
index e9b42aa..587bdf6 100644
--- a/src/tilemap.h
+++ b/src/tilemap.h
@@ -1,4 +1,5 @@
 #pragma once
+#include "collision.h"
 
 extern struct tilemap {
 	void *tileset;
@@ -10,7 +11,7 @@ extern struct tilemap {
 	struct parallax {
 		float x, y;
 	} *parallax;
-	unsigned *collision;
+	collision_T *collision;
 	void **tilemaps;
 } *tilemap, *next_tilemap;