Mercurial > molko
changeset 592:1560ef13146c
rpg: map support player sprite
author | David Demelier <markand@malikania.fr> |
---|---|
date | Mon, 20 Mar 2023 21:59:02 +0100 |
parents | bca466732620 |
children | f9e85d0aca74 |
files | libmlk-example/assets/maps/world.json libmlk-rpg/CMakeLists.txt libmlk-rpg/mlk/rpg/map-loader-file.c libmlk-rpg/mlk/rpg/map-loader-file.h libmlk-rpg/mlk/rpg/map-loader.c libmlk-rpg/mlk/rpg/map-loader.h mlk-map/mlk-map.c |
diffstat | 7 files changed, 222 insertions(+), 26 deletions(-) [+] |
line wrap: on
line diff
--- a/libmlk-example/assets/maps/world.json Mon Mar 20 21:12:15 2023 +0100 +++ b/libmlk-example/assets/maps/world.json Mon Mar 20 21:59:02 2023 +0100 @@ -69,22 +69,37 @@ "orientation":"orthogonal", "properties":[ { - "name":"origin-x", + "name":"player-origin-x", "type":"int", "value":384 }, { - "name":"origin-y", + "name":"player-origin-y", "type":"int", "value":480 }, { + "name":"player-sprite", + "type":"string", + "value":"john.png" + }, + { + "name":"player-sprite-h", + "type":"int", + "value":48 + }, + { + "name":"player-sprite-w", + "type":"int", + "value":48 + }, + { "name":"title", "type":"string", "value":"Isolated Island" }], "renderorder":"right-down", - "tiledversion":"1.9.2", + "tiledversion":"1.10.0", "tileheight":48, "tilesets":[ { @@ -93,6 +108,6 @@ }], "tilewidth":48, "type":"map", - "version":"1.9", + "version":"1.10", "width":30 } \ No newline at end of file
--- a/libmlk-rpg/CMakeLists.txt Mon Mar 20 21:12:15 2023 +0100 +++ b/libmlk-rpg/CMakeLists.txt Mon Mar 20 21:59:02 2023 +0100 @@ -48,6 +48,7 @@ ${libmlk-rpg_SOURCE_DIR}/mlk/rpg/tileset-loader-file.h ${libmlk-rpg_SOURCE_DIR}/mlk/rpg/tileset-loader.h ${libmlk-rpg_SOURCE_DIR}/mlk/rpg/tileset.h + ${libmlk-rpg_SOURCE_DIR}/mlk/rpg/walksprite.h ) set(
--- a/libmlk-rpg/mlk/rpg/map-loader-file.c Mon Mar 20 21:12:15 2023 +0100 +++ b/libmlk-rpg/mlk/rpg/map-loader-file.c Mon Mar 20 21:59:02 2023 +0100 @@ -19,12 +19,72 @@ #include <assert.h> #include <mlk/core/alloc.h> +#include <mlk/core/image.h> +#include <mlk/core/sprite.h> +#include <mlk/core/texture.h> #include "map-loader-file.h" #include "map-loader.h" #include "map.h" #include "tileset-loader.h" +static inline void * +allocate(void ***array, size_t width) +{ + void **ptr, *elem; + + /* Not yet allocated? Allocate a new pointer element. */ + if (!*array) + ptr = mlk_alloc_new0(1, sizeof (void *)); + else + ptr = mlk_alloc_expand(*array, 1); + + if (!ptr) + return NULL; + + /* Now allocate the element itself because. */ + if (!(elem = mlk_alloc_new0(1, width))) + return NULL; + + /* Store it into the array of elements. */ + ptr[mlk_alloc_getn(ptr) - 1] = elem; + *array = ptr; + + return elem; +} + +static struct mlk_texture * +init_texture(struct mlk_map_loader *self, + struct mlk_map *map, + const char *ident) +{ + (void)map; + + struct mlk_map_loader_file *file = self->data; + struct mlk_texture *texture; + char path[MLK_PATH_MAX]; + + snprintf(path, sizeof (path), "%s/%s", file->directory, ident); + + /* No need to deallocate, already done in finish anyway. */ + if (!(texture = allocate((void ***)&file->textures, sizeof (struct mlk_texture)))) + return NULL; + if (mlk_image_open(texture, path) < 0) + return NULL; + + return texture; +} + +static struct mlk_sprite * +init_sprite(struct mlk_map_loader *self, struct mlk_map *map) +{ + (void)map; + + struct mlk_map_loader_file *file = self->data; + + return allocate((void ***)&file->sprites, sizeof (struct mlk_sprite)); +} + static struct mlk_tileset * init_tileset(struct mlk_map_loader *self, struct mlk_map *map, @@ -86,6 +146,31 @@ return ptr; } +static void +finish(void ***ptr, void (*finish)(void *)) +{ + size_t len; + + /* Already cleared. */ + if (!*ptr) + return; + + len = mlk_alloc_getn(*ptr); + + for (size_t i = 0; i < len; ++i) + finish((*ptr)[i]); + + mlk_alloc_free(*ptr); + *ptr = NULL; +} + +static void +finish_texture(void *element) +{ + mlk_texture_finish(element); + mlk_alloc_free(element); +} + void mlk_map_loader_file_init(struct mlk_map_loader_file *file, struct mlk_map_loader *loader, @@ -105,6 +190,10 @@ loader->data = file; if (!loader->init_tileset) loader->init_tileset = init_tileset; + if (!loader->init_texture) + loader->init_texture = init_texture; + if (!loader->init_sprite) + loader->init_sprite = init_sprite; if (!loader->alloc_tiles) loader->alloc_tiles = alloc_tiles; if (!loader->expand_blocks) @@ -124,4 +213,7 @@ mlk_tileset_loader_file_finish(&file->tileset_loader_file); mlk_alloc_free(file->blocks); file->blocks = NULL; + + finish((void ***)&file->sprites, mlk_alloc_free); + finish((void ***)&file->textures, finish_texture); }
--- a/libmlk-rpg/mlk/rpg/map-loader-file.h Mon Mar 20 21:12:15 2023 +0100 +++ b/libmlk-rpg/mlk/rpg/map-loader-file.h Mon Mar 20 21:59:02 2023 +0100 @@ -31,6 +31,8 @@ #include "tileset.h" struct mlk_map_loader; +struct mlk_sprite; +struct mlk_texture; /** * \struct mlk_map_loader_file @@ -47,6 +49,9 @@ /** \cond MLK_PRIVATE_DECLS */ unsigned int *tiles[MLK_MAP_LAYER_TYPE_LAST]; + struct mlk_texture **textures; + struct mlk_sprite **sprites; + /* * We use a tileset file loader if init_tileset function isn't present * in this map loader.
--- a/libmlk-rpg/mlk/rpg/map-loader.c Mon Mar 20 21:12:15 2023 +0100 +++ b/libmlk-rpg/mlk/rpg/map-loader.c Mon Mar 20 21:59:02 2023 +0100 @@ -24,6 +24,7 @@ #include <mlk/util/util.h> #include <mlk/core/err.h> +#include <mlk/core/sprite.h> #include <mlk/core/trace.h> #include <mlk/core/util.h> @@ -187,16 +188,49 @@ } static int -parse_origin(struct mlk_map_loader *loader, - struct mlk_map *map, - const char *line, - FILE *fp) +parse_player_origin(struct mlk_map_loader *loader, + struct mlk_map *map, + const char *line, + FILE *fp) { (void)loader; (void)fp; - if (sscanf(line, "origin|%d|%d", &map->player_x, &map->player_y) != 2) - return mlk_errf("invalid origin"); + if (sscanf(line, "player-origin|%d|%d", &map->player_x, &map->player_y) != 2) + return mlk_errf("invalid player origin"); + + return 0; +} + +static int +parse_player_sprite(struct mlk_map_loader *loader, + struct mlk_map *map, + const char *line, + FILE *fp) +{ + (void)fp; + + char format[32], ident[FILENAME_MAX + 1] = {0}; + unsigned int w = 0, h = 0; + struct mlk_sprite *sprite; + struct mlk_texture *texture; + + snprintf(format, sizeof (format), "player-sprite|%%u|%%u|%%%zu[^\n]", sizeof (ident) - 1); + + if (sscanf(line, format, &w, &h, ident) != 3) + return mlk_errf("invalid player sprite"); + if (!(texture = loader->init_texture(loader, map, ident))) + return -1; + if (!(sprite = loader->init_sprite(loader, map))) + return -1; + + sprite->cellw = w; + sprite->cellh = h; + sprite->texture = texture; + mlk_sprite_init(sprite); + + /* Add this sprite into the final map. */ + map->player_sprite = sprite; return 0; } @@ -211,11 +245,12 @@ const char *property; int (*read)(struct mlk_map_loader *, struct mlk_map *, const char *, FILE *); } props[] = { - { "columns", parse_columns }, - { "rows", parse_rows }, - { "tileset", parse_tileset }, - { "origin", parse_origin }, - { "layer", parse_layer }, + { "columns", parse_columns }, + { "rows", parse_rows }, + { "tileset", parse_tileset }, + { "player-origin", parse_player_origin }, + { "player-sprite", parse_player_sprite }, + { "layer", parse_layer }, }; for (size_t i = 0; i < MLK_UTIL_SIZE(props); ++i) {
--- a/libmlk-rpg/mlk/rpg/map-loader.h Mon Mar 20 21:12:15 2023 +0100 +++ b/libmlk-rpg/mlk/rpg/map-loader.h Mon Mar 20 21:59:02 2023 +0100 @@ -25,6 +25,8 @@ struct mlk_map; struct mlk_map_block; +struct mlk_sprite; +struct mlk_texture; struct mlk_tileset; /** @@ -59,6 +61,31 @@ /** * (read-write) * + * Open a texture from the given ident name. + * + * \param self this loader + * \param ident the texture name (or path) + * \return a borrowed texture or NULL on failure + */ + struct mlk_texture * (*init_texture)(struct mlk_map_loader *self, + struct mlk_map *map, + const char *ident); + + /** + * (read-write) + * + * Return a sprite that the loader needs. + * + * \param self this loader + * \return a unused sprite + * \return a borrowed sprite or NULL on failure + */ + struct mlk_sprite * (*init_sprite)(struct mlk_map_loader *self, + struct mlk_map *map); + + /** + * (read-write) + * * Allocate the number of tiles required to fill a layer. * * \param self this loader
--- a/mlk-map/mlk-map.c Mon Mar 20 21:12:15 2023 +0100 +++ b/mlk-map/mlk-map.c Mon Mar 20 21:59:02 2023 +0100 @@ -56,27 +56,48 @@ } static void -write_origin(const json_t *props) +write_player_origin(const json_t *props) { - const json_t *prop_origin_x; - const json_t *prop_origin_y; + const json_t *x, *y; - prop_origin_x = find_property(props, "origin-x"); - prop_origin_y = find_property(props, "origin-y"); + x = find_property(props, "player-origin-x"); + y = find_property(props, "player-origin-y"); - if (!prop_origin_x || !json_is_integer(prop_origin_x) || - !prop_origin_y || !json_is_integer(prop_origin_y)) + if (!x || !json_is_integer(x) || + !y || !json_is_integer(y)) return; - printf("origin|%d|%d\n", - (int)json_integer_value(prop_origin_x), - (int)json_integer_value(prop_origin_y)); + printf("player-origin|%d|%d\n", + (int)json_integer_value(x), + (int)json_integer_value(y)); +} + +static void +write_player_sprite(const json_t *props) +{ + const json_t *sprite, *w, *h; + + sprite = find_property(props, "player-sprite"); + w = find_property(props, "player-sprite-w"); + h = find_property(props, "player-sprite-h"); + + if (!sprite || !json_is_string(sprite) || + !w || !json_is_integer(w) || + !h || !json_is_integer(h)) + return; + + printf("player-sprite|%d|%d|%s\n", + (int)json_integer_value(w), + (int)json_integer_value(h), + json_string_value(sprite) + ); } static void write_properties(const json_t *props) { - write_origin(props); + write_player_origin(props); + write_player_sprite(props); } static void