summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzlago2024-09-27 10:32:11 +0200
committerzlago2024-09-27 10:32:11 +0200
commitd3dc2389c308278442831f370950b2d25e5fa734 (patch)
treed14270a7706a4f80a5d2b8110bf0eda136e89494
parentba5b241f672cce00d1fe9521da445aa8d7f918b0 (diff)
tile collision
-rw-r--r--assets.mk3
-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
9 files changed, 216 insertions, 11 deletions
diff --git a/assets.mk b/assets.mk
index 2171911..f2e47e7 100644
--- a/assets.mk
+++ b/assets.mk
@@ -6,6 +6,7 @@ tilesets := $(patsubst src/res/set/%.ase,out/%.png,$(wildcard src/res/set/*.ase)
images := $(patsubst src/res/%.ase,out/%.png,$(wildcard src/res/*.ase))
maps := $(patsubst src/res/%.tmx,out/%.map,$(wildcard src/res/*.tmx))
music := $(wildcard src/res/*.xm)
+collision := $(wildcard src/res/*.col)
out/%.png: src/res/%.ase | out/
${PRITE} -b $(abspath $<) --save-as $(abspath $@)
@@ -22,5 +23,5 @@ out/%.json: src/res/%.tmx ${tilesets} ${images} | out/
out/%.map: out/%.json out/json2map | out/
out/json2map $< $@
-out/assets.res: ${tilesets} ${images} ${maps} ${music} | out/
+out/assets.res: ${tilesets} ${images} ${maps} ${music} ${collision} | out/
${ZIP} -Xj9q $@ $?
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;