Repair embedded dependency build and test setup

Isolate vendored test registration, namespace project error codes, and update dependency revisions. Fix mutable sprite path handling, out-of-tree fixtures, and charviewer initialization while documenting the outstanding character-to-sprite refcount bug.

Co-authored-by: Codex (GPT-5) <noreply@openai.com>
This commit is contained in:
2026-07-29 18:01:05 -04:00
parent 74867ea82e
commit cf9ebb206f
22 changed files with 209 additions and 64 deletions

4
.gitmodules vendored
View File

@@ -15,10 +15,10 @@
url = git@github.com:libsdl-org/SDL_ttf.git url = git@github.com:libsdl-org/SDL_ttf.git
[submodule "deps/libsdlerror"] [submodule "deps/libsdlerror"]
path = deps/libakerror path = deps/libakerror
url = https://source.home.aklabs.net/andrew/libsdlerror.git url = https://source.starfort.tech/andrew/libakerror.git
[submodule "deps/libakstdlib"] [submodule "deps/libakstdlib"]
path = deps/libakstdlib path = deps/libakstdlib
url = https://source.home.aklabs.net/andrew/libakstdlib.git url = https://source.starfort.tech/andrew/libakstdlib.git
[submodule "deps/jansson"] [submodule "deps/jansson"]
path = deps/jansson path = deps/jansson
url = git@github.com:akheron/jansson.git url = git@github.com:akheron/jansson.git

44
AGENTS.md Normal file
View File

@@ -0,0 +1,44 @@
# Repository Guidelines
## Project Structure & Module Organization
This is a C library intended to support the development of video games. Public C headers live in `include/akgl/`; keep declarations there aligned with their implementations in `src/`. Tests are standalone C programs under `tests/`, with JSON, image, and map fixtures in `tests/assets/`. The `util/` directory contains the `charviewer` utility and its sample assets. Third-party and companion libraries are vendored in `deps/`. Treat `build/`, generated `akgl.pc` files, and `include/akgl/SDL_GameControllerDB.h` as build outputs rather than hand-maintained source.
## Build, Test, and Development Commands
Configure an out-of-tree development build:
```sh
cmake -S . -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo
```
Build all library, utility, and test targets:
```sh
cmake --build build --parallel
```
Run the complete test suite with failure details:
```sh
ctest --test-dir build --output-on-failure
```
Run one test while iterating, for example `ctest --test-dir build -R sprite --output-on-failure`. The `rebuild.sh` script also installs into a developer-specific `/home/andrew/local` prefix and removes existing outputs; prefer the portable commands above unless that exact workflow is intended.
## Coding Style & Naming Conventions
Follow the surrounding C style: braces on the next line for function bodies, spaces inside control-flow parentheses, and short, focused functions. Preserve the indentation of the file being edited; older files contain both spaces and tabs. Public symbols use the `akgl_` prefix, public types use `akgl_TypeName`, and constants/macros use `AKGL_UPPER_SNAKE_CASE`. Name matching header/source pairs by feature, such as `include/akgl/sprite.h` and `src/sprite.c`. No repository-wide formatter or linter is configured, so avoid unrelated formatting churn.
## Rules
- Add yourself (agent program name, model name and version) as a co-author on every commit message
- Avoid dynamic memory allocation. Use the `akgl_heap_*` methods to retrieve necessary objects at runtime, and to release them when done. If the akgl heap facilities don't provide the kind of object needed, create a new heap layer to support that type of object.
## Testing Guidelines
Tests use simple executable return codes and are registered through CTest in `CMakeLists.txt`; there is no declared coverage threshold. Add focused tests as `tests/<feature>.c`, create a matching `test_<feature>` target, and register it with `add_test`. Put reusable fixtures in `tests/assets/` and keep paths compatible with tests launched from the build tree.
## Commit & Pull Request Guidelines
Recent commits use concise, imperative summaries such as `Fix a scale bug...` and often explain related changes in one sentence. Keep each commit scoped and describe user-visible behavior. Pull requests should summarize the change, identify affected modules, list the CMake/CTest commands run, and link relevant issues. Include screenshots only for rendering, map, or `charviewer` changes.

View File

@@ -4,7 +4,25 @@ project(akgl LANGUAGES C)
include(CTest) include(CTest)
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
# Vendored projects own their test suites. Suppress their CTest registration
# while embedded so the top-level suite contains only targets built here.
set(AKGL_SUPPRESS_DEPENDENCY_TESTS TRUE)
function(add_test)
if(NOT AKGL_SUPPRESS_DEPENDENCY_TESTS)
_add_test(${ARGV})
endif()
endfunction()
function(set_tests_properties)
if(NOT AKGL_SUPPRESS_DEPENDENCY_TESTS)
_set_tests_properties(${ARGV})
endif()
endfunction()
set(JANSSON_WITHOUT_TESTS ON CACHE BOOL "Do not build vendored Jansson tests" FORCE)
set(JANSSON_EXAMPLES OFF CACHE BOOL "Do not build vendored Jansson examples" FORCE)
set(JANSSON_BUILD_DOCS OFF CACHE BOOL "Do not build vendored Jansson docs" FORCE)
add_subdirectory(deps/jansson EXCLUDE_FROM_ALL) add_subdirectory(deps/jansson EXCLUDE_FROM_ALL)
add_subdirectory(deps/libakerror EXCLUDE_FROM_ALL) add_subdirectory(deps/libakerror EXCLUDE_FROM_ALL)
add_subdirectory(deps/libakstdlib EXCLUDE_FROM_ALL) add_subdirectory(deps/libakstdlib EXCLUDE_FROM_ALL)
@@ -13,6 +31,13 @@ add_subdirectory(deps/SDL_image EXCLUDE_FROM_ALL)
add_subdirectory(deps/SDL_mixer EXCLUDE_FROM_ALL) add_subdirectory(deps/SDL_mixer EXCLUDE_FROM_ALL)
add_subdirectory(deps/SDL_ttf EXCLUDE_FROM_ALL) add_subdirectory(deps/SDL_ttf EXCLUDE_FROM_ALL)
# Reserve error-name table entries for libakgl-specific status codes.
target_compile_definitions(akerror PUBLIC
AKERR_MAX_ERR_VALUE=256
)
set(AKGL_SUPPRESS_DEPENDENCY_TESTS FALSE)
else() else()
find_package(PkgConfig REQUIRED) find_package(PkgConfig REQUIRED)
@@ -48,6 +73,11 @@ set(libdir "\${exec_prefix}/lib")
set(includedir "\${prefix}/include") set(includedir "\${prefix}/include")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/akgl.pc.in ${CMAKE_CURRENT_BINARY_DIR}/akgl.pc @ONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/akgl.pc.in ${CMAKE_CURRENT_BINARY_DIR}/akgl.pc @ONLY)
# Tests use both relative paths and SDL_GetBasePath(), so stage fixtures beside
# test executables in every out-of-tree build.
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/tests/assets"
DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
add_custom_command( add_custom_command(
OUTPUT ${GAMECONTROLLERDB_H} OUTPUT ${GAMECONTROLLERDB_H}
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/mkcontrollermappings.sh ${CMAKE_CURRENT_SOURCE_DIR} COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/mkcontrollermappings.sh ${CMAKE_CURRENT_SOURCE_DIR}
@@ -100,6 +130,11 @@ add_test(NAME tilemap COMMAND test_tilemap)
add_test(NAME util COMMAND test_util) add_test(NAME util COMMAND test_util)
add_test(NAME semver_unit COMMAND test_semver_unit) add_test(NAME semver_unit COMMAND test_semver_unit)
set_tests_properties(
actor bitmasks character registry sprite staticstring tilemap util semver_unit
PROPERTIES WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/tests"
)
# Specify include directories for the library's headers (if applicable) # Specify include directories for the library's headers (if applicable)
target_include_directories(akgl PUBLIC target_include_directories(akgl PUBLIC
include/ include/

15
TODO.md Normal file
View File

@@ -0,0 +1,15 @@
# TODO
1. **Make character-to-sprite state bindings release their references symmetrically.**
`akgl_character_sprite_add()` increments the sprite refcount for every state-map
binding, but no corresponding removal API exists. Replacing a state binding
also leaves the previous sprite's refcount incremented. When
`akgl_heap_release_character()` drops the character refcount to zero, it clears
the character registry entry and zeroes the structure without enumerating
`state_sprites`, decrementing the bound sprites, or destroying the SDL property
map. Implement binding removal/replacement so each removed binding releases
exactly one sprite reference. On final character release, enumerate every
remaining binding (the existing `akgl_character_state_sprites_iterate()` release
path may be reusable), release each reference, destroy `state_sprites`, and then
clear the character. Add tests for removal, replacement, duplicate sprite
bindings across multiple states, and final character release.

View File

@@ -12,7 +12,10 @@
#define RESTORE_GCC_WARNINGS \ #define RESTORE_GCC_WARNINGS \
_Pragma("GCC diagnostic pop") _Pragma("GCC diagnostic pop")
#define AKGL_ERR_SDL AKERR_LAST_ERRNO_VALUE + 1 #define AKGL_ERR_SDL (AKERR_LAST_ERRNO_VALUE + 18)
#define AKGL_ERR_LOGICINTERRUPT AKERR_LAST_ERRNO_VALUE + 2 #define AKGL_ERR_REGISTRY (AKERR_LAST_ERRNO_VALUE + 19)
#define AKGL_ERR_HEAP (AKERR_LAST_ERRNO_VALUE + 20)
#define AKGL_ERR_BEHAVIOR (AKERR_LAST_ERRNO_VALUE + 21)
#define AKGL_ERR_LOGICINTERRUPT (AKERR_LAST_ERRNO_VALUE + 22)
#endif // _ERROR_H_ #endif // _ERROR_H_

View File

@@ -274,6 +274,36 @@ akerr_ErrorContext *akgl_actor_add_child(akgl_Actor *obj, akgl_Actor *child)
FAIL_RETURN(errctx, AKERR_OUTOFBOUNDS, "Parent object has no remaining child slots left"); FAIL_RETURN(errctx, AKERR_OUTOFBOUNDS, "Parent object has no remaining child slots left");
} }
void akgl_registry_iterate_actor(void *userdata, SDL_PropertiesID registry, const char *name)
{
PREPARE_ERROR(errctx);
akgl_Iterator *opflags = (akgl_Iterator *)userdata;
akgl_Actor *obj = NULL;
ATTEMPT {
FAIL_ZERO_BREAK(errctx, name, AKERR_NULLPOINTER, "registry_iterate_actor received NULL property name");
FAIL_ZERO_BREAK(errctx, opflags, AKERR_NULLPOINTER, "received NULL iterator flags");
obj = SDL_GetPointerProperty(registry, name, NULL);
FAIL_ZERO_BREAK(errctx, obj, AKERR_KEY, "registry_iterate_actor received property name that was not in the registry");
if (AKGL_BITMASK_HAS(opflags->flags, AKGL_ITERATOR_OP_LAYERMASK) && obj->layer != opflags->layerid) {
break;
}
if (AKGL_BITMASK_HAS(opflags->flags, AKGL_ITERATOR_OP_UPDATE)) {
CATCH(errctx, obj->updatefunc(obj));
}
if (AKGL_BITMASK_HAS(opflags->flags, AKGL_ITERATOR_OP_TILEMAPSCALE)) {
CATCH(errctx, akgl_tilemap_scale_actor(gamemap, obj));
} else {
obj->scale = 1.0;
}
if (AKGL_BITMASK_HAS(opflags->flags, AKGL_ITERATOR_OP_RENDER)) {
CATCH(errctx, obj->renderfunc(obj));
}
} CLEANUP {
} PROCESS(errctx) {
} FINISH_NORETURN(errctx);
}
akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_left_on(akgl_Actor *obj, SDL_Event *event) akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_left_on(akgl_Actor *obj, SDL_Event *event)
{ {
PREPARE_ERROR(errctx); PREPARE_ERROR(errctx);

View File

@@ -277,7 +277,7 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_controller_default(int controlmapid, cha
controlmap->jsid = jsid; controlmap->jsid = jsid;
controlmap->target = SDL_GetPointerProperty(AKGL_REGISTRY_ACTOR, actorname, NULL); controlmap->target = SDL_GetPointerProperty(AKGL_REGISTRY_ACTOR, actorname, NULL);
FAIL_ZERO_BREAK(errctx, controlmap->target, AKERR_REGISTRY, "Actor %s not found in registry", actorname); FAIL_ZERO_BREAK(errctx, controlmap->target, AKGL_ERR_REGISTRY, "Actor %s not found in registry", actorname);
// ---- KEYBOARD CONTROLS ---- // ---- KEYBOARD CONTROLS ----

View File

@@ -20,6 +20,10 @@ akerr_ErrorContext *akgl_heap_init()
PREPARE_ERROR(errctx); PREPARE_ERROR(errctx);
int i = 0; int i = 0;
akerr_name_for_status(AKGL_ERR_SDL, "SDL Error"); akerr_name_for_status(AKGL_ERR_SDL, "SDL Error");
akerr_name_for_status(AKGL_ERR_REGISTRY, "Registry Error");
akerr_name_for_status(AKGL_ERR_HEAP, "Heap Error");
akerr_name_for_status(AKGL_ERR_BEHAVIOR, "Behavior Error");
akerr_name_for_status(AKGL_ERR_LOGICINTERRUPT, "Logic Interrupt");
PASS(errctx, akgl_heap_init_actor()); PASS(errctx, akgl_heap_init_actor());
for ( i = 0; i < AKGL_MAX_HEAP_SPRITE; i++) { for ( i = 0; i < AKGL_MAX_HEAP_SPRITE; i++) {
memset(&HEAP_SPRITE[i], 0x00, sizeof(akgl_Sprite)); memset(&HEAP_SPRITE[i], 0x00, sizeof(akgl_Sprite));
@@ -55,7 +59,7 @@ akerr_ErrorContext *akgl_heap_next_actor(akgl_Actor **dest)
*dest = &HEAP_ACTOR[i]; *dest = &HEAP_ACTOR[i];
SUCCEED_RETURN(errctx); SUCCEED_RETURN(errctx);
} }
FAIL_RETURN(errctx, AKERR_HEAP, "Unable to find unused actor on the heap"); FAIL_RETURN(errctx, AKGL_ERR_HEAP, "Unable to find unused actor on the heap");
} }
akerr_ErrorContext *akgl_heap_next_sprite(akgl_Sprite **dest) akerr_ErrorContext *akgl_heap_next_sprite(akgl_Sprite **dest)
@@ -68,7 +72,7 @@ akerr_ErrorContext *akgl_heap_next_sprite(akgl_Sprite **dest)
*dest = &HEAP_SPRITE[i]; *dest = &HEAP_SPRITE[i];
SUCCEED_RETURN(errctx); SUCCEED_RETURN(errctx);
} }
FAIL_RETURN(errctx, AKERR_HEAP, "Unable to find unused sprite on the heap"); FAIL_RETURN(errctx, AKGL_ERR_HEAP, "Unable to find unused sprite on the heap");
} }
akerr_ErrorContext *akgl_heap_next_spritesheet(akgl_SpriteSheet **dest) akerr_ErrorContext *akgl_heap_next_spritesheet(akgl_SpriteSheet **dest)
@@ -81,7 +85,7 @@ akerr_ErrorContext *akgl_heap_next_spritesheet(akgl_SpriteSheet **dest)
*dest = &HEAP_SPRITESHEET[i]; *dest = &HEAP_SPRITESHEET[i];
SUCCEED_RETURN(errctx); SUCCEED_RETURN(errctx);
} }
FAIL_RETURN(errctx, AKERR_HEAP, "Unable to find unused spritesheet on the heap"); FAIL_RETURN(errctx, AKGL_ERR_HEAP, "Unable to find unused spritesheet on the heap");
} }
akerr_ErrorContext *akgl_heap_next_character(akgl_Character **dest) akerr_ErrorContext *akgl_heap_next_character(akgl_Character **dest)
@@ -94,7 +98,7 @@ akerr_ErrorContext *akgl_heap_next_character(akgl_Character **dest)
*dest = &HEAP_CHARACTER[i]; *dest = &HEAP_CHARACTER[i];
SUCCEED_RETURN(errctx); SUCCEED_RETURN(errctx);
} }
FAIL_RETURN(errctx, AKERR_HEAP, "Unable to find unused character on the heap"); FAIL_RETURN(errctx, AKGL_ERR_HEAP, "Unable to find unused character on the heap");
} }
akerr_ErrorContext *akgl_heap_next_string(akgl_String **dest) akerr_ErrorContext *akgl_heap_next_string(akgl_String **dest)
@@ -108,7 +112,7 @@ akerr_ErrorContext *akgl_heap_next_string(akgl_String **dest)
HEAP_STRING[i].refcount += 1; HEAP_STRING[i].refcount += 1;
SUCCEED_RETURN(errctx); SUCCEED_RETURN(errctx);
} }
FAIL_RETURN(errctx, AKERR_HEAP, "Unable to find unused string on the heap"); FAIL_RETURN(errctx, AKGL_ERR_HEAP, "Unable to find unused string on the heap");
} }
akerr_ErrorContext *akgl_heap_release_actor(akgl_Actor *ptr) akerr_ErrorContext *akgl_heap_release_actor(akgl_Actor *ptr)

View File

@@ -58,7 +58,7 @@ static akerr_ErrorContext *akgl_sprite_load_json_spritesheet(json_t *json, akgl_
if ( *sheet == NULL ) { if ( *sheet == NULL ) {
CATCH(errctx, akgl_heap_next_spritesheet(sheet)); CATCH(errctx, akgl_heap_next_spritesheet(sheet));
CATCH(errctx, akgl_get_json_integer_value((json_t *)spritesheet_json, "frame_width", &ss_frame_width)); CATCH(errctx, akgl_get_json_integer_value((json_t *)spritesheet_json, "frame_width", &ss_frame_width));
CATCH(errctx, akgl_get_json_integer_value((json_t *)spritesheet_json, "frame_height", &ss_frame_width)); CATCH(errctx, akgl_get_json_integer_value((json_t *)spritesheet_json, "frame_height", &ss_frame_height));
CATCH(errctx, CATCH(errctx,
akgl_spritesheet_initialize( akgl_spritesheet_initialize(
(akgl_SpriteSheet *)*sheet, (akgl_SpriteSheet *)*sheet,
@@ -85,12 +85,20 @@ akerr_ErrorContext *akgl_sprite_load_json(char *filename)
akgl_Sprite *obj = NULL; akgl_Sprite *obj = NULL;
akgl_SpriteSheet *sheet = NULL; akgl_SpriteSheet *sheet = NULL;
akgl_String *spritename = NULL; akgl_String *spritename = NULL;
//string *tmpstr = NULL; akgl_String *filename_copy = NULL;
int i = 0; int i = 0;
FAIL_ZERO_RETURN(errctx, filename, AKERR_NULLPOINTER, "Received null filename"); FAIL_ZERO_RETURN(errctx, filename, AKERR_NULLPOINTER, "Received null filename");
ATTEMPT { ATTEMPT {
CATCH(errctx, akgl_heap_next_sprite(&obj)); CATCH(errctx, akgl_heap_next_sprite(&obj));
CATCH(errctx, akgl_heap_next_string(&filename_copy));
FAIL_NONZERO_BREAK(
errctx,
strlen(filename) >= AKGL_MAX_STRING_LENGTH,
AKERR_OUTOFBOUNDS,
"Sprite filename exceeds temporary string capacity"
);
SDL_strlcpy(filename_copy->data, filename, AKGL_MAX_STRING_LENGTH);
//CATCH(errctx, akgl_heap_next_string(&tmpstr)); //CATCH(errctx, akgl_heap_next_string(&tmpstr));
//CATCH(errctx, akgl_string_initialize(tmpstr, NULL)); //CATCH(errctx, akgl_string_initialize(tmpstr, NULL));
CATCH(errctx, akgl_heap_next_string(&spritename)); CATCH(errctx, akgl_heap_next_string(&spritename));
@@ -105,7 +113,7 @@ akerr_ErrorContext *akgl_sprite_load_json(char *filename)
"Error while loading sprite from %s on line %d: %s", filename, error.line, error.text "Error while loading sprite from %s on line %d: %s", filename, error.line, error.text
); );
CATCH(errctx, akgl_sprite_load_json_spritesheet((json_t *)json, &sheet, dirname(filename))); CATCH(errctx, akgl_sprite_load_json_spritesheet((json_t *)json, &sheet, dirname(filename_copy->data)));
CATCH(errctx, akgl_get_json_string_value((json_t *)json, "name", &spritename)); CATCH(errctx, akgl_get_json_string_value((json_t *)json, "name", &spritename));
CATCH(errctx, CATCH(errctx,
akgl_sprite_initialize( akgl_sprite_initialize(
@@ -132,6 +140,7 @@ akerr_ErrorContext *akgl_sprite_load_json(char *filename)
IGNORE(akgl_heap_release_spritesheet(sheet)); IGNORE(akgl_heap_release_spritesheet(sheet));
} }
IGNORE(akgl_heap_release_string(spritename)); IGNORE(akgl_heap_release_string(spritename));
IGNORE(akgl_heap_release_string(filename_copy));
//IGNORE(akgl_heap_release_string(tmpstr)); //IGNORE(akgl_heap_release_string(tmpstr));
} PROCESS(errctx) { } PROCESS(errctx) {
} FINISH(errctx, true); } FINISH(errctx, true);

View File

@@ -2,6 +2,7 @@
handle_unhandled_error(errctx); handle_unhandled_error(errctx);
#include <akerror.h> #include <akerror.h>
#include <akgl/error.h>
#define UNHANDLED_ERROR_EXIT 0 #define UNHANDLED_ERROR_EXIT 0
#define UNHANDLED_ERROR_SET 1 #define UNHANDLED_ERROR_SET 1
@@ -42,7 +43,7 @@ akerr_ErrorContext *akgl_actor_update_noop(akgl_Actor *obj)
// Currently the renderer assumes there is a global variable named `renderer` // Currently the renderer assumes there is a global variable named `renderer`
int akgl_actor_rendered; int akgl_actor_rendered;
akerr_ErrorContext *akgl_actor_render_noop(akgl_Actor *obj, SDL_Renderer *r) akerr_ErrorContext *akgl_actor_render_noop(akgl_Actor *obj)
{ {
PREPARE_ERROR(errctx); PREPARE_ERROR(errctx);
akgl_actor_rendered = 1; akgl_actor_rendered = 1;
@@ -129,13 +130,13 @@ akerr_ErrorContext *test_registry_actor_iterator_updaterender(void)
FAIL_ZERO_BREAK( FAIL_ZERO_BREAK(
unhandled_error_context, unhandled_error_context,
akgl_actor_updated, akgl_actor_updated,
AKERR_BEHAVIOR, AKGL_ERR_BEHAVIOR,
"actor->updatefunc not called by the iterator" "actor->updatefunc not called by the iterator"
); );
FAIL_ZERO_BREAK( FAIL_ZERO_BREAK(
unhandled_error_context, unhandled_error_context,
akgl_actor_rendered, akgl_actor_rendered,
AKERR_BEHAVIOR, AKGL_ERR_BEHAVIOR,
"actor->renderfunc not called by the iterator" "actor->renderfunc not called by the iterator"
); );
} CLEANUP { } CLEANUP {
@@ -235,7 +236,7 @@ akerr_ErrorContext *test_actor_manage_children(void)
CATCH(errctx, parent->addchild(parent, child)); CATCH(errctx, parent->addchild(parent, child));
} CLEANUP { } CLEANUP {
if ( errctx == NULL ) { if ( errctx == NULL ) {
FAIL(errctx, AKERR_BEHAVIOR, "addchild does not throw AKERR_RELATIONSHIP when child already has a parent"); FAIL(errctx, AKGL_ERR_BEHAVIOR, "addchild does not throw AKERR_RELATIONSHIP when child already has a parent");
} }
} PROCESS(errctx) { } PROCESS(errctx) {
} HANDLE(errctx, AKERR_RELATIONSHIP) { } HANDLE(errctx, AKERR_RELATIONSHIP) {
@@ -248,7 +249,7 @@ akerr_ErrorContext *test_actor_manage_children(void)
CATCH(errctx, parent->addchild(parent, child)); CATCH(errctx, parent->addchild(parent, child));
} CLEANUP { } CLEANUP {
if ( errctx == NULL ) { if ( errctx == NULL ) {
FAIL(errctx, AKERR_BEHAVIOR, "addchild does not throw AKERR_OUTOFBOUNDS when all children already set"); FAIL(errctx, AKGL_ERR_BEHAVIOR, "addchild does not throw AKERR_OUTOFBOUNDS when all children already set");
} }
} PROCESS(errctx) { } PROCESS(errctx) {
} HANDLE(errctx, AKERR_OUTOFBOUNDS) { } HANDLE(errctx, AKERR_OUTOFBOUNDS) {

View File

@@ -1,7 +1,8 @@
{ {
"name": "testcharacter", "name": "testcharacter",
"velocity_x": 0.20, "movementspeed": 1,
"velocity_y": 0.20, "acceleration_x": 0.20,
"acceleration_y": 0.20,
"sprite_mappings": [ "sprite_mappings": [
{ {
"state": [ "state": [
@@ -12,7 +13,7 @@
}, },
{ {
"state": [ "state": [
"ACTOR_STATE_DEAD" "AKGL_ACTOR_STATE_DEAD"
], ],
"sprite": "testsprite2" "sprite": "testsprite2"
} }

View File

@@ -1,6 +1,6 @@
{ {
"spritesheet": { "spritesheet": {
"filename": "assets/spritesheet.png", "filename": "spritesheet.png",
"frame_width": 48, "frame_width": 48,
"frame_height": 48 "frame_height": 48
}, },

View File

@@ -1,6 +1,6 @@
{ {
"spritesheet": { "spritesheet": {
"filename": "assets/spritesheet.png", "filename": "spritesheet.png",
"frame_width": 48, "frame_width": 48,
"frame_height": 48 "frame_height": 48
}, },

View File

@@ -50,6 +50,7 @@ akerr_ErrorContext *test_character_sprite_mgmt()
PREPARE_ERROR(errctx); PREPARE_ERROR(errctx);
ATTEMPT { ATTEMPT {
CATCH(errctx, akgl_heap_next_character(&testchar)); CATCH(errctx, akgl_heap_next_character(&testchar));
CATCH(errctx, akgl_character_initialize(testchar, "testchar"));
CATCH(errctx, akgl_sprite_load_json("assets/testsprite.json")); CATCH(errctx, akgl_sprite_load_json("assets/testsprite.json"));
testsprite = SDL_GetPointerProperty(AKGL_REGISTRY_SPRITE, "testsprite", NULL); testsprite = SDL_GetPointerProperty(AKGL_REGISTRY_SPRITE, "testsprite", NULL);
FAIL_ZERO_BREAK( FAIL_ZERO_BREAK(
@@ -89,6 +90,7 @@ akerr_ErrorContext *test_character_iterate_state_sprites()
PREPARE_ERROR(errctx); PREPARE_ERROR(errctx);
ATTEMPT { ATTEMPT {
CATCH(errctx, akgl_heap_next_character(&testchar)); CATCH(errctx, akgl_heap_next_character(&testchar));
CATCH(errctx, akgl_character_initialize(testchar, "testchar"));
CATCH(errctx, akgl_sprite_load_json("assets/testsprite.json")); CATCH(errctx, akgl_sprite_load_json("assets/testsprite.json"));
testsprite = SDL_GetPointerProperty(AKGL_REGISTRY_SPRITE, "testsprite", NULL); testsprite = SDL_GetPointerProperty(AKGL_REGISTRY_SPRITE, "testsprite", NULL);
FAIL_ZERO_BREAK( FAIL_ZERO_BREAK(
@@ -169,8 +171,8 @@ akerr_ErrorContext *test_akgl_character_load_json()
CATCH(errctx, testcharacter->sprite_get(testcharacter, AKGL_ACTOR_STATE_DEAD, &comparesprite)); CATCH(errctx, testcharacter->sprite_get(testcharacter, AKGL_ACTOR_STATE_DEAD, &comparesprite));
FAIL_ZERO_BREAK(errctx, (comparesprite == testsprite2), AKERR_VALUE, "Wrong sprite for state AKGL_ACTOR_STATE_DEAD"); FAIL_ZERO_BREAK(errctx, (comparesprite == testsprite2), AKERR_VALUE, "Wrong sprite for state AKGL_ACTOR_STATE_DEAD");
FAIL_ZERO_BREAK(errctx, (testcharacter->vx != 0.200000003), AKERR_VALUE, "Wrong X velocity for test character"); FAIL_ZERO_BREAK(errctx, (testcharacter->ax != 0.200000003), AKERR_VALUE, "Wrong X acceleration for test character");
FAIL_ZERO_BREAK(errctx, (testcharacter->vy != 0.200000003), AKERR_VALUE, "Wrong Y velocity for test character"); FAIL_ZERO_BREAK(errctx, (testcharacter->ay != 0.200000003), AKERR_VALUE, "Wrong Y acceleration for test character");
// Release our handles on the sprites so the character's heap_release can reduce them to 0 // Release our handles on the sprites so the character's heap_release can reduce them to 0
CATCH(errctx, akgl_heap_release_sprite(testsprite)); CATCH(errctx, akgl_heap_release_sprite(testsprite));

View File

@@ -68,7 +68,7 @@ int main(void)
AKGL_REGISTRY_CHARACTER, AKGL_REGISTRY_CHARACTER,
"little guy", "little guy",
NULL); NULL);
FAIL_ZERO_BREAK(errctx, actorptr->basechar, AKERR_REGISTRY, "Can't load character 'little guy' from the registry"); FAIL_ZERO_BREAK(errctx, actorptr->basechar, AKGL_ERR_REGISTRY, "Can't load character 'little guy' from the registry");
actorptr->movement_controls_face = false; actorptr->movement_controls_face = false;
actorptr->state = (AKGL_ACTOR_STATE_ALIVE | AKGL_ACTOR_STATE_FACE_LEFT); actorptr->state = (AKGL_ACTOR_STATE_ALIVE | AKGL_ACTOR_STATE_FACE_LEFT);
actorptr->x = 320; actorptr->x = 320;

View File

@@ -43,7 +43,7 @@ akerr_ErrorContext *test_akgl_registry_init(RegistryFuncPtr funcptr)
} PROCESS(errctx) { } PROCESS(errctx) {
} FINISH(errctx, true); } FINISH(errctx, true);
FAIL_RETURN(errctx, AKERR_BEHAVIOR, "SDL memory allocator fails but registry reports successful property creation"); FAIL_RETURN(errctx, AKGL_ERR_BEHAVIOR, "SDL memory allocator fails but registry reports successful property creation");
} }
akerr_ErrorContext *test_akgl_registry_init_creation_failures(void) akerr_ErrorContext *test_akgl_registry_init_creation_failures(void)

View File

@@ -1,5 +1,6 @@
#include <string.h> #include <string.h>
#include <akerror.h> #include <akerror.h>
#include <akgl/error.h>
#include <akgl/heap.h> #include <akgl/heap.h>
#include <akgl/staticstring.h> #include <akgl/staticstring.h>
@@ -111,7 +112,7 @@ akerr_ErrorContext *test_akgl_string_initialize(void)
FAIL_NONZERO_BREAK(errctx, strcmp((char *)&ptr->data, "Test value"), AKERR_VALUE, "Expected 'Test value', got %s", (char *)&ptr->data); FAIL_NONZERO_BREAK(errctx, strcmp((char *)&ptr->data, "Test value"), AKERR_VALUE, "Expected 'Test value', got %s", (char *)&ptr->data);
CATCH(errctx, akgl_heap_release_string(NULL)); CATCH(errctx, akgl_heap_release_string(NULL));
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Failure to properly handle NULL pointer"); FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "Failure to properly handle NULL pointer");
} CLEANUP { } CLEANUP {
} PROCESS(errctx) { } PROCESS(errctx) {
} FINISH(errctx, true); } FINISH(errctx, true);

View File

@@ -26,7 +26,7 @@ akerr_ErrorContext *test_tilemap_akgl_get_json_tilemap_property(void)
AKGL_MAX_STRING_LENGTH, AKGL_MAX_STRING_LENGTH,
"%s%s", "%s%s",
SDL_GetBasePath(), SDL_GetBasePath(),
"assets/snippets/test_tilemap_akgl_get_json_tilemap_property.json" "assets/snippets/test_tilemap_get_json_tilemap_property.json"
); );
jsondoc = json_load_file((char *)&tmpstr->data, 0, (json_error_t *)&jsonerr); jsondoc = json_load_file((char *)&tmpstr->data, 0, (json_error_t *)&jsonerr);
FAIL_ZERO_BREAK(errctx, jsondoc, AKERR_NULLPOINTER, "Failure loading json fixture: %s", (char *)jsonerr.text); FAIL_ZERO_BREAK(errctx, jsondoc, AKERR_NULLPOINTER, "Failure loading json fixture: %s", (char *)jsonerr.text);

View File

@@ -1,5 +1,6 @@
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
#include <akerror.h> #include <akerror.h>
#include <akgl/error.h>
#include <akgl/util.h> #include <akgl/util.h>
akerr_ErrorContext *test_akgl_rectangle_points_nullpointers(void) akerr_ErrorContext *test_akgl_rectangle_points_nullpointers(void)
@@ -10,7 +11,7 @@ akerr_ErrorContext *test_akgl_rectangle_points_nullpointers(void)
ATTEMPT { ATTEMPT {
CATCH(errctx, akgl_rectangle_points(NULL, NULL)); CATCH(errctx, akgl_rectangle_points(NULL, NULL));
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_rectangle_points fails to FAIL with all NULL pointers"); FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "akgl_rectangle_points fails to FAIL with all NULL pointers");
} CLEANUP { } CLEANUP {
} PROCESS(errctx) { } PROCESS(errctx) {
} HANDLE(errctx, AKERR_NULLPOINTER) { } HANDLE(errctx, AKERR_NULLPOINTER) {
@@ -19,7 +20,7 @@ akerr_ErrorContext *test_akgl_rectangle_points_nullpointers(void)
ATTEMPT { ATTEMPT {
CATCH(errctx, akgl_rectangle_points(NULL, &testrect)); CATCH(errctx, akgl_rectangle_points(NULL, &testrect));
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_rectangle_points fails to FAIL with NULL SDL_FRect pointer"); FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "akgl_rectangle_points fails to FAIL with NULL SDL_FRect pointer");
} CLEANUP { } CLEANUP {
} PROCESS(errctx) { } PROCESS(errctx) {
} HANDLE(errctx, AKERR_NULLPOINTER) { } HANDLE(errctx, AKERR_NULLPOINTER) {
@@ -28,7 +29,7 @@ akerr_ErrorContext *test_akgl_rectangle_points_nullpointers(void)
ATTEMPT { ATTEMPT {
CATCH(errctx, akgl_rectangle_points(&points, NULL)); CATCH(errctx, akgl_rectangle_points(&points, NULL));
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_rectangle_points fails to FAIL with NULL RectanglePoints pointer"); FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "akgl_rectangle_points fails to FAIL with NULL RectanglePoints pointer");
} CLEANUP { } CLEANUP {
} PROCESS(errctx) { } PROCESS(errctx) {
} HANDLE(errctx, AKERR_NULLPOINTER) { } HANDLE(errctx, AKERR_NULLPOINTER) {
@@ -63,7 +64,7 @@ akerr_ErrorContext *test_akgl_rectangle_points_math(void)
points.bottomright.y != 32 ) { points.bottomright.y != 32 ) {
FAIL_BREAK( FAIL_BREAK(
errctx, errctx,
AKERR_BEHAVIOR, AKGL_ERR_BEHAVIOR,
"akgl_rectangle_points incorrectly calculated points for {x=0, y=0, w=32, h=32} to {topleft={%d, %d}, topright={%d, %d}, bottomleft={%d, %d}, bottomright={%d, %d}}", "akgl_rectangle_points incorrectly calculated points for {x=0, y=0, w=32, h=32} to {topleft={%d, %d}, topright={%d, %d}, bottomleft={%d, %d}, bottomright={%d, %d}}",
points.topleft.x, points.topleft.y, points.topleft.x, points.topleft.y,
points.topright.x, points.topright.y, points.topright.x, points.topright.y,
@@ -87,7 +88,7 @@ akerr_ErrorContext *test_akgl_collide_point_rectangle_nullpointers(void)
ATTEMPT { ATTEMPT {
CATCH(errctx, akgl_collide_point_rectangle(&testpoint, &testrectpoints, NULL)); CATCH(errctx, akgl_collide_point_rectangle(&testpoint, &testrectpoints, NULL));
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_collide_point_rectangle(*, *, NULL) failed"); FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "akgl_collide_point_rectangle(*, *, NULL) failed");
} CLEANUP { } CLEANUP {
} PROCESS(errctx) { } PROCESS(errctx) {
} HANDLE(errctx, AKERR_NULLPOINTER) { } HANDLE(errctx, AKERR_NULLPOINTER) {
@@ -96,7 +97,7 @@ akerr_ErrorContext *test_akgl_collide_point_rectangle_nullpointers(void)
ATTEMPT { ATTEMPT {
CATCH(errctx, akgl_collide_point_rectangle(&testpoint, NULL, &testcollide)); CATCH(errctx, akgl_collide_point_rectangle(&testpoint, NULL, &testcollide));
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_collide_point_rectangle(*, NULL, *) failed"); FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "akgl_collide_point_rectangle(*, NULL, *) failed");
} CLEANUP { } CLEANUP {
} PROCESS(errctx) { } PROCESS(errctx) {
} HANDLE(errctx, AKERR_NULLPOINTER) { } HANDLE(errctx, AKERR_NULLPOINTER) {
@@ -105,7 +106,7 @@ akerr_ErrorContext *test_akgl_collide_point_rectangle_nullpointers(void)
ATTEMPT { ATTEMPT {
CATCH(errctx, akgl_collide_point_rectangle(NULL, &testrectpoints, &testcollide)); CATCH(errctx, akgl_collide_point_rectangle(NULL, &testrectpoints, &testcollide));
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_collide_point_rectangle(NULL, *, *) failed"); FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "akgl_collide_point_rectangle(NULL, *, *) failed");
} CLEANUP { } CLEANUP {
} PROCESS(errctx) { } PROCESS(errctx) {
} HANDLE(errctx, AKERR_NULLPOINTER) { } HANDLE(errctx, AKERR_NULLPOINTER) {
@@ -114,7 +115,7 @@ akerr_ErrorContext *test_akgl_collide_point_rectangle_nullpointers(void)
ATTEMPT { ATTEMPT {
CATCH(errctx, akgl_collide_point_rectangle(NULL, NULL, NULL)); CATCH(errctx, akgl_collide_point_rectangle(NULL, NULL, NULL));
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_collide_point_rectangle(NULL, NULL, NULL) failed"); FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "akgl_collide_point_rectangle(NULL, NULL, NULL) failed");
} CLEANUP { } CLEANUP {
} PROCESS(errctx) { } PROCESS(errctx) {
} HANDLE(errctx, AKERR_NULLPOINTER) { } HANDLE(errctx, AKERR_NULLPOINTER) {
@@ -142,14 +143,14 @@ akerr_ErrorContext *test_akgl_collide_point_rectangle_logic(void)
CATCH(errctx, akgl_rectangle_points(&testrectpoints, &testrect)); CATCH(errctx, akgl_rectangle_points(&testrectpoints, &testrect));
CATCH(errctx, akgl_collide_point_rectangle(&testpoint, &testrectpoints, &testcollide)); CATCH(errctx, akgl_collide_point_rectangle(&testpoint, &testrectpoints, &testcollide));
if ( testcollide == false ) { if ( testcollide == false ) {
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Valid collision missed"); FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "Valid collision missed");
} }
testpoint.x = 48; testpoint.x = 48;
testpoint.y = 48; testpoint.y = 48;
CATCH(errctx, akgl_collide_point_rectangle(&testpoint, &testrectpoints, &testcollide)); CATCH(errctx, akgl_collide_point_rectangle(&testpoint, &testrectpoints, &testcollide));
if ( testcollide == true ) { if ( testcollide == true ) {
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Invalid collision reported"); FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "Invalid collision reported");
} }
} CLEANUP { } CLEANUP {
} PROCESS(errctx) { } PROCESS(errctx) {
@@ -167,7 +168,7 @@ akerr_ErrorContext *test_akgl_collide_rectangles_nullpointers(void)
ATTEMPT { ATTEMPT {
CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, NULL)); CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, NULL));
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_collide_rectangles(*, *, NULL) failed"); FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "akgl_collide_rectangles(*, *, NULL) failed");
} CLEANUP { } CLEANUP {
} PROCESS(errctx) { } PROCESS(errctx) {
} HANDLE(errctx, AKERR_NULLPOINTER) { } HANDLE(errctx, AKERR_NULLPOINTER) {
@@ -176,7 +177,7 @@ akerr_ErrorContext *test_akgl_collide_rectangles_nullpointers(void)
ATTEMPT { ATTEMPT {
CATCH(errctx, akgl_collide_rectangles(&testrect1, NULL, &testcollide)); CATCH(errctx, akgl_collide_rectangles(&testrect1, NULL, &testcollide));
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_collide_rectangles(*, NULL, *) failed"); FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "akgl_collide_rectangles(*, NULL, *) failed");
} CLEANUP { } CLEANUP {
} PROCESS(errctx) { } PROCESS(errctx) {
} HANDLE(errctx, AKERR_NULLPOINTER) { } HANDLE(errctx, AKERR_NULLPOINTER) {
@@ -185,7 +186,7 @@ akerr_ErrorContext *test_akgl_collide_rectangles_nullpointers(void)
ATTEMPT { ATTEMPT {
CATCH(errctx, akgl_collide_rectangles(NULL, &testrect2, &testcollide)); CATCH(errctx, akgl_collide_rectangles(NULL, &testrect2, &testcollide));
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_collide_rectangles(NULL, *, *) failed"); FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "akgl_collide_rectangles(NULL, *, *) failed");
} CLEANUP { } CLEANUP {
} PROCESS(errctx) { } PROCESS(errctx) {
} HANDLE(errctx, AKERR_NULLPOINTER) { } HANDLE(errctx, AKERR_NULLPOINTER) {
@@ -194,7 +195,7 @@ akerr_ErrorContext *test_akgl_collide_rectangles_nullpointers(void)
ATTEMPT { ATTEMPT {
CATCH(errctx, akgl_collide_rectangles(NULL, NULL, NULL)); CATCH(errctx, akgl_collide_rectangles(NULL, NULL, NULL));
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_collide_rectangles(NULL, NULL, NULL) failed"); FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "akgl_collide_rectangles(NULL, NULL, NULL) failed");
} CLEANUP { } CLEANUP {
} PROCESS(errctx) { } PROCESS(errctx) {
} HANDLE(errctx, AKERR_NULLPOINTER) { } HANDLE(errctx, AKERR_NULLPOINTER) {
@@ -222,14 +223,14 @@ akerr_ErrorContext *test_akgl_collide_rectangles_logic(void)
// Collision overlapping on the top left // Collision overlapping on the top left
CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide)); CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide));
if ( testcollide == false ) { if ( testcollide == false ) {
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Valid collision missed"); FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "Valid collision missed");
} }
// Collision overlapping on the top right // Collision overlapping on the top right
testrect1.x = 64; testrect1.x = 64;
CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide)); CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide));
if ( testcollide == false ) { if ( testcollide == false ) {
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Valid collision missed"); FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "Valid collision missed");
} }
// Collision overlapping on the bottom left // Collision overlapping on the bottom left
@@ -237,7 +238,7 @@ akerr_ErrorContext *test_akgl_collide_rectangles_logic(void)
testrect1.y = 32; testrect1.y = 32;
CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide)); CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide));
if ( testcollide == false ) { if ( testcollide == false ) {
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Valid collision missed"); FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "Valid collision missed");
} }
// Collision overlapping on the bottom right // Collision overlapping on the bottom right
@@ -245,7 +246,7 @@ akerr_ErrorContext *test_akgl_collide_rectangles_logic(void)
testrect1.y = 32; testrect1.y = 32;
CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide)); CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide));
if ( testcollide == false ) { if ( testcollide == false ) {
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Valid collision missed"); FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "Valid collision missed");
} }
// Collision overlapping the top edge // Collision overlapping the top edge
@@ -255,7 +256,7 @@ akerr_ErrorContext *test_akgl_collide_rectangles_logic(void)
testrect1.h = 32; testrect1.h = 32;
CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide)); CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide));
if ( testcollide == false ) { if ( testcollide == false ) {
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Valid collision missed"); FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "Valid collision missed");
} }
// Collision overlapping the left edge // Collision overlapping the left edge
@@ -265,7 +266,7 @@ akerr_ErrorContext *test_akgl_collide_rectangles_logic(void)
testrect1.h = 80; testrect1.h = 80;
CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide)); CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide));
if ( testcollide == false ) { if ( testcollide == false ) {
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Valid collision missed"); FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "Valid collision missed");
} }
// Collision overlapping the right edge // Collision overlapping the right edge
@@ -275,7 +276,7 @@ akerr_ErrorContext *test_akgl_collide_rectangles_logic(void)
testrect1.h = 80; testrect1.h = 80;
CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide)); CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide));
if ( testcollide == false ) { if ( testcollide == false ) {
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Valid collision missed"); FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "Valid collision missed");
} }
// Collision overlapping the bottom edge // Collision overlapping the bottom edge
@@ -285,7 +286,7 @@ akerr_ErrorContext *test_akgl_collide_rectangles_logic(void)
testrect1.h = 32; testrect1.h = 32;
CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide)); CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide));
if ( testcollide == false ) { if ( testcollide == false ) {
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Valid collision missed"); FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "Valid collision missed");
} }
// Not colliding // Not colliding
@@ -295,7 +296,7 @@ akerr_ErrorContext *test_akgl_collide_rectangles_logic(void)
testrect1.h = 16; testrect1.h = 16;
CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide)); CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide));
if ( testcollide == true ) { if ( testcollide == true ) {
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Invalid collision reported"); FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "Invalid collision reported");
} }
} CLEANUP { } CLEANUP {

View File

@@ -48,12 +48,11 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
strcpy((char *)&game.name, "charviewer"); strcpy((char *)&game.name, "charviewer");
strcpy((char *)&game.version, "0.0.1"); strcpy((char *)&game.version, "0.0.1");
strcpy((char *)&game.uri, "net.aklabs.libakgl.charviewer"); strcpy((char *)&game.uri, "net.aklabs.libakgl.charviewer");
game.screenwidth = 640;
game.screenheight = 480;
CATCH(errctx, akgl_game_init()); CATCH(errctx, akgl_game_init());
CATCH(errctx, akgl_heap_init()); CATCH(errctx, akgl_set_property("game.screenwidth", "640"));
CATCH(errctx, akgl_registry_init()); CATCH(errctx, akgl_set_property("game.screenheight", "480"));
CATCH(errctx, akgl_render_init2d(renderer));
CATCH(errctx, akgl_physics_init_null(physics));
} CLEANUP { } CLEANUP {
} PROCESS(errctx) { } PROCESS(errctx) {
@@ -94,7 +93,7 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
AKGL_REGISTRY_CHARACTER, AKGL_REGISTRY_CHARACTER,
"little guy", "little guy",
NULL); NULL);
FAIL_ZERO_BREAK(errctx, actorptr->basechar, AKERR_REGISTRY, "Can't load character 'little guy' from the registry"); FAIL_ZERO_BREAK(errctx, actorptr->basechar, AKGL_ERR_REGISTRY, "Can't load character 'little guy' from the registry");
actorptr->movement_controls_face = false; actorptr->movement_controls_face = false;
actorptr->state = (AKGL_ACTOR_STATE_ALIVE | AKGL_ACTOR_STATE_FACE_DOWN); actorptr->state = (AKGL_ACTOR_STATE_ALIVE | AKGL_ACTOR_STATE_FACE_DOWN);
actorptr->x = 320; actorptr->x = 320;
@@ -145,9 +144,9 @@ SDL_AppResult SDL_AppIterate(void *appstate)
AKGL_BITMASK_CLEAR(opflags.flags); AKGL_BITMASK_CLEAR(opflags.flags);
AKGL_BITMASK_ADD(opflags.flags, AKGL_ITERATOR_OP_UPDATE); AKGL_BITMASK_ADD(opflags.flags, AKGL_ITERATOR_OP_UPDATE);
AKGL_BITMASK_ADD(opflags.flags, AKGL_ITERATOR_OP_RENDER); AKGL_BITMASK_ADD(opflags.flags, AKGL_ITERATOR_OP_RENDER);
akgl_draw_background(game.screenwidth, game.screenheight); akgl_draw_background((int)camera->w, (int)camera->h);
ATTEMPT { ATTEMPT {
CATCH(errctx, akgl_tilemap_draw(renderer, (akgl_Tilemap *)&gamemap, &camera, i)); CATCH(errctx, akgl_tilemap_draw(gamemap, camera, i));
SDL_EnumerateProperties(AKGL_REGISTRY_ACTOR, &akgl_registry_iterate_actor, (void *)&opflags); SDL_EnumerateProperties(AKGL_REGISTRY_ACTOR, &akgl_registry_iterate_actor, (void *)&opflags);
} CLEANUP { } CLEANUP {
} PROCESS(errctx) { } PROCESS(errctx) {
@@ -155,7 +154,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
LOG_ERROR(errctx); LOG_ERROR(errctx);
return SDL_APP_FAILURE; return SDL_APP_FAILURE;
} FINISH_NORETURN(errctx); } FINISH_NORETURN(errctx);
SDL_RenderPresent(renderer); SDL_RenderPresent(renderer->sdl_renderer);
return SDL_APP_CONTINUE; return SDL_APP_CONTINUE;
} }