From e304b0a4acc3f0870f55e6b584c464096333dfdc Mon Sep 17 00:00:00 2001 From: zlago Date: Fri, 27 Sep 2024 18:34:24 +0200 Subject: tilemap collision the 'middle ground' layer is the only layer which is solid, and the boundary between the background and the foreground additionally, the maps now can have a custom sky color --- src/tilemap.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 57 insertions(+), 7 deletions(-) (limited to 'src/tilemap.c') diff --git a/src/tilemap.c b/src/tilemap.c index 84d2509..af2c163 100644 --- a/src/tilemap.c +++ b/src/tilemap.c @@ -14,19 +14,40 @@ struct tilemap *tilemap = NULL, *next_tilemap = NULL; #define PACKED __attribute__((__packed__)) +uint8_t const MAGIC[4] = "TMv1"; + struct PACKED sets { + uint8_t magic[4]; uint32_t tilesets_count; uint32_t wang_count; }; struct PACKED map { + struct { + uint8_t r, g, b, a; + } backdrop; uint32_t width; uint32_t height; uint32_t layers; + uint32_t middleground; uint8_t tiles[]; }; -void free_tilemap(struct tilemap *tilemap) { +void tilemap_background(struct tilemap *tilemap, int x, int y, int w, int h) { + SDL_SetRenderDrawColor(renderer, tilemap->backdrop.r, tilemap->backdrop.g, tilemap->backdrop.b, tilemap->backdrop.a); + SDL_RenderFillRect(renderer, &(SDL_Rect) {0, 0, w, h}); + for (int i = 0; i < tilemap->middleground; i++) { + SDL_RenderCopy(renderer, tilemap->tilemaps[i], &(SDL_Rect) {x * tilemap->parallax[i].x, y * tilemap->parallax[i].y, w, h}, &(SDL_Rect) {0, 0, w, h}); + } +} + +void tilemap_foreground(struct tilemap *tilemap, int x, int y, int w, int h) { + for (int i = tilemap->middleground; i < tilemap->layers; i++) { + SDL_RenderCopy(renderer, tilemap->tilemaps[i], &(SDL_Rect) {x * tilemap->parallax[i].x, y * tilemap->parallax[i].y, w, h}, &(SDL_Rect) {0, 0, w, h}); + } +} + +void tilemap_free(struct tilemap *tilemap) { SDL_DestroyTexture(tilemap->tileset); SDL_DestroyTexture(tilemap->wang_tileset); free(tilemap->parallax); @@ -38,11 +59,23 @@ void free_tilemap(struct tilemap *tilemap) { free(tilemap); } -struct tilemap *load_tilemap(void *data, size_t size) { +struct tilemap *tilemap_load(void *data, size_t size) { + size_t const insize = size; + + struct sets *const sets = data; + data = sets + 1; + size -= sizeof (struct sets); + + if (memcmp(sets->magic, MAGIC, sizeof (MAGIC)) != 0) { + fprintf(stderr, "error: unsupported level format (got '%.4s' expected '%.4s')\n", sets->magic, MAGIC); + return NULL; + } + struct tilemap *tilemap = malloc(sizeof (struct tilemap)); if (tilemap == NULL) { return NULL; } + tilemap->tileset = SDL_CreateTexture(renderer, SDL_PIXELTYPE_UNKNOWN, SDL_TEXTUREACCESS_TARGET, 128, 128); tilemap->wang_tileset = SDL_CreateTexture(renderer, SDL_PIXELTYPE_UNKNOWN, SDL_TEXTUREACCESS_TARGET, 128, 128); SDL_SetTextureBlendMode(tilemap->wang_tileset, SDL_BLENDMODE_BLEND); @@ -51,9 +84,6 @@ struct tilemap *load_tilemap(void *data, size_t size) { tilemap->collision = NULL; tilemap->tilemaps = NULL; - struct sets *const sets = data; - data = sets + 1; - size -= sizeof (struct sets); char *str = data; int y = 0; SDL_SetRenderTarget(renderer, tilemap->tileset); @@ -95,7 +125,7 @@ struct tilemap *load_tilemap(void *data, size_t size) { str += sizeof (uint32_t); size_t len = strnlen(str, size); if (len == size) { - free_tilemap(tilemap); + tilemap_free(tilemap); return NULL; } void *tex = res_get_texture(str).data; @@ -117,11 +147,29 @@ struct tilemap *load_tilemap(void *data, size_t size) { goto fail; } + tilemap->backdrop.r = map->backdrop.r; + tilemap->backdrop.g = map->backdrop.g; + tilemap->backdrop.b = map->backdrop.b; + tilemap->backdrop.a = map->backdrop.a; tilemap->width = map->width; tilemap->height = map->height; tilemap->layers = map->layers; + tilemap->middleground = map->middleground; tilemap->tilemaps = malloc(sizeof (void *) * tilemap->layers); + if (tilemap->middleground > tilemap->layers) { + goto fail; + } else if (tilemap->middleground == 0) { + fputs("warn: map has no middle ground\n", stderr); + tilemap->collision = calloc(tilemap->width, tilemap->height * sizeof (collision_T)); + } else { + tilemap->collision = malloc(tilemap->width * tilemap->height * sizeof (collision_T)); + size_t const ll = (tilemap->middleground - 1) * map->width * map->height; + for (size_t i = 0; i < tilemap->width * tilemap->height; i++) { + tilemap->collision[i] = collision[map->tiles[i + ll]]; + } + } + for (int l = 0; l < tilemap->layers; l++) { SDL_Texture *layer = SDL_CreateTexture(renderer, SDL_PIXELTYPE_UNKNOWN, SDL_TEXTUREACCESS_TARGET, map->width * 8, map->height * 8); SDL_SetTextureBlendMode(layer, SDL_BLENDMODE_BLEND); @@ -170,11 +218,13 @@ struct tilemap *load_tilemap(void *data, size_t size) { size -= sizeof (struct parallax) * map->layers; + tilemap->input_bytes = insize - size; + //fprintf(stderr, "size: %zuB remaining: %zuB total: %zuB\n", tilemap->input_bytes, size, insize); SDL_SetRenderTarget(renderer, NULL); return tilemap; fail: - free_tilemap(tilemap); + tilemap_free(tilemap); SDL_SetRenderTarget(renderer, NULL); return NULL; } -- cgit 1.4.1-2-gfad0