Update tilemap tests for renderer backends

Migrate tilemap tests to pointer-based game globals and current loader signatures, initialize the renderer callback used by image comparisons, and refresh the character fixture schema. Preserve loaded tileset names by removing a duplicate heap allocation.

Co-authored-by: Codex (GPT-5) <noreply@openai.com>
This commit is contained in:
2026-07-29 18:25:36 -04:00
parent cf9ebb206f
commit 3854b33750
3 changed files with 96 additions and 69 deletions

View File

@@ -1,6 +1,9 @@
{
"name": "testcharacter",
"movementspeed": 1,
"speedtime": 1,
"speed_x": 0.20,
"speed_y": 0.20,
"acceleration_x": 0.20,
"acceleration_y": 0.20,
"sprite_mappings": [

View File

@@ -20,6 +20,8 @@ akerr_ErrorContext *test_tilemap_akgl_get_json_tilemap_property(void)
int propnum;
ATTEMPT {
gamemap = &_akgl_gamemap;
renderer = &_akgl_renderer;
CATCH(errctx, akgl_heap_next_string(&tmpstr));
snprintf(
(char *)&tmpstr->data,
@@ -85,32 +87,34 @@ akerr_ErrorContext *test_akgl_tilemap_compute_tileset_offsets(void)
10 // Tile 2 Y
};
int *comparison_ptrs[8] = {
&gamemap.tilesets[0].tile_offsets[0][0], // Tile 0 X
&gamemap.tilesets[0].tile_offsets[0][1], // Tile 0 Y
&gamemap.tilesets[0].tile_offsets[1][0], // Tile 1 X
&gamemap.tilesets[0].tile_offsets[1][1], // Tile 0 Y
&gamemap.tilesets[0].tile_offsets[2][0], // Tile 2 X
&gamemap.tilesets[0].tile_offsets[2][1], // Tile 2 Y
&gamemap.tilesets[0].tile_offsets[3][0], // Tile 3 X
&gamemap.tilesets[0].tile_offsets[3][0], // Tile 3 Y
&gamemap->tilesets[0].tile_offsets[0][0], // Tile 0 X
&gamemap->tilesets[0].tile_offsets[0][1], // Tile 0 Y
&gamemap->tilesets[0].tile_offsets[1][0], // Tile 1 X
&gamemap->tilesets[0].tile_offsets[1][1], // Tile 0 Y
&gamemap->tilesets[0].tile_offsets[2][0], // Tile 2 X
&gamemap->tilesets[0].tile_offsets[2][1], // Tile 2 Y
&gamemap->tilesets[0].tile_offsets[3][0], // Tile 3 X
&gamemap->tilesets[0].tile_offsets[3][1], // Tile 3 Y
};
int i = 0;
memset((void *)&gamemap, 0x00, sizeof(akgl_Tilemap));
gamemap.tilesets[0].tilecount = 4;
gamemap.tilesets[0].columns = 2;
gamemap.tilesets[0].firstgid = 1;
gamemap.tilesets[0].imageheight = 20;
gamemap.tilesets[0].imagewidth = 20;
gamemap.tilesets[0].tilecount = 4;
gamemap.tilesets[0].tileheight = 10;
gamemap.tilesets[0].tilewidth = 10;
gamemap.tilesets[0].spacing = 0;
gamemap.tilesets[0].margin = 0;
memset((void *)gamemap, 0x00, sizeof(akgl_Tilemap));
gamemap->tilesets[0].tilecount = 4;
gamemap->tilesets[0].columns = 2;
gamemap->tilesets[0].firstgid = 1;
gamemap->tilesets[0].imageheight = 20;
gamemap->tilesets[0].imagewidth = 20;
gamemap->tilesets[0].tilecount = 4;
gamemap->tilesets[0].tileheight = 10;
gamemap->tilesets[0].tilewidth = 10;
gamemap->tilesets[0].spacing = 0;
gamemap->tilesets[0].margin = 0;
PREPARE_ERROR(errctx);
ATTEMPT {
CATCH(errctx, akgl_tilemap_compute_tileset_offsets(&gamemap, 0));
gamemap = &_akgl_gamemap;
renderer = &_akgl_renderer;
CATCH(errctx, akgl_tilemap_compute_tileset_offsets(gamemap, 0));
// Tile 0 X offset
for ( i = 0; i < 8; i++ ) {
FAIL_NONZERO_BREAK(
@@ -139,15 +143,18 @@ akerr_ErrorContext *test_akgl_tilemap_load_layer_objects(void)
json_error_t errdata;
akgl_Actor *testactor;
memset((void *)&gamemap, 0x00, sizeof(akgl_Tilemap));
memset((void *)gamemap, 0x00, sizeof(akgl_Tilemap));
ATTEMPT {
gamemap = &_akgl_gamemap;
renderer = &_akgl_renderer;
CATCH(errctx, akgl_heap_next_string(&pathstr));
snprintf((char *)&pathstr->data, AKGL_MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), "assets/testmap.tmj");
doc = json_load_file((char *)&pathstr->data, 0, &errdata);
snprintf((char *)&pathstr->data, AKGL_MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), "assets");
FAIL_ZERO_BREAK(errctx, doc, AKERR_NULLPOINTER, "Failed to load testmap: %s", (char *)&errdata.text);
CATCH(errctx, akgl_get_json_array_value(doc, "layers", &layers));
CATCH(errctx, akgl_get_json_array_index_object(layers, 1, &objectlayer));
CATCH(errctx, akgl_tilemap_load_layer_objects(&gamemap, objectlayer, 1));
CATCH(errctx, akgl_tilemap_load_layer_objects(gamemap, objectlayer, 1, pathstr));
testactor = SDL_GetPointerProperty(AKGL_REGISTRY_ACTOR, "testactor", NULL);
FAIL_ZERO_BREAK(
@@ -186,21 +193,24 @@ akerr_ErrorContext *test_akgl_tilemap_load_layer_tile(void)
json_t *tiledata = NULL;
json_error_t errdata;
memset((void *)&gamemap, 0x00, sizeof(akgl_Tilemap));
memset((void *)gamemap, 0x00, sizeof(akgl_Tilemap));
ATTEMPT {
gamemap = &_akgl_gamemap;
renderer = &_akgl_renderer;
CATCH(errctx, akgl_heap_next_string(&pathstr));
snprintf((char *)&pathstr->data, AKGL_MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), "assets/testmap.tmj");
doc = json_load_file((char *)&pathstr->data, 0, &errdata);
snprintf((char *)&pathstr->data, AKGL_MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), "assets");
FAIL_ZERO_BREAK(errctx, doc, AKERR_NULLPOINTER, "Failed to load testmap: %s", (char *)&errdata.text);
CATCH(errctx, akgl_get_json_array_value(doc, "layers", &layers));
CATCH(errctx, akgl_get_json_array_index_object(layers, 0, &tilelayer));
CATCH(errctx, akgl_get_json_array_value(tilelayer, "data", &tiledata));
CATCH(errctx, akgl_tilemap_load_layer_tile(&gamemap, tilelayer, 0));
if ( (gamemap.layers[0].data[0] != 1) ||
(gamemap.layers[0].data[1] != 2) ||
(gamemap.layers[0].data[2] != 3) ||
(gamemap.layers[0].data[3] != 4) ) {
CATCH(errctx, akgl_tilemap_load_layer_tile(gamemap, tilelayer, 0, pathstr));
if ( (gamemap->layers[0].data[0] != 1) ||
(gamemap->layers[0].data[1] != 2) ||
(gamemap->layers[0].data[2] != 3) ||
(gamemap->layers[0].data[3] != 4) ) {
FAIL_BREAK(errctx, AKERR_VALUE, "Test tilemap layer 0 tiles loaded with incorrect values (check gdb)");
}
} CLEANUP {
@@ -223,58 +233,61 @@ akerr_ErrorContext *test_akgl_tilemap_load_layers(void)
json_error_t errdata;
int i = 0;
memset((void *)&gamemap, 0x00, sizeof(akgl_Tilemap));
memset((void *)gamemap, 0x00, sizeof(akgl_Tilemap));
ATTEMPT {
gamemap = &_akgl_gamemap;
renderer = &_akgl_renderer;
CATCH(errctx, akgl_heap_next_string(&pathstr));
snprintf((char *)&pathstr->data, AKGL_MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), "assets/testmap.tmj");
doc = json_load_file((char *)&pathstr->data, 0, &errdata);
snprintf((char *)&pathstr->data, AKGL_MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), "assets");
FAIL_ZERO_BREAK(errctx, doc, AKERR_NULLPOINTER, "Failed to load testmap: %s", (char *)&errdata.text);
CATCH(errctx, akgl_tilemap_load_layers(&gamemap, doc));
CATCH(errctx, akgl_tilemap_load_layers(gamemap, doc, pathstr));
FAIL_NONZERO_BREAK(
errctx,
(gamemap.numlayers != 3),
(gamemap->numlayers != 3),
AKERR_VALUE,
"Map layer count incorrect"
);
for ( i = 0; i < gamemap.numlayers; i++ ) {
if ( (gamemap.layers[i].opacity != 1) ||
(gamemap.layers[i].visible != true) ||
(gamemap.layers[i].id != (i + 1)) ||
(gamemap.layers[i].x != 0) ||
(gamemap.layers[i].y != 0) ) {
for ( i = 0; i < gamemap->numlayers; i++ ) {
if ( (gamemap->layers[i].opacity != 1) ||
(gamemap->layers[i].visible != true) ||
(gamemap->layers[i].id != (i + 1)) ||
(gamemap->layers[i].x != 0) ||
(gamemap->layers[i].y != 0) ) {
FAIL(errctx, AKERR_VALUE, "Map layer data loaded incorrectly (see gdb)");
goto _test_akgl_tilemap_load_layers_cleanup;
}
}
// Layer 2 should have 1 object loaded
if ( (gamemap.layers[1].objects[0].actorptr != SDL_GetPointerProperty(AKGL_REGISTRY_ACTOR, "testactor", NULL)) ||
(gamemap.layers[1].objects[1].name[0] != '\0' ) ||
(gamemap.layers[1].objects[1].id != 0) ) {
if ( (gamemap->layers[1].objects[0].actorptr != SDL_GetPointerProperty(AKGL_REGISTRY_ACTOR, "testactor", NULL)) ||
(gamemap->layers[1].objects[1].name[0] != '\0' ) ||
(gamemap->layers[1].objects[1].id != 0) ) {
FAIL_BREAK(errctx, AKERR_VALUE, "Map layer 2 should have 1 loaded object (testactor) and nothing else (see gdb)");
}
// Layer 1 and 3 should have no objects
for ( i = 0; i < AKGL_TILEMAP_MAX_OBJECTS_PER_LAYER ; i++ ) {
if ( gamemap.layers[0].objects[i].id != 0 ) {
if ( gamemap->layers[0].objects[i].id != 0 ) {
FAIL(errctx, AKERR_VALUE, "Map layers 1 and 3 should have no objects loaded but found objects");
goto _test_akgl_tilemap_load_layers_cleanup;
}
}
for ( i = 0; i < AKGL_TILEMAP_MAX_OBJECTS_PER_LAYER ; i++ ) {
if ( gamemap.layers[2].objects[i].id != 0 ) {
if ( gamemap->layers[2].objects[i].id != 0 ) {
FAIL(errctx, AKERR_VALUE, "Map layers 1 and 3 should have no objects loaded but found objects");
goto _test_akgl_tilemap_load_layers_cleanup;
}
}
// Layers 1 and 3 should have tile data
if ( (gamemap.layers[0].data[0] != 1) ||
(gamemap.layers[0].data[1] != 2) ||
(gamemap.layers[0].data[2] != 3) ||
(gamemap.layers[0].data[3] != 4) ||
(gamemap.layers[2].data[0] != 0) ||
(gamemap.layers[2].data[1] != 5) ||
(gamemap.layers[2].data[2] != 0) ||
(gamemap.layers[2].data[3] != 6)
if ( (gamemap->layers[0].data[0] != 1) ||
(gamemap->layers[0].data[1] != 2) ||
(gamemap->layers[0].data[2] != 3) ||
(gamemap->layers[0].data[3] != 4) ||
(gamemap->layers[2].data[0] != 0) ||
(gamemap->layers[2].data[1] != 5) ||
(gamemap->layers[2].data[2] != 0) ||
(gamemap->layers[2].data[3] != 6)
) {
FAIL_BREAK(errctx, AKERR_VALUE, "Map layers 1 and 3 should have tile data but it is incorrect");
}
@@ -299,40 +312,43 @@ akerr_ErrorContext *test_akgl_tilemap_load_tilesets(void)
json_error_t errdata;
SDL_Texture *image = NULL;
memset((void *)&gamemap, 0x00, sizeof(akgl_Tilemap));
memset((void *)gamemap, 0x00, sizeof(akgl_Tilemap));
ATTEMPT {
gamemap = &_akgl_gamemap;
renderer = &_akgl_renderer;
CATCH(errctx, akgl_heap_next_string(&pathstr));
snprintf((char *)&pathstr->data, AKGL_MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), "assets/testmap.tmj");
doc = json_load_file((char *)&pathstr->data, 0, &errdata);
snprintf((char *)&pathstr->data, AKGL_MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), "assets");
FAIL_ZERO_BREAK(errctx, doc, AKERR_NULLPOINTER, "Failed to load testmap: %s", (char *)&errdata.text);
CATCH(errctx, akgl_tilemap_load_tilesets(&gamemap, doc));
FAIL_NONZERO_BREAK(errctx, (gamemap.numtilesets != 1), AKERR_VALUE, "Incorrect number of tilesets loaded for map");
if ( (gamemap.tilesets[0].columns != 48 ) ||
(gamemap.tilesets[0].firstgid != 1) ||
(gamemap.tilesets[0].imageheight != 576) ||
(gamemap.tilesets[0].imagewidth != 768) ||
(gamemap.tilesets[0].margin != 0) ||
(gamemap.tilesets[0].spacing != 0) ||
(gamemap.tilesets[0].tilecount != 1728) ||
(gamemap.tilesets[0].tileheight != 16) ||
(gamemap.tilesets[0].tilewidth != 16) ) {
CATCH(errctx, akgl_tilemap_load_tilesets(gamemap, doc, pathstr));
FAIL_NONZERO_BREAK(errctx, (gamemap->numtilesets != 1), AKERR_VALUE, "Incorrect number of tilesets loaded for map");
if ( (gamemap->tilesets[0].columns != 48 ) ||
(gamemap->tilesets[0].firstgid != 1) ||
(gamemap->tilesets[0].imageheight != 576) ||
(gamemap->tilesets[0].imagewidth != 768) ||
(gamemap->tilesets[0].margin != 0) ||
(gamemap->tilesets[0].spacing != 0) ||
(gamemap->tilesets[0].tilecount != 1728) ||
(gamemap->tilesets[0].tileheight != 16) ||
(gamemap->tilesets[0].tilewidth != 16) ) {
FAIL_BREAK(errctx, AKERR_VALUE, "Tileset loaded with incorrect values");
}
FAIL_NONZERO_BREAK(
errctx,
strcmp((char *)&gamemap.tilesets[0].name, "World_A1"),
strcmp((char *)&gamemap->tilesets[0].name, "World_A1"),
AKERR_VALUE,
"Tileset loaded with incorrect name");
snprintf((char *)&pathstr->data, AKGL_MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), "assets/World_A1.png");
image = IMG_LoadTexture(renderer, (char *)&pathstr->data);
image = IMG_LoadTexture(renderer->sdl_renderer, (char *)&pathstr->data);
FAIL_ZERO_BREAK(errctx, image, AKGL_ERR_SDL, "Failed to load comparison image");
CATCH(
errctx,
akgl_render_and_compare(
gamemap.tilesets[0].texture,
gamemap->tilesets[0].texture,
image,
0, 0, 768, 576,
"test_akgl_tilemap_loaded_tileset.png")
@@ -354,10 +370,12 @@ akerr_ErrorContext *test_akgl_tilemap_load(void)
{
PREPARE_ERROR(errctx);
memset((void *)&gamemap, 0x00, sizeof(akgl_Tilemap));
memset((void *)gamemap, 0x00, sizeof(akgl_Tilemap));
ATTEMPT {
CATCH(errctx, akgl_tilemap_load("assets/testmap.tmj", &gamemap));
gamemap = &_akgl_gamemap;
renderer = &_akgl_renderer;
CATCH(errctx, akgl_tilemap_load("assets/testmap.tmj", gamemap));
} CLEANUP {
} PROCESS(errctx) {
} FINISH(errctx, true);
@@ -369,6 +387,8 @@ akerr_ErrorContext *test_akgl_tilemap_draw(void)
PREPARE_ERROR(errctx);
ATTEMPT {
gamemap = &_akgl_gamemap;
renderer = &_akgl_renderer;
} CLEANUP {
} PROCESS(errctx) {
} FINISH(errctx, true);
@@ -381,6 +401,8 @@ akerr_ErrorContext *test_akgl_tilemap_draw_tileset(void)
PREPARE_ERROR(errctx);
ATTEMPT {
gamemap = &_akgl_gamemap;
renderer = &_akgl_renderer;
} CLEANUP {
} PROCESS(errctx) {
} FINISH(errctx, true);
@@ -392,15 +414,18 @@ int main(void)
PREPARE_ERROR(errctx);
ATTEMPT {
gamemap = &_akgl_gamemap;
renderer = &_akgl_renderer;
SDL_SetAppMetadata("SDL3-GameTest", "0.1", "net.aklabs.sdl3-gametest");
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO )) {
FAIL_BREAK(errctx, AKGL_ERR_SDL, "Couldn't initialize SDL: %s", SDL_GetError());
}
if (!SDL_CreateWindowAndRenderer("net/aklabs/libakgl/test_sprite", 768, 576, 0, &window, &renderer)) {
if (!SDL_CreateWindowAndRenderer("net/aklabs/libakgl/test_sprite", 768, 576, 0, &window, &renderer->sdl_renderer)) {
FAIL_BREAK(errctx, AKGL_ERR_SDL, "Couldn't create window/renderer: %s", SDL_GetError());
}
renderer->draw_texture = &akgl_render_2d_draw_texture;
CATCH(errctx, akgl_registry_init());
CATCH(errctx, akgl_heap_init());