Mercurial > molko
changeset 27:607bd90aba63
core: finalize map converter and opener, closes #2448 @6h
author | David Demelier <markand@malikania.fr> |
---|---|
date | Sun, 12 Jan 2020 21:04:49 +0100 |
parents | 65398df5fb5c |
children | 783841af4033 |
files | Makefile src/main.c src/map.c src/map.h src/sprite.c src/sprite.h tools/molko-map.c |
diffstat | 7 files changed, 257 insertions(+), 11 deletions(-) [+] |
line wrap: on
line diff
--- a/Makefile Sun Jan 12 21:01:10 2020 +0100 +++ b/Makefile Sun Jan 12 21:04:49 2020 +0100 @@ -18,14 +18,15 @@ .POSIX: -CC= clang -CFLAGS= -MMD -O3 -DNDEBUG -std=c18 -Wall -Wextra +CC= gcc +CFLAGS= -MMD -O3 -DNDEBUG -std=c18 -Wall -Wextra -g PROG= molko LIB= libmolko.a SRCS= src/animation.c \ src/clock.c \ src/event.c \ src/font.c \ + src/map.c \ src/message.c \ src/image.c \ src/sprite.c \
--- a/src/main.c Sun Jan 12 21:01:10 2020 +0100 +++ b/src/main.c Sun Jan 12 21:04:49 2020 +0100 @@ -24,22 +24,32 @@ #include "event.h" #include "font.h" #include "image.h" +#include "map.h" #include "message.h" #include "sprite.h" #include "sys.h" #include "texture.h" #include "window.h" +#include <SDL.h> + int main(int argc, char **argv) { (void)argc; (void)argv; + struct map map; struct font *font; sys_init(); - window_init("Molko's Adventure", 1280, 720); + if (!window_init("Molko's Adventure", 1280, 720)) { + printf("%s\n", SDL_GetError()); + exit(1); + } + + if (!map_open(&map, "default.map")) + exit(1); if (!(font = font_openf("assets/fonts/DejaVuSansCondensed.ttf", 12))) exit(1); @@ -76,12 +86,17 @@ window_set_color(0x667788ff); window_clear(); +#if 0 message_update(&welcome, elapsed); message_draw(&welcome); +#endif + map_draw(&map); window_present(); } sys_close(); + map_close(&map); + font_close(font); return 0; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/map.c Sun Jan 12 21:04:49 2020 +0100 @@ -0,0 +1,165 @@ +/* + * map.c -- game map + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "map.h" +#include "image.h" +#include "texture.h" +#include "sprite.h" + +#include <SDL.h> + +#define MAXLEN(v) STRINGIFY(v) +#define STRINGIFY(v) "%" #v "s" + +static void +parse_layer(struct map *map, const char *line, FILE *fp) +{ + char layer_name[32]; + struct map_layer *layer; + size_t amount, current; + + /* Determine layer. */ + if (sscanf(line, "layer|%32s", layer_name) <= 0) + return; + if (strcmp(layer_name, "background") == 0) + layer = &map->layers[0]; + else if (strcmp(layer_name, "foreground") == 0) + layer = &map->layers[1]; + else + return; + + /* Check if weight/height has been specified. */ + if (map->width == 0 || map->height == 0) + return; + + amount = map->width * map->height; + current = 0; + if (!(layer->tiles = calloc(amount, sizeof (uint16_t)))) + return; + + for (int tile; fscanf(fp, "%d", &tile) && current < amount; ++current) + layer->tiles[current] = tile; +} + +static void +parse_tileset(struct map *map, const char *line) +{ + char filename[128 + 1] = { 0 }; + char path[512] = { 0 }; + + sscanf(line, "tileset|%128s", filename); + snprintf(path, sizeof (path), "assets/tilesets/%s", filename); + + if (!(map->tileset = image_openf(path))) + return; + + sprite_init(&map->sprite, map->tileset, map->tilewidth, map->tileheight); +} + +static void +parse(struct map *map, const char *line, FILE *fp) +{ + if (strncmp(line, "title", 5) == 0) + sscanf(line, "title|" MAXLEN(MAP_TITLE_MAX), map->title); + else if (strncmp(line, "width", 5) == 0) + sscanf(line, "width|%hu", &map->width); + else if (strncmp(line, "height", 6) == 0) + sscanf(line, "height|%hu", &map->height); + else if (strncmp(line, "tilewidth", 9) == 0) + sscanf(line, "tilewidth|%hhu", &map->tilewidth); + else if (strncmp(line, "tileheight", 10) == 0) + sscanf(line, "tileheight|%hhu", &map->tileheight); + else if (strncmp(line, "tileset", 7) == 0) + parse_tileset(map, line); + else if (strncmp(line, "layer", 5) == 0) + parse_layer(map, line, fp); +} + +static void +draw_layer(struct map *map, const struct map_layer *layer) +{ + assert(map); + assert(layer); + + int16_t x = 0, y = 0; + + for (uint16_t r = 0; r < map->width; ++r) { + for (uint16_t c = 0; c < map->height; ++c) { + size_t si = r * map->width + c; + size_t sr = (layer->tiles[si] - 1) / map->sprite.ncols; + size_t sc = (layer->tiles[si] - 1) % map->sprite.nrows; + + if (layer->tiles[si] != 0) + sprite_draw(&map->sprite, sr, sc, x, y); + + x += map->tilewidth; + } + + x = 0; + y += map->tileheight; + } +} + +bool +map_open(struct map *map, const char *path) +{ + assert(map); + assert(path); + + memset(map, 0, sizeof (struct map)); + + FILE *fp = fopen(path, "r"); + char line[BUFSIZ]; + + if (!fp) + return false; + + while (fgets(line, sizeof (line), fp)) { + /* Remove \n if any */ + line[strcspn(line, "\n")] = '\0'; + parse(map, line, fp); + } + + fclose(fp); + + return true; +} + +void +map_draw(struct map *map) +{ + draw(map, &map->layers[0]); + draw(map, &map->layers[1]); +} + +void +map_close(struct map *map) +{ + assert(map); + + if (map->tileset) + texture_close(map->tileset); + + free(map->layers[0].tiles); + free(map->layers[1].tiles); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/map.h Sun Jan 12 21:04:49 2020 +0100 @@ -0,0 +1,57 @@ +/* + * map.h -- game map + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef MOLKO_MAP_H +#define MOLKO_MAP_H + +/** + * \file map.h + * \brief Game map. + */ + +#include <stdbool.h> +#include <stdint.h> + +#include "sprite.h" + +#define MAP_TITLE_MAX 32 + +struct texture; + +struct map_layer { + uint16_t *tiles; +}; + +struct map { + char title[MAP_TITLE_MAX]; + struct texture *tileset; + struct sprite sprite; + uint16_t width; + uint16_t height; + uint8_t tilewidth; + uint8_t tileheight; + struct map_layer layers[2]; +}; + +bool +map_open(struct map *map, const char *path); + +void +map_close(struct map *map); + +#endif /* !MOLKO_MAP_H */
--- a/src/sprite.c Sun Jan 12 21:01:10 2020 +0100 +++ b/src/sprite.c Sun Jan 12 21:04:49 2020 +0100 @@ -23,7 +23,7 @@ #include "texture.h" void -sprite_init(struct sprite *sprite, struct texture *tex, uint16_t cellw, uint16_t cellh) +sprite_init(struct sprite *sprite, struct texture *tex, uint8_t cellw, uint8_t cellh) { int w = 0; int h = 0;
--- a/src/sprite.h Sun Jan 12 21:01:10 2020 +0100 +++ b/src/sprite.h Sun Jan 12 21:04:49 2020 +0100 @@ -33,8 +33,8 @@ */ struct sprite { struct texture *texture; /*!< Texture to access (RO) */ - uint16_t cellw; /*!< Width per cell (RW) */ - uint16_t cellh; /*!< Height per cell (RW) */ + uint8_t cellw; /*!< Width per cell (RW) */ + uint8_t cellh; /*!< Height per cell (RW) */ uint16_t nrows; /*!< Number of rows (RW) */ uint16_t ncols; /*!< Number of columns (RW) */ }; @@ -61,8 +61,8 @@ void sprite_init(struct sprite *sprite, struct texture *tex, - uint16_t cellw, - uint16_t cellh); + uint8_t cellw, + uint8_t cellh); /** * Draw the sprite component from row `r' and column `c'.
--- a/tools/molko-map.c Sun Jan 12 21:01:10 2020 +0100 +++ b/tools/molko-map.c Sun Jan 12 21:04:49 2020 +0100 @@ -75,16 +75,24 @@ static void write_metadata(const json_t *document) { + json_t *width = json_object_get(document, "width"); json_t *height = json_object_get(document, "height"); - json_t *width = json_object_get(document, "width"); + json_t *tilewidth = json_object_get(document, "tilewidth"); + json_t *tileheight = json_object_get(document, "tileheight"); + if (!width || !json_is_integer(width)) + die("missing 'width' property\n"); if (!height || !json_is_integer(height)) die("missing 'height' property\n"); - if (!width || !json_is_integer(width)) - die("missing 'width' property\n"); + if (!tilewidth || !json_is_integer(tilewidth)) + die("missing 'tilewidth' property\n"); + if (!tileheight || !json_is_integer(tileheight)) + die("missing 'tileheight' property\n"); printf("width|%lld\n", json_integer_value(width)); printf("height|%lld\n", json_integer_value(height)); + printf("tilewidth|%lld\n", json_integer_value(tilewidth)); + printf("tileheight|%lld\n", json_integer_value(tileheight)); } static void