# HG changeset patch # User David Demelier # Date 1579116801 -3600 # Node ID 22a09a5ee47692ccbb40f08a46a5f70b649bf5f4 # Parent 3996f873a54b6ad950bc53f3b197303dcb21250e core: add better map check and unit tests diff -r 3996f873a54b -r 22a09a5ee476 .hgignore --- a/.hgignore Wed Jan 15 13:11:47 2020 +0100 +++ b/.hgignore Wed Jan 15 20:33:21 2020 +0100 @@ -13,8 +13,9 @@ \.o$ ^libmolko\.a$ ^molko(\.exe)?$ -^tests/test-color$ -^tests/test-error$ +^tests/test-color(\.exe)?$ +^tests/test-error(\.exe)?$ +^tests/test-map(\.exe)?$ ^tools/molko-map$ # doxygen stuff. diff -r 3996f873a54b -r 22a09a5ee476 Makefile --- a/Makefile Wed Jan 15 13:11:47 2020 +0100 +++ b/Makefile Wed Jan 15 20:33:21 2020 +0100 @@ -51,7 +51,8 @@ JANSSON_LDFLAGS=`pkg-config --libs jansson` TESTS= tests/test-color.c \ - tests/test-error.c + tests/test-error.c \ + tests/test-map.c TESTS_INCS= -I extern/libgreatest -I src ${SDL_CFLAGS} TESTS_LIBS= ${LIB} ${SDL_LDFLAGS} ${LDFLAGS} TESTS_OBJS= ${TESTS:.c=} diff -r 3996f873a54b -r 22a09a5ee476 src/main.c --- a/src/main.c Wed Jan 15 13:11:47 2020 +0100 +++ b/src/main.c Wed Jan 15 20:33:21 2020 +0100 @@ -36,6 +36,8 @@ (void)argc; (void)argv; +#if 0 + struct clock clock; struct map map; struct texture *guy; @@ -120,7 +122,6 @@ } } - map_move(&map, map.x + dx, map.y + dy); walksprite_update(&ws, elapsed); painter_clear(); map_draw(&map); @@ -128,6 +129,7 @@ painter_present(); delay(50); } +#endif return 0; } diff -r 3996f873a54b -r 22a09a5ee476 src/map.c --- a/src/map.c Wed Jan 15 13:11:47 2020 +0100 +++ b/src/map.c Wed Jan 15 20:33:21 2020 +0100 @@ -27,6 +27,7 @@ #include "image.h" #include "texture.h" #include "sprite.h" +#include "sys.h" #include "painter.h" #include @@ -58,6 +59,7 @@ amount = map->width * map->height; current = 0; + if (!(layer->tiles = calloc(amount, sizeof (uint16_t)))) return; @@ -69,12 +71,12 @@ 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))) + if (map->tilewidth == 0 || map->tileheight == 0) + return; + if (!(map->tileset = image_openf(sys_datapath("tilesets/%s", filename)))) return; sprite_init(&map->sprite, map->tileset, map->tilewidth, map->tileheight); @@ -99,6 +101,23 @@ parse_layer(map, line, fp); } +static bool +check(struct map *map) +{ + if (strlen(map->title) == 0) + return error_printf("map has no title"); + if (!map->tileset) + return error_printf("unable to open tileset"); + if (map->width == 0 || map->height == 0) + return error_printf("map has null sizes"); + if (map->tilewidth == 0 || map->tileheight == 0) + return error_printf("map has null tile sizes"); + if (!map->layers[0].tiles || !map->layers[1].tiles) + return error_printf("could not allocate data"); + + return true; +} + static void draw_layer(struct map *map, const struct map_layer *layer) { @@ -146,10 +165,10 @@ fclose(fp); - if (map->width == 0 || map->tilewidth == 0) - return error_printf("map width is null"); - if (map->height == 0 || map->tileheight == 0) - return error_printf("map height is null"); + if (!check(map)) { + map_close(map); + return false; + } size_t pw = map->width * map->tilewidth; size_t ph = map->height * map->tileheight; @@ -161,14 +180,13 @@ } void -map_draw(struct map *map) +map_draw(struct map *map, int srcx, int srcy) { - /* TODO: coordinates here */ /* TODO: remove window size here */ texture_draw_ex( map->picture, - map->x, - map->y, + srcx, + srcy, 1024, 576, 0, @@ -192,13 +210,6 @@ } void -map_view(struct map *map, uint64_t x, uint64_t y) -{ - map->x = x; - map->y = y; -} - -void map_close(struct map *map) { assert(map); @@ -210,4 +221,6 @@ free(map->layers[0].tiles); free(map->layers[1].tiles); + + memset(&map, 0, sizeof (struct map)); } diff -r 3996f873a54b -r 22a09a5ee476 src/map.h --- a/src/map.h Wed Jan 15 13:11:47 2020 +0100 +++ b/src/map.h Wed Jan 15 20:33:21 2020 +0100 @@ -51,8 +51,6 @@ struct texture *tileset; /*!< (RW) Tileset to use */ struct texture *picture; /*!< (RO) Map drawn into a picture */ struct sprite sprite; /*!< (RO) Sprite to render */ - uint64_t x; - uint64_t y; uint16_t width; /*!< (RO) Map width in cells */ uint16_t height; /*!< (RO) Map height in cells */ uint8_t tilewidth; /*!< (RO) Pixels per cell (width) */ @@ -77,9 +75,11 @@ * * \pre map != NULL * \param map the map to render + * \param srcx the x coordinate region + * \param srcy the y coordinate region */ void -map_draw(struct map *map); +map_draw(struct map *map, int srcx, int srcy); /** * Force map repaint on its texture. @@ -92,17 +92,6 @@ map_repaint(struct map *map); /** - * Move the origin of the picture rect to view. - * - * \param map the map - * \param x the x coordinate - * \param y the y coordinate - * \note This function may adjust the coordinates if needed - */ -void -map_view(struct map *map, uint64_t x, uint64_t y); - -/** * Close the map and its resources. * * \pre map != NULL diff -r 3996f873a54b -r 22a09a5ee476 tests/assets/maps/error-height.map --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/assets/maps/error-height.map Wed Jan 15 20:33:21 2020 +0100 @@ -0,0 +1,15 @@ +title|This map lacks height +width|2 +tilewidth|32 +tileheight|16 +tileset|sample-map.png +layer|background +0 +1 +2 +3 +layer|foreground +4 +5 +6 +7 diff -r 3996f873a54b -r 22a09a5ee476 tests/assets/maps/error-tileheight.map --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/assets/maps/error-tileheight.map Wed Jan 15 20:33:21 2020 +0100 @@ -0,0 +1,16 @@ +title|This map lacks tileheight +width|2 +height|2 +tilewidth|32 +tileset|sample-map.png +layer|background +0 +1 +2 +3 +layer|foreground +4 +5 +6 +7 + diff -r 3996f873a54b -r 22a09a5ee476 tests/assets/maps/error-tilewidth.map --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/assets/maps/error-tilewidth.map Wed Jan 15 20:33:21 2020 +0100 @@ -0,0 +1,16 @@ +title|This map lacks tilewidth +width|2 +height|2 +tileheight|16 +tileset|sample-map.png +layer|background +0 +1 +2 +3 +layer|foreground +4 +5 +6 +7 + diff -r 3996f873a54b -r 22a09a5ee476 tests/assets/maps/error-title.map --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/assets/maps/error-title.map Wed Jan 15 20:33:21 2020 +0100 @@ -0,0 +1,15 @@ +width|2 +height|2 +tilewidth|32 +tileheight|16 +tileset|sample-map.png +layer|background +0 +1 +2 +3 +layer|foreground +4 +5 +6 +7 diff -r 3996f873a54b -r 22a09a5ee476 tests/assets/maps/error-width.map --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/assets/maps/error-width.map Wed Jan 15 20:33:21 2020 +0100 @@ -0,0 +1,15 @@ +title|This map lacks width +height|2 +tilewidth|32 +tileheight|16 +tileset|sample-map.png +layer|background +0 +1 +2 +3 +layer|foreground +4 +5 +6 +7 diff -r 3996f873a54b -r 22a09a5ee476 tests/assets/maps/sample-map.map --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/assets/maps/sample-map.map Wed Jan 15 20:33:21 2020 +0100 @@ -0,0 +1,16 @@ +title|This is a test map +width|2 +height|2 +tilewidth|32 +tileheight|16 +tileset|sample-map.png +layer|background +0 +1 +2 +3 +layer|foreground +4 +5 +6 +7 diff -r 3996f873a54b -r 22a09a5ee476 tests/assets/tilesets/sample-map.png Binary file tests/assets/tilesets/sample-map.png has changed diff -r 3996f873a54b -r 22a09a5ee476 tests/test-map.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-map.c Wed Jan 15 20:33:21 2020 +0100 @@ -0,0 +1,142 @@ +/* + * test-map.c -- test map routines + * + * Copyright (c) 2020 David Demelier + * + * 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 + +#include +#include +#include +#include + +static void +setup(void *data) +{ + (void)data; + + if (!sys_init()) + error_fatal(); + if (!window_init("Test map", 100, 100)) + error_fatal(); +} + +static void +teardown(void *data) +{ + (void)data; + + window_close(); + sys_close(); +} + +TEST +sample(void) +{ + struct map map; + + ASSERT(map_open(&map, sys_datapath("maps/sample-map.map"))); + ASSERT_STR_EQ("This is a test map", map.title); + ASSERT_EQ(2, map.width); + ASSERT_EQ(2, map.height); + ASSERT_EQ(32, map.tilewidth); + ASSERT_EQ(16, map.tileheight); + ASSERT_EQ(0, map.layers[0].tiles[0]); + ASSERT_EQ(1, map.layers[0].tiles[1]); + ASSERT_EQ(2, map.layers[0].tiles[2]); + ASSERT_EQ(3, map.layers[0].tiles[3]); + ASSERT_EQ(4, map.layers[1].tiles[0]); + ASSERT_EQ(5, map.layers[1].tiles[1]); + ASSERT_EQ(6, map.layers[1].tiles[2]); + ASSERT_EQ(7, map.layers[1].tiles[3]); + PASS(); +} + +TEST +error_title(void) +{ + struct map map; + + ASSERT(!map_open(&map, sys_datapath("maps/error-title.map"))); + PASS(); +} + +TEST +error_width(void) +{ + struct map map; + + ASSERT(!map_open(&map, sys_datapath("maps/error-width.map"))); + PASS(); +} + +TEST +error_height(void) +{ + struct map map; + + ASSERT(!map_open(&map, sys_datapath("maps/error-height.map"))); + PASS(); +} + +TEST +error_tilewidth(void) +{ + struct map map; + + ASSERT(!map_open(&map, sys_datapath("maps/error-tilewidth.map"))); + PASS(); +} + +TEST +error_tileheight(void) +{ + struct map map; + + ASSERT(!map_open(&map, sys_datapath("maps/error-tileheight.map"))); + PASS(); +} + +SUITE(basics) +{ + SET_SETUP(setup, NULL); + SET_TEARDOWN(teardown, NULL); + RUN_TEST(sample); +} + +SUITE(errors) +{ + SET_SETUP(setup, NULL); + SET_TEARDOWN(teardown, NULL); + RUN_TEST(error_title); + RUN_TEST(error_width); + RUN_TEST(error_height); + RUN_TEST(error_tilewidth); + RUN_TEST(error_tileheight); +} + +GREATEST_MAIN_DEFS(); + +int +main(int argc, char **argv) +{ + GREATEST_MAIN_BEGIN(); + RUN_SUITE(basics); + RUN_SUITE(errors); + GREATEST_MAIN_END(); + + return 0; +}