2026-07-30 01:10:31 -04:00
|
|
|
/**
|
|
|
|
|
* @file tilemap.c
|
|
|
|
|
* @brief Implements the tilemap subsystem.
|
|
|
|
|
*/
|
|
|
|
|
|
2026-05-24 09:51:58 -04:00
|
|
|
#include <string.h>
|
|
|
|
|
#include <libgen.h>
|
|
|
|
|
|
2025-08-03 10:07:35 -04:00
|
|
|
#include <SDL3/SDL.h>
|
|
|
|
|
#include <SDL3_image/SDL_image.h>
|
|
|
|
|
#include <SDL3_mixer/SDL_mixer.h>
|
|
|
|
|
#include <jansson.h>
|
2026-05-24 09:51:58 -04:00
|
|
|
|
2026-01-05 08:58:06 -05:00
|
|
|
#include <akerror.h>
|
2026-05-24 09:51:58 -04:00
|
|
|
#include <akstdlib.h>
|
2025-08-03 10:07:35 -04:00
|
|
|
|
2026-05-07 22:20:10 -04:00
|
|
|
#include <akgl/tilemap.h>
|
|
|
|
|
#include <akgl/actor.h>
|
|
|
|
|
#include <akgl/json_helpers.h>
|
|
|
|
|
#include <akgl/heap.h>
|
|
|
|
|
#include <akgl/registry.h>
|
|
|
|
|
#include <akgl/staticstring.h>
|
|
|
|
|
#include <akgl/game.h>
|
2026-05-24 19:57:43 -04:00
|
|
|
#include <akgl/util.h>
|
2026-05-24 09:51:58 -04:00
|
|
|
|
2026-05-06 23:18:42 -04:00
|
|
|
akerr_ErrorContext *akgl_get_json_tilemap_property(json_t *obj, char *key, char *type, json_t **dest)
|
2025-08-03 10:07:35 -04:00
|
|
|
{
|
|
|
|
|
PREPARE_ERROR(errctx);
|
|
|
|
|
json_t *properties = NULL;
|
|
|
|
|
json_t *property = NULL;
|
2026-05-06 23:18:42 -04:00
|
|
|
akgl_String *tmpstr = NULL;
|
2026-05-25 21:29:18 -04:00
|
|
|
akgl_String *typestr = NULL;
|
2025-08-03 10:07:35 -04:00
|
|
|
int i = 0;
|
|
|
|
|
// This is not a generic JSON helper. It assumes we are receiving an object with a 'properties' key
|
|
|
|
|
// inside of it. That key is an array of objects, and each object has a name, type, and value.
|
2026-05-03 23:57:55 -04:00
|
|
|
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL json obj reference");
|
|
|
|
|
FAIL_ZERO_RETURN(errctx, key, AKERR_NULLPOINTER, "NULL key string");
|
2025-08-03 10:07:35 -04:00
|
|
|
ATTEMPT {
|
2026-05-06 23:18:42 -04:00
|
|
|
CATCH(errctx, akgl_get_json_array_value(obj, "properties", &properties));
|
2025-08-03 10:07:35 -04:00
|
|
|
for (i = 0; i < json_array_size(properties); i++) {
|
2026-05-06 23:18:42 -04:00
|
|
|
CATCH(errctx, akgl_get_json_array_index_object(properties, i, &property));
|
|
|
|
|
CATCH(errctx, akgl_get_json_string_value(property, "name", &tmpstr));
|
2025-08-03 10:07:35 -04:00
|
|
|
if ( strcmp(tmpstr->data, key) != 0 ) {
|
2026-05-06 23:18:42 -04:00
|
|
|
CATCH(errctx, akgl_heap_release_string(tmpstr));
|
2025-08-03 10:07:35 -04:00
|
|
|
continue;
|
|
|
|
|
}
|
2026-05-25 21:29:18 -04:00
|
|
|
CATCH(errctx, akgl_get_json_string_value(property, "type", &typestr));
|
|
|
|
|
if ( strcmp(typestr->data, type) != 0 ) {
|
|
|
|
|
FAIL_BREAK(errctx, AKERR_TYPE, "Property %s is present but is incorrect type(expected %s got %s)", key, type, (char *)typestr->data);
|
2025-08-03 10:07:35 -04:00
|
|
|
}
|
|
|
|
|
*dest = property;
|
|
|
|
|
SUCCEED_RETURN(errctx);
|
|
|
|
|
}
|
|
|
|
|
} CLEANUP {
|
|
|
|
|
if ( tmpstr != NULL ) {
|
2026-05-06 23:18:42 -04:00
|
|
|
IGNORE(akgl_heap_release_string(tmpstr));
|
2025-08-03 10:07:35 -04:00
|
|
|
}
|
2026-05-25 21:29:18 -04:00
|
|
|
if ( typestr != NULL ) {
|
|
|
|
|
IGNORE(akgl_heap_release_string(typestr));
|
|
|
|
|
}
|
2025-08-03 10:07:35 -04:00
|
|
|
} PROCESS(errctx) {
|
|
|
|
|
} FINISH(errctx, true);
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
|
2026-05-03 23:57:55 -04:00
|
|
|
FAIL_RETURN(errctx, AKERR_KEY, "Property not found in properties map");
|
2025-08-03 10:07:35 -04:00
|
|
|
}
|
|
|
|
|
|
2026-05-06 23:18:42 -04:00
|
|
|
akerr_ErrorContext *akgl_get_json_properties_string(json_t *obj, char *key, akgl_String **dest)
|
2025-08-03 10:07:35 -04:00
|
|
|
{
|
|
|
|
|
PREPARE_ERROR(errctx);
|
|
|
|
|
json_t *property;
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
|
2026-06-02 17:11:16 -04:00
|
|
|
PASS(errctx, akgl_get_json_tilemap_property(obj, key, "string", &property));
|
|
|
|
|
PASS(errctx, akgl_heap_next_string(dest));
|
|
|
|
|
PASS(errctx, akgl_string_initialize(*dest, NULL));
|
|
|
|
|
PASS(errctx, akgl_get_json_string_value(property, "value", dest));
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
|
2025-08-03 10:07:35 -04:00
|
|
|
SUCCEED_RETURN(errctx);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-06 23:18:42 -04:00
|
|
|
akerr_ErrorContext *akgl_get_json_properties_integer(json_t *obj, char *key, int *dest)
|
2025-08-03 10:07:35 -04:00
|
|
|
{
|
|
|
|
|
PREPARE_ERROR(errctx);
|
|
|
|
|
json_t *property = NULL;
|
2026-06-02 17:11:16 -04:00
|
|
|
PASS(errctx, akgl_get_json_tilemap_property(obj, key, "int", &property));
|
|
|
|
|
PASS(errctx, akgl_get_json_integer_value(property, "value", dest));
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
|
2025-08-03 10:07:35 -04:00
|
|
|
SUCCEED_RETURN(errctx);
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-30 01:10:31 -04:00
|
|
|
/**
|
Document what the functions actually do instead of that they can fail
The Doxygen comments were generated from the declarations, so 217 @throws
lines across 21 headers read "When the corresponding validation or operation
fails" and told a caller nothing beyond the status name. The @param lines were
the same shape: every output was "Output destination populated by the
function", every instance "Object to initialize, inspect, or modify".
Rewritten against the implementations, following the pattern libakstdlib
already uses:
- @throws names the condition. akgl_sprite_load_json separated AKERR_KEY
(absent) from AKERR_TYPE (present, wrong type) from AKERR_OUTOFBOUNDS
(filename too long, or array indexed past its end), and gained AKGL_ERR_SDL
and AKGL_ERR_HEAP, which it raises and never declared.
- Parameters say whether they are required, what a NULL means, and what is
written on a failure path. Where an argument is not checked, the doc says so:
akgl_heap_next_actor's dest is a crash on NULL, not an error, and
akgl_render_2d_frame_start dereferences self before testing it.
- The conventions move up to the file blocks so the per-function docs stay
short. json_helpers.h states once that absence is an error here and that
json_t * results are borrowed; heap.h explains the pool model and the
acquire asymmetry; physics.h carries the thrust/environmental/velocity table.
- Struct fields, enum values, macros and exported globals are documented,
including the dead ones - sprite_w/sprite_h, movetimer, p_scale and
timer_gravity are read by nothing, and say so.
Also fixes ten comments in error.h and audio.h that opened with /** rather
than /**<, so Doxygen attached them to the following entity and rendered the
text as part of the macro's value. Verified against the generated HTML.
Comments only - no declaration changed. Doxygen builds clean under
WARN_AS_ERROR, scripts/reindent.sh --check passes, 19/19 suites pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 11:02:20 -04:00
|
|
|
* @brief Read a Tiled custom property declared as `number`.
|
|
|
|
|
*
|
|
|
|
|
* Tiled writes `float` for a floating-point property, so this matches nothing
|
|
|
|
|
* Tiled produces today -- akgl_get_json_properties_float is the one the loader
|
|
|
|
|
* uses. Kept because a hand-written or older map may still say `number`.
|
|
|
|
|
*
|
|
|
|
|
* @param obj The Tiled object whose `properties` array to search. Required.
|
|
|
|
|
* @param key The property name. Required.
|
|
|
|
|
* @param dest Receives the value as a `float`. Not written on any failure path.
|
2026-07-30 01:10:31 -04:00
|
|
|
* @return `NULL` on success, otherwise an error context owned by the caller.
|
Document what the functions actually do instead of that they can fail
The Doxygen comments were generated from the declarations, so 217 @throws
lines across 21 headers read "When the corresponding validation or operation
fails" and told a caller nothing beyond the status name. The @param lines were
the same shape: every output was "Output destination populated by the
function", every instance "Object to initialize, inspect, or modify".
Rewritten against the implementations, following the pattern libakstdlib
already uses:
- @throws names the condition. akgl_sprite_load_json separated AKERR_KEY
(absent) from AKERR_TYPE (present, wrong type) from AKERR_OUTOFBOUNDS
(filename too long, or array indexed past its end), and gained AKGL_ERR_SDL
and AKGL_ERR_HEAP, which it raises and never declared.
- Parameters say whether they are required, what a NULL means, and what is
written on a failure path. Where an argument is not checked, the doc says so:
akgl_heap_next_actor's dest is a crash on NULL, not an error, and
akgl_render_2d_frame_start dereferences self before testing it.
- The conventions move up to the file blocks so the per-function docs stay
short. json_helpers.h states once that absence is an error here and that
json_t * results are borrowed; heap.h explains the pool model and the
acquire asymmetry; physics.h carries the thrust/environmental/velocity table.
- Struct fields, enum values, macros and exported globals are documented,
including the dead ones - sprite_w/sprite_h, movetimer, p_scale and
timer_gravity are read by nothing, and say so.
Also fixes ten comments in error.h and audio.h that opened with /** rather
than /**<, so Doxygen attached them to the following entity and rendered the
text as part of the macro's value. Verified against the generated HTML.
Comments only - no declaration changed. Doxygen builds clean under
WARN_AS_ERROR, scripts/reindent.sh --check passes, 19/19 suites pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 11:02:20 -04:00
|
|
|
* @throws AKERR_NULLPOINTER If @p obj or @p key is `NULL`.
|
|
|
|
|
* @throws AKERR_KEY If the property is absent, or @p obj has no properties.
|
|
|
|
|
* @throws AKERR_TYPE If the property is not declared `number`, or its `value` is
|
|
|
|
|
* not numeric.
|
|
|
|
|
* @throws AKGL_ERR_HEAP If the string pool is exhausted.
|
2026-07-30 01:10:31 -04:00
|
|
|
*/
|
2026-05-13 23:36:49 -04:00
|
|
|
akerr_ErrorContext *akgl_get_json_properties_number(json_t *obj, char *key, float *dest)
|
|
|
|
|
{
|
|
|
|
|
PREPARE_ERROR(errctx);
|
|
|
|
|
json_t *property = NULL;
|
2026-06-02 17:11:16 -04:00
|
|
|
PASS(errctx, akgl_get_json_tilemap_property(obj, key, "number", &property));
|
|
|
|
|
PASS(errctx, akgl_get_json_number_value(property, "value", dest));
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
|
2026-05-13 23:36:49 -04:00
|
|
|
SUCCEED_RETURN(errctx);
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-30 01:10:31 -04:00
|
|
|
/**
|
Document what the functions actually do instead of that they can fail
The Doxygen comments were generated from the declarations, so 217 @throws
lines across 21 headers read "When the corresponding validation or operation
fails" and told a caller nothing beyond the status name. The @param lines were
the same shape: every output was "Output destination populated by the
function", every instance "Object to initialize, inspect, or modify".
Rewritten against the implementations, following the pattern libakstdlib
already uses:
- @throws names the condition. akgl_sprite_load_json separated AKERR_KEY
(absent) from AKERR_TYPE (present, wrong type) from AKERR_OUTOFBOUNDS
(filename too long, or array indexed past its end), and gained AKGL_ERR_SDL
and AKGL_ERR_HEAP, which it raises and never declared.
- Parameters say whether they are required, what a NULL means, and what is
written on a failure path. Where an argument is not checked, the doc says so:
akgl_heap_next_actor's dest is a crash on NULL, not an error, and
akgl_render_2d_frame_start dereferences self before testing it.
- The conventions move up to the file blocks so the per-function docs stay
short. json_helpers.h states once that absence is an error here and that
json_t * results are borrowed; heap.h explains the pool model and the
acquire asymmetry; physics.h carries the thrust/environmental/velocity table.
- Struct fields, enum values, macros and exported globals are documented,
including the dead ones - sprite_w/sprite_h, movetimer, p_scale and
timer_gravity are read by nothing, and say so.
Also fixes ten comments in error.h and audio.h that opened with /** rather
than /**<, so Doxygen attached them to the following entity and rendered the
text as part of the macro's value. Verified against the generated HTML.
Comments only - no declaration changed. Doxygen builds clean under
WARN_AS_ERROR, scripts/reindent.sh --check passes, 19/19 suites pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 11:02:20 -04:00
|
|
|
* @brief Read a Tiled custom property declared as `float`.
|
|
|
|
|
*
|
|
|
|
|
* The spelling Tiled actually writes for a floating-point property. This is how
|
|
|
|
|
* the `scale` on a perspective marker is read.
|
|
|
|
|
*
|
|
|
|
|
* @param obj The Tiled object whose `properties` array to search. Required.
|
|
|
|
|
* @param key The property name. Required.
|
|
|
|
|
* @param dest Receives the value. Not written on any failure path.
|
2026-07-30 01:10:31 -04:00
|
|
|
* @return `NULL` on success, otherwise an error context owned by the caller.
|
Document what the functions actually do instead of that they can fail
The Doxygen comments were generated from the declarations, so 217 @throws
lines across 21 headers read "When the corresponding validation or operation
fails" and told a caller nothing beyond the status name. The @param lines were
the same shape: every output was "Output destination populated by the
function", every instance "Object to initialize, inspect, or modify".
Rewritten against the implementations, following the pattern libakstdlib
already uses:
- @throws names the condition. akgl_sprite_load_json separated AKERR_KEY
(absent) from AKERR_TYPE (present, wrong type) from AKERR_OUTOFBOUNDS
(filename too long, or array indexed past its end), and gained AKGL_ERR_SDL
and AKGL_ERR_HEAP, which it raises and never declared.
- Parameters say whether they are required, what a NULL means, and what is
written on a failure path. Where an argument is not checked, the doc says so:
akgl_heap_next_actor's dest is a crash on NULL, not an error, and
akgl_render_2d_frame_start dereferences self before testing it.
- The conventions move up to the file blocks so the per-function docs stay
short. json_helpers.h states once that absence is an error here and that
json_t * results are borrowed; heap.h explains the pool model and the
acquire asymmetry; physics.h carries the thrust/environmental/velocity table.
- Struct fields, enum values, macros and exported globals are documented,
including the dead ones - sprite_w/sprite_h, movetimer, p_scale and
timer_gravity are read by nothing, and say so.
Also fixes ten comments in error.h and audio.h that opened with /** rather
than /**<, so Doxygen attached them to the following entity and rendered the
text as part of the macro's value. Verified against the generated HTML.
Comments only - no declaration changed. Doxygen builds clean under
WARN_AS_ERROR, scripts/reindent.sh --check passes, 19/19 suites pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 11:02:20 -04:00
|
|
|
* @throws AKERR_NULLPOINTER If @p obj or @p key is `NULL`.
|
|
|
|
|
* @throws AKERR_KEY If the property is absent, or @p obj has no properties.
|
|
|
|
|
* @throws AKERR_TYPE If the property is not declared `float`, or its `value` is
|
|
|
|
|
* not numeric.
|
|
|
|
|
* @throws AKGL_ERR_HEAP If the string pool is exhausted.
|
2026-07-30 01:10:31 -04:00
|
|
|
*/
|
2026-05-25 21:29:18 -04:00
|
|
|
akerr_ErrorContext *akgl_get_json_properties_float(json_t *obj, char *key, float *dest)
|
|
|
|
|
{
|
|
|
|
|
PREPARE_ERROR(errctx);
|
|
|
|
|
json_t *property = NULL;
|
2026-06-02 17:11:16 -04:00
|
|
|
PASS(errctx, akgl_get_json_tilemap_property(obj, key, "float", &property));
|
|
|
|
|
PASS(errctx, akgl_get_json_number_value(property, "value", dest));
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
|
2026-06-02 17:11:16 -04:00
|
|
|
SUCCEED_RETURN(errctx);
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-30 01:10:31 -04:00
|
|
|
/**
|
Document what the functions actually do instead of that they can fail
The Doxygen comments were generated from the declarations, so 217 @throws
lines across 21 headers read "When the corresponding validation or operation
fails" and told a caller nothing beyond the status name. The @param lines were
the same shape: every output was "Output destination populated by the
function", every instance "Object to initialize, inspect, or modify".
Rewritten against the implementations, following the pattern libakstdlib
already uses:
- @throws names the condition. akgl_sprite_load_json separated AKERR_KEY
(absent) from AKERR_TYPE (present, wrong type) from AKERR_OUTOFBOUNDS
(filename too long, or array indexed past its end), and gained AKGL_ERR_SDL
and AKGL_ERR_HEAP, which it raises and never declared.
- Parameters say whether they are required, what a NULL means, and what is
written on a failure path. Where an argument is not checked, the doc says so:
akgl_heap_next_actor's dest is a crash on NULL, not an error, and
akgl_render_2d_frame_start dereferences self before testing it.
- The conventions move up to the file blocks so the per-function docs stay
short. json_helpers.h states once that absence is an error here and that
json_t * results are borrowed; heap.h explains the pool model and the
acquire asymmetry; physics.h carries the thrust/environmental/velocity table.
- Struct fields, enum values, macros and exported globals are documented,
including the dead ones - sprite_w/sprite_h, movetimer, p_scale and
timer_gravity are read by nothing, and say so.
Also fixes ten comments in error.h and audio.h that opened with /** rather
than /**<, so Doxygen attached them to the following entity and rendered the
text as part of the macro's value. Verified against the generated HTML.
Comments only - no declaration changed. Doxygen builds clean under
WARN_AS_ERROR, scripts/reindent.sh --check passes, 19/19 suites pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 11:02:20 -04:00
|
|
|
* @brief Read a Tiled custom property declared as `float`, at full precision.
|
|
|
|
|
*
|
|
|
|
|
* Same declared type as akgl_get_json_properties_float, but writing a `double`.
|
|
|
|
|
* The map's physics constants are `double`, which is the reason both exist.
|
|
|
|
|
*
|
|
|
|
|
* @param obj The Tiled object whose `properties` array to search. Required.
|
|
|
|
|
* @param key The property name. Required.
|
|
|
|
|
* @param dest Receives the value. Not written on any failure path.
|
2026-07-30 01:10:31 -04:00
|
|
|
* @return `NULL` on success, otherwise an error context owned by the caller.
|
Document what the functions actually do instead of that they can fail
The Doxygen comments were generated from the declarations, so 217 @throws
lines across 21 headers read "When the corresponding validation or operation
fails" and told a caller nothing beyond the status name. The @param lines were
the same shape: every output was "Output destination populated by the
function", every instance "Object to initialize, inspect, or modify".
Rewritten against the implementations, following the pattern libakstdlib
already uses:
- @throws names the condition. akgl_sprite_load_json separated AKERR_KEY
(absent) from AKERR_TYPE (present, wrong type) from AKERR_OUTOFBOUNDS
(filename too long, or array indexed past its end), and gained AKGL_ERR_SDL
and AKGL_ERR_HEAP, which it raises and never declared.
- Parameters say whether they are required, what a NULL means, and what is
written on a failure path. Where an argument is not checked, the doc says so:
akgl_heap_next_actor's dest is a crash on NULL, not an error, and
akgl_render_2d_frame_start dereferences self before testing it.
- The conventions move up to the file blocks so the per-function docs stay
short. json_helpers.h states once that absence is an error here and that
json_t * results are borrowed; heap.h explains the pool model and the
acquire asymmetry; physics.h carries the thrust/environmental/velocity table.
- Struct fields, enum values, macros and exported globals are documented,
including the dead ones - sprite_w/sprite_h, movetimer, p_scale and
timer_gravity are read by nothing, and say so.
Also fixes ten comments in error.h and audio.h that opened with /** rather
than /**<, so Doxygen attached them to the following entity and rendered the
text as part of the macro's value. Verified against the generated HTML.
Comments only - no declaration changed. Doxygen builds clean under
WARN_AS_ERROR, scripts/reindent.sh --check passes, 19/19 suites pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 11:02:20 -04:00
|
|
|
* @throws AKERR_NULLPOINTER If @p obj or @p key is `NULL`.
|
|
|
|
|
* @throws AKERR_KEY If the property is absent, or @p obj has no properties.
|
|
|
|
|
* akgl_tilemap_load_physics passes this status to
|
|
|
|
|
* akgl_get_json_with_default, which turns it into a default of 0.0.
|
|
|
|
|
* @throws AKERR_TYPE If the property is not declared `float`, or its `value` is
|
|
|
|
|
* not numeric.
|
|
|
|
|
* @throws AKGL_ERR_HEAP If the string pool is exhausted.
|
2026-07-30 01:10:31 -04:00
|
|
|
*/
|
2026-06-02 17:11:16 -04:00
|
|
|
akerr_ErrorContext *akgl_get_json_properties_double(json_t *obj, char *key, double *dest)
|
|
|
|
|
{
|
|
|
|
|
PREPARE_ERROR(errctx);
|
|
|
|
|
json_t *property = NULL;
|
|
|
|
|
PASS(errctx, akgl_get_json_tilemap_property(obj, key, "float", &property));
|
|
|
|
|
PASS(errctx, akgl_get_json_double_value(property, "value", dest));
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
|
2026-05-25 21:29:18 -04:00
|
|
|
SUCCEED_RETURN(errctx);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-24 09:51:58 -04:00
|
|
|
akerr_ErrorContext *akgl_tilemap_load_tilesets_each(json_t *tileset, akgl_Tilemap *dest, int tsidx, akgl_String *dirname)
|
2025-08-03 10:07:35 -04:00
|
|
|
{
|
2026-05-24 19:57:43 -04:00
|
|
|
PREPARE_ERROR(e);
|
2026-05-06 23:18:42 -04:00
|
|
|
akgl_String *tmpstr = NULL;
|
2026-05-24 19:57:43 -04:00
|
|
|
akgl_String *tmppath = NULL;
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
|
2026-05-24 19:57:43 -04:00
|
|
|
PASS(e, akgl_get_json_integer_value((json_t *)tileset, "columns", &dest->tilesets[tsidx].columns));
|
|
|
|
|
PASS(e, akgl_get_json_integer_value((json_t *)tileset, "firstgid", &dest->tilesets[tsidx].firstgid));
|
|
|
|
|
PASS(e, akgl_get_json_integer_value((json_t *)tileset, "imageheight", &dest->tilesets[tsidx].imageheight));
|
|
|
|
|
PASS(e, akgl_get_json_integer_value((json_t *)tileset, "imagewidth", &dest->tilesets[tsidx].imagewidth));
|
|
|
|
|
PASS(e, akgl_get_json_integer_value((json_t *)tileset, "margin", &dest->tilesets[tsidx].margin));
|
|
|
|
|
PASS(e, akgl_get_json_integer_value((json_t *)tileset, "spacing", &dest->tilesets[tsidx].spacing));
|
|
|
|
|
PASS(e, akgl_get_json_integer_value((json_t *)tileset, "tilecount", &dest->tilesets[tsidx].tilecount));
|
|
|
|
|
PASS(e, akgl_get_json_integer_value((json_t *)tileset, "tileheight", &dest->tilesets[tsidx].tileheight));
|
|
|
|
|
PASS(e, akgl_get_json_integer_value((json_t *)tileset, "tilewidth", &dest->tilesets[tsidx].tilewidth));
|
|
|
|
|
|
|
|
|
|
PASS(e, akgl_get_json_string_value((json_t *)tileset, "name", &tmpstr));
|
|
|
|
|
PASS(e, akgl_heap_next_string(&tmppath));
|
2025-08-03 10:07:35 -04:00
|
|
|
ATTEMPT {
|
|
|
|
|
strncpy((char *)&dest->tilesets[tsidx].name,
|
|
|
|
|
(char *)&tmpstr->data,
|
2026-05-06 23:18:42 -04:00
|
|
|
AKGL_TILEMAP_MAX_TILESET_NAME_SIZE
|
2025-08-03 10:07:35 -04:00
|
|
|
);
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
|
|
|
|
|
CATCH(e, akgl_get_json_string_value((json_t *)tileset, "image", &tmpstr));
|
2026-05-24 19:57:43 -04:00
|
|
|
CATCH(e, akgl_path_relative((char *)&dirname->data, (char *)&tmpstr->data, tmppath));
|
|
|
|
|
strncpy((char *)&dest->tilesets[tsidx].imagefilename, tmppath->data, AKGL_MAX_STRING_LENGTH);
|
2025-08-03 10:07:35 -04:00
|
|
|
} CLEANUP {
|
2026-05-24 19:57:43 -04:00
|
|
|
IGNORE(akgl_heap_release_string(tmpstr));
|
|
|
|
|
IGNORE(akgl_heap_release_string(tmppath));
|
|
|
|
|
} PROCESS(e) {
|
|
|
|
|
} FINISH(e, true);
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
|
2026-06-02 13:15:26 -04:00
|
|
|
dest->tilesets[tsidx].texture = IMG_LoadTexture(renderer->sdl_renderer, (char *)&dest->tilesets[tsidx].imagefilename);
|
2026-05-24 19:57:43 -04:00
|
|
|
FAIL_ZERO_RETURN(e, dest->tilesets[tsidx].texture, AKERR_NULLPOINTER, "Failed loading tileset image : %s", SDL_GetError());
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
|
2026-05-24 19:57:43 -04:00
|
|
|
SUCCEED_RETURN(e);
|
2025-08-03 10:07:35 -04:00
|
|
|
}
|
|
|
|
|
|
2026-05-06 23:18:42 -04:00
|
|
|
akerr_ErrorContext *akgl_tilemap_compute_tileset_offsets(akgl_Tilemap *dest, int tilesetidx)
|
2025-08-03 10:07:35 -04:00
|
|
|
{
|
|
|
|
|
int x_offset = 0;
|
|
|
|
|
int y_offset = 0;
|
|
|
|
|
int x_col = 0;
|
|
|
|
|
int y_col = 0;
|
|
|
|
|
int j = 0;
|
|
|
|
|
PREPARE_ERROR(errctx);
|
|
|
|
|
/* FIXME: THIS DOES NOT PROPERLY ACCOUNT FOR MARGINS
|
|
|
|
|
* It should be possible to make it work easily I just didn't feel like accounting for them in the
|
|
|
|
|
* initial math.
|
|
|
|
|
*/
|
|
|
|
|
/*SDL_Log("Tileset %s has %d rows %d columns",
|
|
|
|
|
dest->tilesets[tilesetidx].name,
|
|
|
|
|
(dest->tilesets[tilesetidx].tilecount / dest->tilesets[tilesetidx].columns),
|
|
|
|
|
dest->tilesets[tilesetidx].columns);*/
|
|
|
|
|
for (j = 0; j <= (dest->tilesets[tilesetidx].tilecount); j++) {
|
|
|
|
|
/*
|
|
|
|
|
* For a given 8x2 tilemap like this with 10x10 tiles and 0 spacing and 0 margin
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
*
|
2025-08-03 10:07:35 -04:00
|
|
|
* 01234567
|
|
|
|
|
* 89ABCDEF
|
|
|
|
|
*
|
|
|
|
|
* tile 0 would be offset (0,0)
|
|
|
|
|
* tile 4 would be offset (40,1)
|
|
|
|
|
* tile 7 would be offset (70,1)
|
|
|
|
|
* tile 8 would be offset (1,8)
|
|
|
|
|
* tile C would be offset (40,8)
|
|
|
|
|
* tile F would be offset (70,8)
|
|
|
|
|
*/
|
|
|
|
|
if ( j >= dest->tilesets[tilesetidx].columns ) {
|
|
|
|
|
x_col = (j % dest->tilesets[tilesetidx].columns);
|
|
|
|
|
y_col = (j / dest->tilesets[tilesetidx].columns);
|
|
|
|
|
x_offset = x_col * (dest->tilesets[tilesetidx].tilewidth + dest->tilesets[tilesetidx].spacing);
|
|
|
|
|
y_offset = y_col * (dest->tilesets[tilesetidx].tileheight + dest->tilesets[tilesetidx].spacing);
|
|
|
|
|
} else {
|
|
|
|
|
x_col = j;
|
|
|
|
|
y_col = 0;
|
|
|
|
|
x_offset = (j * (dest->tilesets[tilesetidx].tilewidth + dest->tilesets[tilesetidx].spacing));
|
|
|
|
|
y_offset = dest->tilesets[tilesetidx].spacing;
|
|
|
|
|
}
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
|
2025-08-03 10:07:35 -04:00
|
|
|
dest->tilesets[tilesetidx].tile_offsets[j][0] = x_offset;
|
|
|
|
|
dest->tilesets[tilesetidx].tile_offsets[j][1] = y_offset;
|
|
|
|
|
/* SDL_Log("Tileset %s index (%d, %d) is offset (%d, %d)",
|
|
|
|
|
dest->tilesets[tilesetidx].name,
|
|
|
|
|
x_col,
|
|
|
|
|
y_col,
|
|
|
|
|
x_offset,
|
|
|
|
|
y_offset);*/
|
|
|
|
|
// SDL_Log("Processed %d total tiles for tileset", j);
|
|
|
|
|
}
|
|
|
|
|
SUCCEED_RETURN(errctx);
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
}
|
|
|
|
|
|
2026-05-24 09:51:58 -04:00
|
|
|
akerr_ErrorContext *akgl_tilemap_load_tilesets(akgl_Tilemap *dest, json_t *root, akgl_String *dirname)
|
2025-08-03 10:07:35 -04:00
|
|
|
{
|
|
|
|
|
PREPARE_ERROR(errctx);
|
2026-05-03 23:57:55 -04:00
|
|
|
FAIL_ZERO_RETURN(errctx, dest, AKERR_NULLPOINTER, "Received NULL tilemap pointer");
|
|
|
|
|
FAIL_ZERO_RETURN(errctx, root, AKERR_NULLPOINTER, "Received NULL json object pointer");
|
2025-08-03 10:07:35 -04:00
|
|
|
|
|
|
|
|
json_t *tilesets = NULL;
|
|
|
|
|
json_t *jstileset = NULL;
|
|
|
|
|
int i;
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
|
2025-08-03 10:07:35 -04:00
|
|
|
dest->numtilesets = 0;
|
|
|
|
|
ATTEMPT {
|
2026-05-06 23:18:42 -04:00
|
|
|
CATCH(errctx, akgl_get_json_array_value(root, "tilesets", &tilesets))
|
2025-08-03 10:07:35 -04:00
|
|
|
for (i = 0; i < json_array_size((json_t *)tilesets); i++) {
|
2026-05-06 23:18:42 -04:00
|
|
|
CATCH(errctx, akgl_get_json_array_index_object((json_t *)tilesets, i, &jstileset));
|
2026-05-24 09:51:58 -04:00
|
|
|
CATCH(errctx, akgl_tilemap_load_tilesets_each(jstileset, dest, i, dirname));
|
2026-05-06 23:18:42 -04:00
|
|
|
CATCH(errctx, akgl_tilemap_compute_tileset_offsets(dest, i));
|
2025-08-03 10:07:35 -04:00
|
|
|
dest->numtilesets += 1;
|
|
|
|
|
}
|
|
|
|
|
} CLEANUP {
|
|
|
|
|
} PROCESS(errctx) {
|
|
|
|
|
} FINISH(errctx, true);
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
|
2025-08-03 10:07:35 -04:00
|
|
|
SUCCEED_RETURN(errctx);
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-30 01:10:31 -04:00
|
|
|
/**
|
Document what the functions actually do instead of that they can fail
The Doxygen comments were generated from the declarations, so 217 @throws
lines across 21 headers read "When the corresponding validation or operation
fails" and told a caller nothing beyond the status name. The @param lines were
the same shape: every output was "Output destination populated by the
function", every instance "Object to initialize, inspect, or modify".
Rewritten against the implementations, following the pattern libakstdlib
already uses:
- @throws names the condition. akgl_sprite_load_json separated AKERR_KEY
(absent) from AKERR_TYPE (present, wrong type) from AKERR_OUTOFBOUNDS
(filename too long, or array indexed past its end), and gained AKGL_ERR_SDL
and AKGL_ERR_HEAP, which it raises and never declared.
- Parameters say whether they are required, what a NULL means, and what is
written on a failure path. Where an argument is not checked, the doc says so:
akgl_heap_next_actor's dest is a crash on NULL, not an error, and
akgl_render_2d_frame_start dereferences self before testing it.
- The conventions move up to the file blocks so the per-function docs stay
short. json_helpers.h states once that absence is an error here and that
json_t * results are borrowed; heap.h explains the pool model and the
acquire asymmetry; physics.h carries the thrust/environmental/velocity table.
- Struct fields, enum values, macros and exported globals are documented,
including the dead ones - sprite_w/sprite_h, movetimer, p_scale and
timer_gravity are read by nothing, and say so.
Also fixes ten comments in error.h and audio.h that opened with /** rather
than /**<, so Doxygen attached them to the following entity and rendered the
text as part of the macro's value. Verified against the generated HTML.
Comments only - no declaration changed. Doxygen builds clean under
WARN_AS_ERROR, scripts/reindent.sh --check passes, 19/19 suites pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 11:02:20 -04:00
|
|
|
* @brief Turn one Tiled object into a live actor, creating it if it is not already registered.
|
|
|
|
|
*
|
|
|
|
|
* The object's name is the actor's registry key, which is what lets the same
|
|
|
|
|
* actor be placed by more than one object: the first placement creates it and
|
|
|
|
|
* binds the character named in the object's `character` property, and every
|
|
|
|
|
* later one just takes another reference. Either way the object's position,
|
|
|
|
|
* visibility, and layer are copied onto the actor and the object keeps a
|
|
|
|
|
* pointer to it.
|
|
|
|
|
*
|
|
|
|
|
* Not declared in tilemap.h -- reachable only through
|
|
|
|
|
* akgl_tilemap_load_layer_objects.
|
|
|
|
|
*
|
|
|
|
|
* @param curobj The tilemap object, with its `name`, `x`, `y`, and
|
|
|
|
|
* `visible` already read from JSON. Required, unchecked,
|
|
|
|
|
* dereferenced at once.
|
|
|
|
|
* @param layerdatavalue The object's JSON, for the custom properties --
|
|
|
|
|
* `character` and `state` -- that are not part of Tiled's
|
|
|
|
|
* own object fields. Required.
|
|
|
|
|
* @param layerid The layer this object sits on, copied onto the actor.
|
|
|
|
|
* @param dirname Directory to resolve paths against. Accepted for
|
|
|
|
|
* signature consistency; nothing here uses it.
|
2026-07-30 01:10:31 -04:00
|
|
|
* @return `NULL` on success, otherwise an error context owned by the caller.
|
Document what the functions actually do instead of that they can fail
The Doxygen comments were generated from the declarations, so 217 @throws
lines across 21 headers read "When the corresponding validation or operation
fails" and told a caller nothing beyond the status name. The @param lines were
the same shape: every output was "Output destination populated by the
function", every instance "Object to initialize, inspect, or modify".
Rewritten against the implementations, following the pattern libakstdlib
already uses:
- @throws names the condition. akgl_sprite_load_json separated AKERR_KEY
(absent) from AKERR_TYPE (present, wrong type) from AKERR_OUTOFBOUNDS
(filename too long, or array indexed past its end), and gained AKGL_ERR_SDL
and AKGL_ERR_HEAP, which it raises and never declared.
- Parameters say whether they are required, what a NULL means, and what is
written on a failure path. Where an argument is not checked, the doc says so:
akgl_heap_next_actor's dest is a crash on NULL, not an error, and
akgl_render_2d_frame_start dereferences self before testing it.
- The conventions move up to the file blocks so the per-function docs stay
short. json_helpers.h states once that absence is an error here and that
json_t * results are borrowed; heap.h explains the pool model and the
acquire asymmetry; physics.h carries the thrust/environmental/velocity table.
- Struct fields, enum values, macros and exported globals are documented,
including the dead ones - sprite_w/sprite_h, movetimer, p_scale and
timer_gravity are read by nothing, and say so.
Also fixes ten comments in error.h and audio.h that opened with /** rather
than /**<, so Doxygen attached them to the following entity and rendered the
text as part of the macro's value. Verified against the generated HTML.
Comments only - no declaration changed. Doxygen builds clean under
WARN_AS_ERROR, scripts/reindent.sh --check passes, 19/19 suites pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 11:02:20 -04:00
|
|
|
* @throws AKERR_KEY If the object's name is empty -- an actor has to be
|
|
|
|
|
* addressable -- if the `character` or `state` property is absent, or if
|
|
|
|
|
* the named character is not in #AKGL_REGISTRY_CHARACTER.
|
|
|
|
|
* @throws AKERR_TYPE If `character` is not declared `string` or `state` not
|
|
|
|
|
* declared `int`.
|
|
|
|
|
* @throws AKERR_NULLPOINTER If akgl_actor_initialize refuses the name.
|
|
|
|
|
* @throws AKGL_ERR_HEAP If the actor or string pool is exhausted.
|
|
|
|
|
*
|
|
|
|
|
* @note An existing actor's `character` and position are overwritten by each
|
|
|
|
|
* later placement, so two objects naming one actor leave it wherever the
|
|
|
|
|
* last one put it rather than producing two.
|
2026-07-30 01:10:31 -04:00
|
|
|
*/
|
2026-05-24 09:51:58 -04:00
|
|
|
akerr_ErrorContext *akgl_tilemap_load_layer_object_actor(akgl_TilemapObject *curobj, json_t *layerdatavalue, int layerid, akgl_String *dirname)
|
2025-08-03 10:07:35 -04:00
|
|
|
{
|
|
|
|
|
PREPARE_ERROR(errctx);
|
2026-05-06 23:18:42 -04:00
|
|
|
akgl_String *tmpstr = NULL;
|
|
|
|
|
akgl_Actor *actorobj = NULL;
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
|
2026-05-06 23:18:42 -04:00
|
|
|
curobj->type = AKGL_TILEMAP_OBJECT_TYPE_ACTOR;
|
2025-08-03 10:07:35 -04:00
|
|
|
if ( strlen((char *)&curobj->name) == 0 ) {
|
2026-05-03 23:57:55 -04:00
|
|
|
FAIL_RETURN(errctx, AKERR_KEY, "Actor in tile object layer cannot have empty name");
|
2025-08-03 10:07:35 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ATTEMPT {
|
2026-05-06 23:18:42 -04:00
|
|
|
CATCH(errctx, akgl_heap_next_string(&tmpstr));
|
|
|
|
|
actorobj = SDL_GetPointerProperty(AKGL_REGISTRY_ACTOR, (char *)&curobj->name, NULL);
|
2025-08-03 10:07:35 -04:00
|
|
|
if ( actorobj == NULL ) {
|
2026-05-06 23:18:42 -04:00
|
|
|
CATCH(errctx, akgl_heap_next_actor(&actorobj));
|
|
|
|
|
CATCH(errctx, akgl_actor_initialize((akgl_Actor *)actorobj, (char *)&curobj->name));
|
|
|
|
|
CATCH(errctx, akgl_get_json_properties_string((json_t *)layerdatavalue, "character", &tmpstr));
|
2025-08-03 10:07:35 -04:00
|
|
|
CATCH(errctx,
|
2026-05-06 23:18:42 -04:00
|
|
|
akgl_actor_set_character(
|
|
|
|
|
(akgl_Actor *)actorobj,
|
2025-08-03 10:07:35 -04:00
|
|
|
(char *)&tmpstr->data
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
actorobj->refcount += 1;
|
|
|
|
|
}
|
2026-05-06 23:18:42 -04:00
|
|
|
CATCH(errctx, akgl_get_json_properties_integer((json_t *)layerdatavalue, "state", &actorobj->state));
|
2025-08-03 10:07:35 -04:00
|
|
|
} CLEANUP {
|
|
|
|
|
if ( tmpstr != NULL ) {
|
2026-05-06 23:18:42 -04:00
|
|
|
IGNORE(akgl_heap_release_string(tmpstr));
|
2025-08-03 10:07:35 -04:00
|
|
|
}
|
|
|
|
|
} PROCESS(errctx) {
|
|
|
|
|
} FINISH(errctx, true);
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
|
2025-08-03 10:07:35 -04:00
|
|
|
actorobj->layer = layerid;
|
|
|
|
|
actorobj->x = curobj->x;
|
|
|
|
|
actorobj->y = curobj->y;
|
|
|
|
|
actorobj->visible = curobj->visible;
|
2026-05-06 23:18:42 -04:00
|
|
|
curobj->actorptr = (akgl_Actor *)actorobj;
|
2025-08-03 10:07:35 -04:00
|
|
|
|
|
|
|
|
SUCCEED_RETURN(errctx);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-24 09:51:58 -04:00
|
|
|
akerr_ErrorContext *akgl_tilemap_load_layer_objects(akgl_Tilemap *dest, json_t *root, int layerid, akgl_String *dirname)
|
2025-08-03 10:07:35 -04:00
|
|
|
{
|
|
|
|
|
PREPARE_ERROR(errctx);
|
|
|
|
|
json_t *layerdata = NULL;
|
|
|
|
|
json_t *layerdatavalue = NULL;
|
|
|
|
|
int j;
|
|
|
|
|
int len;
|
2026-05-06 23:18:42 -04:00
|
|
|
akgl_TilemapLayer *curlayer = NULL;
|
|
|
|
|
akgl_TilemapObject *curobj = NULL;
|
|
|
|
|
akgl_String *tmpstr = NULL;
|
2025-08-03 10:07:35 -04:00
|
|
|
|
2026-05-03 23:57:55 -04:00
|
|
|
FAIL_ZERO_RETURN(errctx, dest, AKERR_NULLPOINTER, "NULL destination tilemap reference");
|
|
|
|
|
FAIL_ZERO_RETURN(errctx, root, AKERR_NULLPOINTER, "NULL tilemap root reference");
|
2025-08-03 10:07:35 -04:00
|
|
|
|
2026-06-02 17:11:16 -04:00
|
|
|
PASS(errctx, akgl_get_json_array_value(root, "objects", &layerdata));
|
|
|
|
|
len = json_array_size((json_t *)layerdata);
|
|
|
|
|
curlayer = &dest->layers[layerid];
|
|
|
|
|
for ( j = 0; j < len; j++ ) {
|
|
|
|
|
PASS(errctx, akgl_get_json_array_index_object((json_t *)layerdata, j, &layerdatavalue));
|
|
|
|
|
curobj = &curlayer->objects[j];
|
|
|
|
|
PASS(errctx, akgl_get_json_string_value((json_t *)layerdatavalue, "name", &tmpstr));
|
|
|
|
|
strncpy((char *)curobj->name, tmpstr->data, AKGL_ACTOR_MAX_NAME_LENGTH);
|
|
|
|
|
PASS(errctx, akgl_heap_release_string(tmpstr));
|
|
|
|
|
PASS(errctx, akgl_get_json_number_value((json_t *)layerdatavalue, "x", &curobj->x));
|
|
|
|
|
PASS(errctx, akgl_get_json_number_value((json_t *)layerdatavalue, "y", &curobj->y));
|
|
|
|
|
PASS(errctx, akgl_get_json_boolean_value((json_t *)layerdatavalue, "visible", &curobj->visible));
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
|
2026-06-02 17:11:16 -04:00
|
|
|
PASS(errctx, akgl_get_json_string_value((json_t *)layerdatavalue, "type", &tmpstr));
|
|
|
|
|
if ( strcmp(tmpstr->data, "actor") == 0 ) {
|
|
|
|
|
PASS(errctx, akgl_tilemap_load_layer_object_actor(curobj, layerdatavalue, layerid, dirname));
|
|
|
|
|
} else if ( strcmp(tmpstr->data, "perspective") == 0 ) {
|
|
|
|
|
curobj->visible = false;
|
|
|
|
|
if ( strcmp((char *)curobj->name, "p_foreground") == 0 ) {
|
|
|
|
|
dest->p_foreground_y = curobj->y;
|
|
|
|
|
PASS(errctx, akgl_get_json_integer_value((json_t *)layerdatavalue, "height", &dest->p_foreground_h));
|
|
|
|
|
PASS(errctx, akgl_get_json_properties_float((json_t *)layerdatavalue, "scale", &dest->p_foreground_scale));
|
|
|
|
|
} else if ( strcmp((char *)curobj->name, "p_vanishing") == 0 ) {
|
|
|
|
|
dest->p_vanishing_y = curobj->y;
|
|
|
|
|
PASS(errctx, akgl_get_json_integer_value((json_t *)layerdatavalue, "height", &dest->p_vanishing_h));
|
|
|
|
|
PASS(errctx, akgl_get_json_properties_float((json_t *)layerdatavalue, "scale", &dest->p_vanishing_scale));
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
}
|
|
|
|
|
}
|
2026-06-02 17:11:16 -04:00
|
|
|
layerdatavalue = NULL;
|
|
|
|
|
}
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
|
2025-08-03 10:07:35 -04:00
|
|
|
SUCCEED_RETURN(errctx);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-24 09:51:58 -04:00
|
|
|
akerr_ErrorContext *akgl_tilemap_load_layer_tile(akgl_Tilemap *dest, json_t *root, int layerid, akgl_String *dirname)
|
2025-08-03 10:07:35 -04:00
|
|
|
{
|
|
|
|
|
PREPARE_ERROR(errctx);
|
|
|
|
|
json_t *layerdata = NULL;
|
|
|
|
|
int j;
|
|
|
|
|
int layerdatalen;
|
|
|
|
|
|
2026-05-03 23:57:55 -04:00
|
|
|
FAIL_ZERO_RETURN(errctx, dest, AKERR_NULLPOINTER, "NULL destination tilemap reference");
|
|
|
|
|
FAIL_ZERO_RETURN(errctx, root, AKERR_NULLPOINTER, "NULL tilemap root reference");
|
2026-05-24 09:51:58 -04:00
|
|
|
FAIL_ZERO_RETURN(errctx, dirname, AKERR_NULLPOINTER, "dirname");
|
2025-08-03 10:07:35 -04:00
|
|
|
|
|
|
|
|
ATTEMPT {
|
2026-05-06 23:18:42 -04:00
|
|
|
CATCH(errctx, akgl_get_json_integer_value(root, "height", &dest->layers[layerid].height));
|
|
|
|
|
CATCH(errctx, akgl_get_json_integer_value(root, "width", &dest->layers[layerid].width));
|
|
|
|
|
CATCH(errctx, akgl_get_json_array_value(root, "data", &layerdata));
|
2025-08-03 10:07:35 -04:00
|
|
|
layerdatalen = (dest->layers[layerid].width * dest->layers[layerid].height);
|
2026-05-06 23:18:42 -04:00
|
|
|
if ( layerdatalen >= (AKGL_TILEMAP_MAX_WIDTH * AKGL_TILEMAP_MAX_HEIGHT) ) {
|
2026-05-03 23:57:55 -04:00
|
|
|
FAIL_BREAK(errctx, AKERR_OUTOFBOUNDS, "Map layer exceeds the maximum size");
|
2025-08-03 10:07:35 -04:00
|
|
|
}
|
|
|
|
|
for ( j = 0; j < layerdatalen; j++ ) {
|
2026-05-06 23:18:42 -04:00
|
|
|
CATCH(errctx, akgl_get_json_array_index_integer(layerdata, j, &dest->layers[layerid].data[j]));
|
2025-08-03 10:07:35 -04:00
|
|
|
}
|
|
|
|
|
} CLEANUP {
|
|
|
|
|
} PROCESS(errctx) {
|
|
|
|
|
} FINISH(errctx, true);
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
|
2025-08-03 10:07:35 -04:00
|
|
|
SUCCEED_RETURN(errctx);
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-30 01:10:31 -04:00
|
|
|
/**
|
Document what the functions actually do instead of that they can fail
The Doxygen comments were generated from the declarations, so 217 @throws
lines across 21 headers read "When the corresponding validation or operation
fails" and told a caller nothing beyond the status name. The @param lines were
the same shape: every output was "Output destination populated by the
function", every instance "Object to initialize, inspect, or modify".
Rewritten against the implementations, following the pattern libakstdlib
already uses:
- @throws names the condition. akgl_sprite_load_json separated AKERR_KEY
(absent) from AKERR_TYPE (present, wrong type) from AKERR_OUTOFBOUNDS
(filename too long, or array indexed past its end), and gained AKGL_ERR_SDL
and AKGL_ERR_HEAP, which it raises and never declared.
- Parameters say whether they are required, what a NULL means, and what is
written on a failure path. Where an argument is not checked, the doc says so:
akgl_heap_next_actor's dest is a crash on NULL, not an error, and
akgl_render_2d_frame_start dereferences self before testing it.
- The conventions move up to the file blocks so the per-function docs stay
short. json_helpers.h states once that absence is an error here and that
json_t * results are borrowed; heap.h explains the pool model and the
acquire asymmetry; physics.h carries the thrust/environmental/velocity table.
- Struct fields, enum values, macros and exported globals are documented,
including the dead ones - sprite_w/sprite_h, movetimer, p_scale and
timer_gravity are read by nothing, and say so.
Also fixes ten comments in error.h and audio.h that opened with /** rather
than /**<, so Doxygen attached them to the following entity and rendered the
text as part of the macro's value. Verified against the generated HTML.
Comments only - no declaration changed. Doxygen builds clean under
WARN_AS_ERROR, scripts/reindent.sh --check passes, 19/19 suites pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 11:02:20 -04:00
|
|
|
* @brief Load one image layer: upload its image as a single texture.
|
|
|
|
|
*
|
|
|
|
|
* An image layer is one picture rather than a grid, which is what a parallax
|
|
|
|
|
* backdrop wants. The layer's `width` and `height` are taken from the loaded
|
|
|
|
|
* texture rather than from the JSON, so they are always the true pixel size.
|
|
|
|
|
*
|
|
|
|
|
* Not declared in tilemap.h -- reachable only through akgl_tilemap_load_layers.
|
|
|
|
|
*
|
|
|
|
|
* @param dest The map to load into. Required.
|
|
|
|
|
* @param root The layer's JSON object. Required.
|
|
|
|
|
* @param layerid Which layer slot to fill. Not bounds-checked.
|
|
|
|
|
* @param dirname Directory to resolve the layer's `image` path against.
|
|
|
|
|
* Required. Joined with a `/` rather than run through
|
|
|
|
|
* akgl_path_relative, so unlike a tileset image this path is not
|
|
|
|
|
* canonicalized and an absolute one will not work.
|
2026-07-30 01:10:31 -04:00
|
|
|
* @return `NULL` on success, otherwise an error context owned by the caller.
|
Document what the functions actually do instead of that they can fail
The Doxygen comments were generated from the declarations, so 217 @throws
lines across 21 headers read "When the corresponding validation or operation
fails" and told a caller nothing beyond the status name. The @param lines were
the same shape: every output was "Output destination populated by the
function", every instance "Object to initialize, inspect, or modify".
Rewritten against the implementations, following the pattern libakstdlib
already uses:
- @throws names the condition. akgl_sprite_load_json separated AKERR_KEY
(absent) from AKERR_TYPE (present, wrong type) from AKERR_OUTOFBOUNDS
(filename too long, or array indexed past its end), and gained AKGL_ERR_SDL
and AKGL_ERR_HEAP, which it raises and never declared.
- Parameters say whether they are required, what a NULL means, and what is
written on a failure path. Where an argument is not checked, the doc says so:
akgl_heap_next_actor's dest is a crash on NULL, not an error, and
akgl_render_2d_frame_start dereferences self before testing it.
- The conventions move up to the file blocks so the per-function docs stay
short. json_helpers.h states once that absence is an error here and that
json_t * results are borrowed; heap.h explains the pool model and the
acquire asymmetry; physics.h carries the thrust/environmental/velocity table.
- Struct fields, enum values, macros and exported globals are documented,
including the dead ones - sprite_w/sprite_h, movetimer, p_scale and
timer_gravity are read by nothing, and say so.
Also fixes ten comments in error.h and audio.h that opened with /** rather
than /**<, so Doxygen attached them to the following entity and rendered the
text as part of the macro's value. Verified against the generated HTML.
Comments only - no declaration changed. Doxygen builds clean under
WARN_AS_ERROR, scripts/reindent.sh --check passes, 19/19 suites pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 11:02:20 -04:00
|
|
|
* @throws AKERR_NULLPOINTER If @p dest, @p root, or @p dirname is `NULL`.
|
|
|
|
|
* @throws AKERR_KEY If the layer has no `image`.
|
|
|
|
|
* @throws AKERR_TYPE If `image` is not a string.
|
|
|
|
|
* @throws AKGL_ERR_SDL If the image cannot be loaded. The message carries
|
|
|
|
|
* `SDL_GetError()`.
|
|
|
|
|
* @throws AKGL_ERR_HEAP If the string pool is exhausted.
|
|
|
|
|
*
|
|
|
|
|
* @note The joined path is truncated at
|
|
|
|
|
* #AKGL_TILEMAP_MAX_TILESET_FILENAME_SIZE without complaint, so an
|
|
|
|
|
* over-long path fails as a missing file rather than as a length error.
|
2026-07-30 01:10:31 -04:00
|
|
|
*/
|
2026-05-24 09:51:58 -04:00
|
|
|
akerr_ErrorContext *akgl_tilemap_load_layer_image(akgl_Tilemap *dest, json_t *root, int layerid, akgl_String *dirname)
|
2026-05-13 08:02:59 -04:00
|
|
|
{
|
|
|
|
|
PREPARE_ERROR(errctx);
|
|
|
|
|
akgl_String *tmpstr;
|
|
|
|
|
akgl_String *fpath;
|
|
|
|
|
|
|
|
|
|
FAIL_ZERO_RETURN(errctx, dest, AKERR_NULLPOINTER, "NULL destination tilemap reference");
|
|
|
|
|
FAIL_ZERO_RETURN(errctx, root, AKERR_NULLPOINTER, "NULL tilemap root reference");
|
2026-05-24 09:51:58 -04:00
|
|
|
FAIL_ZERO_RETURN(errctx, dirname, AKERR_NULLPOINTER, "dirname");
|
2026-05-13 08:02:59 -04:00
|
|
|
|
|
|
|
|
ATTEMPT {
|
|
|
|
|
CATCH(errctx, akgl_heap_next_string(&tmpstr));
|
|
|
|
|
CATCH(errctx, akgl_heap_next_string(&fpath));
|
|
|
|
|
CATCH(errctx, akgl_get_json_string_value(root, "image", &tmpstr));
|
|
|
|
|
|
2026-05-24 09:51:58 -04:00
|
|
|
DISABLE_GCC_WARNING_FORMAT_TRUNCATION
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
snprintf((char *)&fpath->data,
|
|
|
|
|
AKGL_TILEMAP_MAX_TILESET_FILENAME_SIZE,
|
|
|
|
|
"%s/%s",
|
|
|
|
|
dirname->data,
|
|
|
|
|
tmpstr->data
|
|
|
|
|
);
|
2026-05-24 09:51:58 -04:00
|
|
|
RESTORE_GCC_WARNINGS
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
|
|
|
|
|
dest->layers[layerid].texture = IMG_LoadTexture(renderer->sdl_renderer, (char *)fpath->data);
|
2026-05-13 08:02:59 -04:00
|
|
|
FAIL_ZERO_BREAK(errctx, dest->layers[layerid].texture, AKGL_ERR_SDL, "%s", SDL_GetError());
|
|
|
|
|
dest->layers[layerid].width = dest->layers[layerid].texture->w;
|
|
|
|
|
dest->layers[layerid].height = dest->layers[layerid].texture->h;
|
|
|
|
|
} CLEANUP {
|
|
|
|
|
IGNORE(akgl_heap_release_string(tmpstr));
|
|
|
|
|
IGNORE(akgl_heap_release_string(fpath));
|
|
|
|
|
} PROCESS(errctx) {
|
|
|
|
|
} FINISH(errctx, true);
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
|
2026-05-13 08:02:59 -04:00
|
|
|
SUCCEED_RETURN(errctx);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-24 09:51:58 -04:00
|
|
|
akerr_ErrorContext *akgl_tilemap_load_layers(akgl_Tilemap *dest, json_t *root, akgl_String *dirname)
|
2025-08-03 10:07:35 -04:00
|
|
|
{
|
|
|
|
|
PREPARE_ERROR(errctx);
|
2026-05-06 23:18:42 -04:00
|
|
|
FAIL_ZERO_RETURN(errctx, dest, AKERR_NULLPOINTER, "akgl_tilemap_load_layers received NULL tilemap pointer");
|
|
|
|
|
FAIL_ZERO_RETURN(errctx, root, AKERR_NULLPOINTER, "akgl_tilemap_load_layers received NULL json object pointer");
|
2026-05-24 09:51:58 -04:00
|
|
|
FAIL_ZERO_RETURN(errctx, dirname, AKERR_NULLPOINTER, "dirname");
|
2025-08-03 10:07:35 -04:00
|
|
|
json_t *layers = NULL;
|
|
|
|
|
json_t *layer = NULL;
|
2026-05-06 23:18:42 -04:00
|
|
|
akgl_String *tmpstr = NULL;
|
2025-08-03 10:07:35 -04:00
|
|
|
int i;
|
2026-05-13 08:02:59 -04:00
|
|
|
int layerid = 0;
|
|
|
|
|
int tmpint = 0;
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
|
2025-08-03 10:07:35 -04:00
|
|
|
ATTEMPT {
|
2026-05-06 23:18:42 -04:00
|
|
|
CATCH(errctx, akgl_get_json_array_value(root, "layers", &layers));
|
2025-08-03 10:07:35 -04:00
|
|
|
dest->numlayers = json_array_size((json_t *)layers);
|
|
|
|
|
for ( i = 0; i < dest->numlayers; i++) {
|
2026-05-06 23:18:42 -04:00
|
|
|
if ( i >= AKGL_TILEMAP_MAX_LAYERS ) {
|
2026-05-03 23:57:55 -04:00
|
|
|
FAIL_BREAK(errctx, AKERR_OUTOFBOUNDS, "Map exceeds the maximum number of layers");
|
2025-08-03 10:07:35 -04:00
|
|
|
}
|
2026-05-06 23:18:42 -04:00
|
|
|
CATCH(errctx, akgl_get_json_array_index_object((json_t *)layers, i, &layer));
|
|
|
|
|
CATCH(errctx, akgl_get_json_integer_value((json_t *)layer, "id", &tmpint));
|
2026-05-13 08:02:59 -04:00
|
|
|
CATCH(errctx, akgl_get_json_number_value((json_t *)layer, "opacity", &dest->layers[layerid].opacity));
|
|
|
|
|
CATCH(errctx, akgl_get_json_boolean_value((json_t *)layer, "visible", &dest->layers[layerid].visible));
|
|
|
|
|
CATCH(errctx, akgl_get_json_integer_value((json_t *)layer, "id", &dest->layers[layerid].id));
|
|
|
|
|
CATCH(errctx, akgl_get_json_integer_value((json_t *)layer, "x", &dest->layers[layerid].x));
|
|
|
|
|
CATCH(errctx, akgl_get_json_integer_value((json_t *)layer, "y", &dest->layers[layerid].y));
|
2025-08-03 10:07:35 -04:00
|
|
|
|
2026-05-06 23:18:42 -04:00
|
|
|
CATCH(errctx, akgl_get_json_string_value((json_t *)layer, "type", &tmpstr));
|
2026-05-13 08:02:59 -04:00
|
|
|
SDL_Log("Layer %d has type %s", layerid, tmpstr->data);
|
2025-08-03 10:07:35 -04:00
|
|
|
if ( strncmp((char *)tmpstr->data, "objectgroup", strlen((char *)tmpstr->data)) == 0 ) {
|
2026-05-13 08:02:59 -04:00
|
|
|
dest->layers[layerid].type = AKGL_TILEMAP_LAYER_TYPE_OBJECTS;
|
2026-05-24 09:51:58 -04:00
|
|
|
CATCH(errctx, akgl_tilemap_load_layer_objects((akgl_Tilemap *)dest, (json_t *)layer, layerid, dirname));
|
2025-08-03 10:07:35 -04:00
|
|
|
} else if ( strncmp((char *)tmpstr->data, "tilelayer", strlen((char *)tmpstr->data)) == 0 ) {
|
2026-05-13 08:02:59 -04:00
|
|
|
dest->layers[layerid].type = AKGL_TILEMAP_LAYER_TYPE_TILES;
|
2026-05-24 09:51:58 -04:00
|
|
|
CATCH(errctx, akgl_tilemap_load_layer_tile((akgl_Tilemap *)dest, (json_t *)layer, layerid, dirname));
|
2026-05-13 08:02:59 -04:00
|
|
|
} else if ( strncmp((char *)tmpstr->data, "imagelayer", strlen((char *)tmpstr->data)) == 0 ) {
|
|
|
|
|
dest->layers[layerid].type = AKGL_TILEMAP_LAYER_TYPE_IMAGE;
|
2026-05-24 09:51:58 -04:00
|
|
|
CATCH(errctx, akgl_tilemap_load_layer_image((akgl_Tilemap *)dest, (json_t *)layer, layerid, dirname));
|
2025-08-03 10:07:35 -04:00
|
|
|
}
|
|
|
|
|
layer = NULL;
|
2026-05-13 08:02:59 -04:00
|
|
|
layerid += 1;
|
2025-08-03 10:07:35 -04:00
|
|
|
}
|
|
|
|
|
} CLEANUP {
|
|
|
|
|
} PROCESS(errctx) {
|
|
|
|
|
} FINISH(errctx, true);
|
|
|
|
|
SUCCEED_RETURN(errctx);
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-30 01:10:31 -04:00
|
|
|
/**
|
Document what the functions actually do instead of that they can fail
The Doxygen comments were generated from the declarations, so 217 @throws
lines across 21 headers read "When the corresponding validation or operation
fails" and told a caller nothing beyond the status name. The @param lines were
the same shape: every output was "Output destination populated by the
function", every instance "Object to initialize, inspect, or modify".
Rewritten against the implementations, following the pattern libakstdlib
already uses:
- @throws names the condition. akgl_sprite_load_json separated AKERR_KEY
(absent) from AKERR_TYPE (present, wrong type) from AKERR_OUTOFBOUNDS
(filename too long, or array indexed past its end), and gained AKGL_ERR_SDL
and AKGL_ERR_HEAP, which it raises and never declared.
- Parameters say whether they are required, what a NULL means, and what is
written on a failure path. Where an argument is not checked, the doc says so:
akgl_heap_next_actor's dest is a crash on NULL, not an error, and
akgl_render_2d_frame_start dereferences self before testing it.
- The conventions move up to the file blocks so the per-function docs stay
short. json_helpers.h states once that absence is an error here and that
json_t * results are borrowed; heap.h explains the pool model and the
acquire asymmetry; physics.h carries the thrust/environmental/velocity table.
- Struct fields, enum values, macros and exported globals are documented,
including the dead ones - sprite_w/sprite_h, movetimer, p_scale and
timer_gravity are read by nothing, and say so.
Also fixes ten comments in error.h and audio.h that opened with /** rather
than /**<, so Doxygen attached them to the following entity and rendered the
text as part of the macro's value. Verified against the generated HTML.
Comments only - no declaration changed. Doxygen builds clean under
WARN_AS_ERROR, scripts/reindent.sh --check passes, 19/19 suites pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 11:02:20 -04:00
|
|
|
* @brief Give the map its own physics backend, if it asked for one.
|
|
|
|
|
*
|
|
|
|
|
* A map with a `physics.model` custom property gets its own backend, configured
|
|
|
|
|
* from `physics.gravity.x`/`.y`/`.z` and `physics.drag.x`/`.y`/`.z`, and
|
|
|
|
|
* `use_own_physics` is set so a caller knows to simulate through it. Each
|
|
|
|
|
* constant defaults to 0.0 when absent, so a map can name a model and override
|
|
|
|
|
* only what it cares about.
|
|
|
|
|
*
|
|
|
|
|
* Absence is the normal case at every level: a map with no properties at all, or
|
|
|
|
|
* with properties but no `physics.model`, uses the game's global backend and
|
|
|
|
|
* this returns success. That is why the AKERR_KEY handlers here are not error
|
|
|
|
|
* paths -- they are the "map did not ask" path.
|
|
|
|
|
*
|
|
|
|
|
* Not declared in tilemap.h -- reachable only through akgl_tilemap_load.
|
|
|
|
|
*
|
|
|
|
|
* @param dest The map to configure. Required in practice; not checked here,
|
|
|
|
|
* since akgl_tilemap_load has already done so.
|
|
|
|
|
* @param root The map's root JSON object. Required, likewise.
|
|
|
|
|
* @return `NULL` on success -- including when the map declared no physics at
|
|
|
|
|
* all -- otherwise an error context owned by the caller.
|
|
|
|
|
* @throws AKERR_KEY If `physics.model` names a backend that does not exist.
|
|
|
|
|
* @throws AKERR_TYPE If `physics.model` is not declared `string`, or one of the
|
|
|
|
|
* six constants is not declared `float`.
|
|
|
|
|
* @throws AKERR_NULLPOINTER If akgl_physics_factory refuses its arguments.
|
|
|
|
|
* @throws AKGL_ERR_HEAP If the string pool is exhausted.
|
2026-07-30 01:10:31 -04:00
|
|
|
*/
|
2026-06-02 17:11:16 -04:00
|
|
|
akerr_ErrorContext *akgl_tilemap_load_physics(akgl_Tilemap *dest, json_t *root)
|
|
|
|
|
{
|
|
|
|
|
PREPARE_ERROR(e);
|
|
|
|
|
json_t *props = NULL;
|
|
|
|
|
akgl_String *tmpval = NULL;
|
|
|
|
|
double defzero = 0.0;
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
|
2026-06-02 17:11:16 -04:00
|
|
|
ATTEMPT {
|
|
|
|
|
CATCH(e, akgl_heap_next_string(&tmpval));
|
|
|
|
|
CATCH(e, akgl_get_json_array_value((json_t *)root, "properties", &props));
|
|
|
|
|
} CLEANUP {
|
|
|
|
|
IGNORE(akgl_heap_release_string(tmpval));
|
|
|
|
|
} PROCESS(e) {
|
|
|
|
|
} HANDLE(e, AKERR_KEY) {
|
|
|
|
|
// Map has no properties, do nothing
|
|
|
|
|
SDL_Log("Map has no properties");
|
|
|
|
|
SUCCEED_RETURN(e);
|
|
|
|
|
} FINISH(e, true);
|
|
|
|
|
|
|
|
|
|
ATTEMPT {
|
|
|
|
|
CATCH(e, akgl_heap_next_string(&tmpval));
|
|
|
|
|
CATCH(e, akgl_get_json_properties_string(
|
|
|
|
|
root,
|
|
|
|
|
"physics.model",
|
|
|
|
|
&tmpval
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
PASS(e, akgl_physics_factory(&dest->physics, tmpval));
|
|
|
|
|
dest->use_own_physics = true;
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
|
2026-06-02 17:11:16 -04:00
|
|
|
CATCH(e, akgl_get_json_with_default(
|
|
|
|
|
akgl_get_json_properties_double(
|
|
|
|
|
root, "physics.gravity.x", &dest->physics.gravity_x
|
|
|
|
|
),
|
|
|
|
|
(void *)&defzero,
|
|
|
|
|
(void *)&dest->physics.gravity_x,
|
|
|
|
|
sizeof(double)));
|
|
|
|
|
CATCH(e, akgl_get_json_with_default(
|
|
|
|
|
akgl_get_json_properties_double(
|
|
|
|
|
root, "physics.gravity.y", &dest->physics.gravity_y
|
|
|
|
|
),
|
|
|
|
|
(void *)&defzero,
|
|
|
|
|
(void *)&dest->physics.gravity_y,
|
|
|
|
|
sizeof(double)));
|
|
|
|
|
CATCH(e, akgl_get_json_with_default(
|
|
|
|
|
akgl_get_json_properties_double(
|
|
|
|
|
root, "physics.gravity.z", &dest->physics.gravity_z
|
|
|
|
|
),
|
|
|
|
|
(void *)&defzero,
|
|
|
|
|
(void *)&dest->physics.gravity_z,
|
|
|
|
|
sizeof(double)));
|
|
|
|
|
CATCH(e, akgl_get_json_with_default(
|
|
|
|
|
akgl_get_json_properties_double(
|
|
|
|
|
root, "physics.drag.x", &dest->physics.drag_x
|
|
|
|
|
),
|
|
|
|
|
(void *)&defzero,
|
|
|
|
|
(void *)&dest->physics.drag_x,
|
|
|
|
|
sizeof(double)));
|
|
|
|
|
CATCH(e, akgl_get_json_with_default(
|
|
|
|
|
akgl_get_json_properties_double(
|
|
|
|
|
root, "physics.drag.y", &dest->physics.drag_y
|
|
|
|
|
),
|
|
|
|
|
(void *)&defzero,
|
|
|
|
|
(void *)&dest->physics.drag_y,
|
|
|
|
|
sizeof(double)));
|
|
|
|
|
CATCH(e, akgl_get_json_with_default(
|
|
|
|
|
akgl_get_json_properties_double(
|
|
|
|
|
root, "physics.drag.z", &dest->physics.drag_z
|
|
|
|
|
),
|
|
|
|
|
(void *)&defzero,
|
|
|
|
|
(void *)&dest->physics.drag_z,
|
|
|
|
|
sizeof(double)));
|
|
|
|
|
} CLEANUP {
|
|
|
|
|
IGNORE(akgl_heap_release_string(tmpval));
|
|
|
|
|
} PROCESS(e) {
|
|
|
|
|
} HANDLE(e, AKERR_KEY) {
|
|
|
|
|
SDL_Log("Map uses game physics");
|
|
|
|
|
} FINISH(e, true);
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
|
2026-06-02 17:11:16 -04:00
|
|
|
SUCCEED_RETURN(e);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-06 23:18:42 -04:00
|
|
|
akerr_ErrorContext *akgl_tilemap_load(char *fname, akgl_Tilemap *dest)
|
2025-08-03 10:07:35 -04:00
|
|
|
{
|
|
|
|
|
PREPARE_ERROR(errctx);
|
|
|
|
|
json_t *json = NULL;
|
2026-05-06 23:18:42 -04:00
|
|
|
//akgl_String *tmpstr = NULL;
|
2025-08-03 10:07:35 -04:00
|
|
|
json_error_t error;
|
2026-05-24 09:51:58 -04:00
|
|
|
akgl_String *dirnamestr = NULL;
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
|
2026-05-03 23:57:55 -04:00
|
|
|
FAIL_ZERO_RETURN(errctx, fname, AKERR_NULLPOINTER, "load_tilemap received null filename");
|
|
|
|
|
FAIL_ZERO_RETURN(errctx, dest, AKERR_NULLPOINTER, "load_tilemap received null tilemap");
|
2025-08-03 10:07:35 -04:00
|
|
|
|
2026-05-06 23:18:42 -04:00
|
|
|
memset(dest, 0x00, sizeof(akgl_Tilemap));
|
2026-05-13 23:36:49 -04:00
|
|
|
dest->p_foreground_scale = 1.0;
|
|
|
|
|
dest->p_vanishing_scale = 1.0;
|
2025-08-03 10:07:35 -04:00
|
|
|
|
2026-05-24 09:51:58 -04:00
|
|
|
PASS(errctx, akgl_heap_next_string(&dirnamestr));
|
2025-08-03 10:07:35 -04:00
|
|
|
ATTEMPT {
|
2026-05-06 23:18:42 -04:00
|
|
|
//CATCH(errctx, akgl_heap_next_string(&tmpstr));
|
|
|
|
|
//CATCH(errctx, akgl_string_initialize(tmpstr, NULL));
|
|
|
|
|
//SDL_snprintf(tmpstr->data, AKGL_MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), fname);
|
2026-07-31 08:27:15 -04:00
|
|
|
CATCH(errctx, aksl_realpath(fname, (char *)&dirnamestr->data, sizeof(dirnamestr->data)));
|
2026-05-24 09:51:58 -04:00
|
|
|
dirname((char *)&dirnamestr->data);
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
|
2025-08-09 08:54:12 -04:00
|
|
|
json = json_load_file(fname, 0, &error);
|
2025-08-03 10:07:35 -04:00
|
|
|
FAIL_ZERO_BREAK(
|
|
|
|
|
errctx,
|
|
|
|
|
json,
|
2026-05-03 23:57:55 -04:00
|
|
|
AKERR_NULLPOINTER,
|
2025-08-03 10:07:35 -04:00
|
|
|
"Error while loading tilemap from %s on line %d: %s-",
|
2025-08-09 08:54:12 -04:00
|
|
|
fname,
|
2025-08-03 10:07:35 -04:00
|
|
|
error.line,
|
|
|
|
|
error.text
|
|
|
|
|
);
|
2026-06-02 17:11:16 -04:00
|
|
|
CATCH(errctx, akgl_tilemap_load_physics(dest, json));
|
2026-05-06 23:18:42 -04:00
|
|
|
CATCH(errctx, akgl_get_json_integer_value((json_t *)json, "tileheight", &dest->tileheight));
|
|
|
|
|
CATCH(errctx, akgl_get_json_integer_value((json_t *)json, "tilewidth", &dest->tilewidth));
|
|
|
|
|
CATCH(errctx, akgl_get_json_integer_value((json_t *)json, "height", &dest->height));
|
|
|
|
|
CATCH(errctx, akgl_get_json_integer_value((json_t *)json, "width", &dest->width));
|
2025-08-03 10:07:35 -04:00
|
|
|
|
|
|
|
|
dest->orientation = 0;
|
2026-05-06 23:18:42 -04:00
|
|
|
if ( (dest->width * dest->height) >= (AKGL_TILEMAP_MAX_WIDTH * AKGL_TILEMAP_MAX_HEIGHT) ) {
|
2026-05-03 23:57:55 -04:00
|
|
|
FAIL_RETURN(errctx, AKERR_OUTOFBOUNDS, "Map exceeds the maximum size");
|
2025-08-03 10:07:35 -04:00
|
|
|
}
|
|
|
|
|
|
2026-05-24 09:51:58 -04:00
|
|
|
CATCH(errctx, akgl_tilemap_load_layers((akgl_Tilemap *)dest, (json_t *)json, dirnamestr));
|
|
|
|
|
CATCH(errctx, akgl_tilemap_load_tilesets((akgl_Tilemap *)dest, (json_t *)json, dirnamestr));
|
2026-05-13 09:57:24 -04:00
|
|
|
|
|
|
|
|
if ( dest->p_foreground_y && dest->p_vanishing_y ) {
|
|
|
|
|
// How much bigger is the foreground vs the vanishing point?
|
|
|
|
|
// if vanishing is height 16, and foreground is height 32, that is a 2x scale difference
|
2026-05-13 23:36:49 -04:00
|
|
|
/* dest->p_scale = ((float)dest->p_foreground_h / (float)dest->p_vanishing_h); */
|
|
|
|
|
/* SDL_Log("Map perspective scale is (%d/%d) = %f", dest->p_foreground_h, dest->p_vanishing_h, dest->p_scale); */
|
|
|
|
|
// Sprites are scale N (default 1.0) at the foreground, so how much do we need to
|
2026-05-13 09:57:24 -04:00
|
|
|
// scale them for every pixel above foreground_y before they reach vanishing_y?
|
|
|
|
|
// If vanishing is at 320 and foreground is at 640, that is a 320 line difference
|
2026-05-13 23:36:49 -04:00
|
|
|
// If our scaling rate is 2x, then our rate is (((N=1.0) / (640 - 320)) / (dest->p_scale = 2)), or
|
|
|
|
|
// 0.0066% scale per pixel.
|
|
|
|
|
dest->p_rate = ((dest->p_foreground_scale - dest->p_vanishing_scale) / (dest->p_foreground_y - dest->p_vanishing_y));
|
2026-05-13 09:57:24 -04:00
|
|
|
SDL_Log("Map perspective rate is %f", dest->p_rate);
|
|
|
|
|
}
|
2025-08-03 10:07:35 -04:00
|
|
|
} CLEANUP {
|
2026-05-06 23:18:42 -04:00
|
|
|
//IGNORE(akgl_heap_release_string(tmpstr));
|
2025-08-03 10:07:35 -04:00
|
|
|
} PROCESS(errctx) {
|
|
|
|
|
} FINISH(errctx, true);
|
|
|
|
|
SUCCEED_RETURN(errctx);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-24 21:59:29 -04:00
|
|
|
akerr_ErrorContext *akgl_tilemap_draw(akgl_Tilemap *map, SDL_FRect *viewport, int layeridx)
|
2025-08-03 10:07:35 -04:00
|
|
|
{
|
|
|
|
|
PREPARE_ERROR(errctx);
|
|
|
|
|
SDL_FRect dest = {.x = 0, .y = 0, .w = 0, .h = 0};;
|
|
|
|
|
SDL_FRect src = {.x = 0, .y = 0, .w = 0, .h = 0};
|
|
|
|
|
int start_x = 0;
|
|
|
|
|
int start_y = 0;
|
|
|
|
|
int end_x = 0;
|
|
|
|
|
int end_y = 0;
|
|
|
|
|
int yidx = 0;
|
|
|
|
|
int xidx = 0;
|
|
|
|
|
int tilesetidx = 0;
|
|
|
|
|
int tilenum = 0;
|
|
|
|
|
int offset = 0;
|
|
|
|
|
/*
|
|
|
|
|
* Render every tile in the map that partially intersects the viewport
|
|
|
|
|
*
|
|
|
|
|
* For an 8x2 tilemap with 16 pixel square tiles like this
|
|
|
|
|
*
|
|
|
|
|
* 01234567
|
|
|
|
|
* 89ABCDEF
|
|
|
|
|
*
|
|
|
|
|
* With a viewport of (x=20, y=8, w=90, y=20), we would render:
|
|
|
|
|
*
|
|
|
|
|
* 123456
|
|
|
|
|
* 9ABCDE
|
|
|
|
|
*
|
|
|
|
|
* 0 and 8 would not be rendered. 1, 9, 6, and E would be partially rendered at their corner.
|
|
|
|
|
* 2,3,4,5 and A,B,C,D would be partially rendered with a slice from their center.
|
|
|
|
|
*/
|
2026-05-06 23:18:42 -04:00
|
|
|
FAIL_ZERO_RETURN(errctx, map, AKERR_NULLPOINTER, "akgl_tilemap_draw received NULL pointer to tilemap");
|
|
|
|
|
FAIL_ZERO_RETURN(errctx, viewport, AKERR_NULLPOINTER, "akgl_tilemap_draw received NULL pointer to viewport");
|
2025-08-03 10:07:35 -04:00
|
|
|
|
|
|
|
|
/* Only try to render the stuff that is partially within the viewport */
|
|
|
|
|
|
|
|
|
|
start_x = viewport->x / map->tilewidth;
|
|
|
|
|
start_y = viewport->y / map->tileheight;
|
|
|
|
|
end_x = (viewport->x + viewport->w) / map->tilewidth;
|
|
|
|
|
end_y = (viewport->y + viewport->h) / map->tileheight;
|
|
|
|
|
if ( end_x > map->width ) {
|
|
|
|
|
end_x = map->width;
|
|
|
|
|
}
|
|
|
|
|
if ( end_y > map->height ) {
|
|
|
|
|
end_y = map->height;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*SDL_Log("Rendering map into viewport from (%d, %d) to (%d, %d)",
|
|
|
|
|
start_x, start_y, end_x, end_y);*/
|
|
|
|
|
|
2026-05-13 08:02:59 -04:00
|
|
|
if ( map->layers[layeridx].type == AKGL_TILEMAP_LAYER_TYPE_IMAGE ) {
|
|
|
|
|
dest.x = 0;
|
|
|
|
|
dest.y = 0;
|
|
|
|
|
src.w = map->layers[layeridx].width;
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
src.h = map->layers[layeridx].height;
|
2026-05-13 08:02:59 -04:00
|
|
|
dest.w = map->layers[layeridx].width;
|
|
|
|
|
dest.h = map->layers[layeridx].height;
|
2026-06-02 13:15:26 -04:00
|
|
|
PASS(errctx, renderer->draw_texture(renderer, map->layers[layeridx].texture, &src, &dest, 0, NULL, SDL_FLIP_NONE));
|
2026-05-13 08:02:59 -04:00
|
|
|
SUCCEED_RETURN(errctx);
|
|
|
|
|
}
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
|
2025-08-03 10:07:35 -04:00
|
|
|
dest.x = 0;
|
|
|
|
|
dest.y = 0;
|
|
|
|
|
dest.w = map->tilewidth;
|
|
|
|
|
dest.h = map->tileheight;
|
|
|
|
|
for ( yidx = start_y; yidx < end_y; yidx++ ) {
|
|
|
|
|
dest.x = 0;
|
|
|
|
|
for ( xidx = start_x; xidx < end_x; xidx++ ) {
|
|
|
|
|
if ( yidx == 0 ) {
|
|
|
|
|
offset = xidx;
|
|
|
|
|
} else {
|
|
|
|
|
offset = xidx + (yidx * (map->width));
|
|
|
|
|
}
|
|
|
|
|
tilenum = map->layers[layeridx].data[offset];
|
|
|
|
|
// FIXME: This is probably not very efficient. Need a better way to look up
|
|
|
|
|
// tile offsets within the tilesets by their tile ID.
|
|
|
|
|
for ( tilesetidx = 0; tilesetidx < map->numtilesets ; tilesetidx++ ) {
|
|
|
|
|
if ( map->tilesets[tilesetidx].firstgid <= tilenum &&
|
|
|
|
|
(map->tilesets[tilesetidx].firstgid + map->tilesets[tilesetidx].tilecount) >= tilenum ) {
|
|
|
|
|
// Render this tile to the correct screen position
|
|
|
|
|
// FIXME: These conditionals are probably not very efficient. Need a better way of getting
|
|
|
|
|
// the intersection of this tile with the viewport and rendering only that portion.
|
|
|
|
|
if ( xidx == 0 ) {
|
|
|
|
|
src.x += (int)viewport->x % map->tilewidth;
|
|
|
|
|
src.w = map->tilewidth - ((int)viewport->x % map->tilewidth);
|
|
|
|
|
} else {
|
|
|
|
|
src.x = map->tilesets[tilesetidx].tile_offsets[tilenum - map->tilesets[tilesetidx].firstgid][0];
|
|
|
|
|
src.w = map->tilewidth;
|
|
|
|
|
}
|
|
|
|
|
if ( yidx == 0 ) {
|
|
|
|
|
src.y += (int)viewport->y % map->tileheight;
|
|
|
|
|
src.h = map->tileheight - ((int)viewport->y % map->tileheight);
|
|
|
|
|
} else {
|
|
|
|
|
src.y = map->tilesets[tilesetidx].tile_offsets[tilenum - map->tilesets[tilesetidx].firstgid][1];
|
|
|
|
|
src.h = map->tileheight;
|
|
|
|
|
}
|
|
|
|
|
/*SDL_Log("Blitting tile #%d (local tileset id %d from offset %d) from map layer %d map (x=%d,y=%d) tileset %d (x=%f,y=%f,w=%f,h=%f) to (x=%f,y=%f,w=%f,h=%f)",
|
|
|
|
|
tilenum,
|
|
|
|
|
(tilenum - map->tilesets[tilesetidx].firstgid),
|
|
|
|
|
offset,
|
|
|
|
|
layeridx,
|
|
|
|
|
xidx,
|
|
|
|
|
yidx,
|
|
|
|
|
tilesetidx,
|
|
|
|
|
src.x,
|
|
|
|
|
src.y,
|
|
|
|
|
src.w,
|
|
|
|
|
src.h,
|
|
|
|
|
dest.x,
|
|
|
|
|
dest.y,
|
|
|
|
|
dest.w,
|
|
|
|
|
dest.h);*/
|
2026-06-02 13:15:26 -04:00
|
|
|
PASS(errctx, renderer->draw_texture(renderer, map->tilesets[tilesetidx].texture, &src, &dest, 0, NULL, SDL_FLIP_NONE));
|
2025-08-03 10:07:35 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
dest.x += map->tilewidth;
|
|
|
|
|
}
|
|
|
|
|
dest.y += map->tileheight;
|
|
|
|
|
}
|
|
|
|
|
SUCCEED_RETURN(errctx);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-24 21:59:29 -04:00
|
|
|
akerr_ErrorContext *akgl_tilemap_draw_tileset(akgl_Tilemap *map, int tilesetidx)
|
2025-08-03 10:07:35 -04:00
|
|
|
{
|
|
|
|
|
PREPARE_ERROR(errctx);
|
|
|
|
|
SDL_FRect dest;
|
|
|
|
|
SDL_FRect src;
|
|
|
|
|
int tilenum = 0;
|
|
|
|
|
/*
|
2026-05-24 21:59:29 -04:00
|
|
|
* Render every tile in a tileset to the default renderer
|
2025-08-03 10:07:35 -04:00
|
|
|
* (this is a debugging tool that shows that the recorded tile offsets are correct,
|
|
|
|
|
* by proving that we can reconstruct the original tileset image)
|
|
|
|
|
*/
|
|
|
|
|
|
2026-05-06 23:18:42 -04:00
|
|
|
FAIL_ZERO_RETURN(errctx, map, AKERR_NULLPOINTER, "akgl_tilemap_draw_tileset received NULL pointer to tilemap");
|
|
|
|
|
FAIL_NONZERO_RETURN(errctx, (tilesetidx >= map->numtilesets), AKERR_OUTOFBOUNDS, "akgl_tilemap_draw_tileset received a tileset index out of bounds");
|
Reindent all C sources to the canonical stroustrup style
Mechanical whitespace-only change across src/, include/, tests/, and
util/, applied with scripts/reindent.sh. No behavioral change.
Most files already conformed. The genuine outliers indented at 2 columns
(json_helpers.c, util.c from akgl_rectangle_points onward, assets.c,
staticstring.c, akgl_actor_add_child, util.h, staticstring.h) or used
spaces where the canonical form is a tab (draw.c). cc-mode also re-aligns
line-continuation backslashes in multi-line macros to its default
c-backslash-column, which is required for the tree to be a fixed point of
the indenter.
Verified whitespace-only: `git diff -w` over this change is empty apart
from three trailing blank lines removed at EOF in src/heap.c,
src/registry.c, and tests/tilemap.c. The build produces no new errors and
ctest is unchanged at 13/14, with `character` still the one intentional
failure.
The tree is now a fixed point of `scripts/reindent.sh --check`.
include/akgl/SDL_GameControllerDB.h is generated and excluded.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:17:37 -04:00
|
|
|
|
2025-08-03 10:07:35 -04:00
|
|
|
for ( tilenum = 0; tilenum < map->tilesets[tilesetidx].tilecount; tilenum++) {
|
|
|
|
|
// Render this tile to the correct screen position
|
|
|
|
|
// FIXME: These conditionals are probably not very efficient. Need a better way of getting
|
|
|
|
|
// the intersection of this tile with the viewport and rendering only that portion.
|
|
|
|
|
src.x = map->tilesets[tilesetidx].tile_offsets[tilenum][0];
|
|
|
|
|
src.y = map->tilesets[tilesetidx].tile_offsets[tilenum][1];
|
|
|
|
|
src.w = map->tilewidth;
|
|
|
|
|
src.h = map->tileheight;
|
|
|
|
|
dest.x = tilenum * map->tilewidth;
|
|
|
|
|
if ( tilenum >= map->tilesets[tilesetidx].columns ) {
|
|
|
|
|
dest.x = (tilenum % (map->tilesets[tilesetidx].columns)) * map->tilewidth;
|
|
|
|
|
}
|
|
|
|
|
if ( tilenum >= (map->tilesets[tilesetidx].columns) ) {
|
|
|
|
|
dest.y = (tilenum / (map->tilesets[tilesetidx].columns)) * map->tileheight;
|
|
|
|
|
} else {
|
|
|
|
|
dest.y = 0;
|
|
|
|
|
}
|
|
|
|
|
dest.w = src.w;
|
|
|
|
|
dest.h = src.h;
|
|
|
|
|
/*SDL_Log("Blitting tile #%d from map tileset %d (x=%f,y=%f,w=%f,h=%f) to (x=%f,y=%f,w=%f,h=%f)",
|
|
|
|
|
tilenum,
|
|
|
|
|
tilesetidx,
|
|
|
|
|
src.x,
|
|
|
|
|
src.y,
|
|
|
|
|
src.w,
|
|
|
|
|
src.h,
|
|
|
|
|
dest.x,
|
|
|
|
|
dest.y,
|
|
|
|
|
dest.w,
|
|
|
|
|
dest.h);*/
|
2026-06-02 13:15:26 -04:00
|
|
|
PASS(errctx, renderer->draw_texture(renderer, map->tilesets[tilesetidx].texture, &src, &dest, 0, NULL, SDL_FLIP_NONE));
|
2025-08-03 10:07:35 -04:00
|
|
|
}
|
|
|
|
|
SUCCEED_RETURN(errctx);
|
|
|
|
|
}
|
2026-05-13 09:57:24 -04:00
|
|
|
|
|
|
|
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_tilemap_scale_actor(akgl_Tilemap *map, akgl_Actor *actor)
|
|
|
|
|
{
|
|
|
|
|
PREPARE_ERROR(e);
|
|
|
|
|
|
|
|
|
|
FAIL_ZERO_RETURN(e, map, AKERR_NULLPOINTER, "NULL map");
|
|
|
|
|
FAIL_ZERO_RETURN(e, actor, AKERR_NULLPOINTER, "NULL actor");
|
|
|
|
|
|
|
|
|
|
if ( actor->y <= map->p_vanishing_y ) {
|
2026-05-13 23:36:49 -04:00
|
|
|
actor->scale = map->p_vanishing_scale;
|
2026-05-13 09:57:24 -04:00
|
|
|
} else if ( actor->y >= map->p_foreground_y ) {
|
2026-05-13 23:36:49 -04:00
|
|
|
actor->scale = map->p_foreground_scale;
|
2026-05-13 09:57:24 -04:00
|
|
|
} else {
|
2026-05-13 23:36:49 -04:00
|
|
|
actor->scale = map->p_foreground_scale - (map->p_rate * (map->p_foreground_y - actor->y));
|
2026-05-13 09:57:24 -04:00
|
|
|
}
|
2026-05-13 16:56:24 -04:00
|
|
|
SUCCEED_RETURN(e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_tilemap_release(akgl_Tilemap *dest)
|
|
|
|
|
{
|
|
|
|
|
// Release all tileset textures
|
|
|
|
|
// Release all image layer textures
|
|
|
|
|
// Memset to zero
|
|
|
|
|
PREPARE_ERROR(e);
|
|
|
|
|
FAIL_ZERO_RETURN(e, dest, AKERR_NULLPOINTER, "NULL map");
|
|
|
|
|
int i = 0;
|
|
|
|
|
for ( i = 0; i < AKGL_TILEMAP_MAX_TILESETS; i++ ) {
|
|
|
|
|
if ( dest->tilesets[i].texture != NULL ) {
|
|
|
|
|
SDL_DestroyTexture(dest->tilesets[i].texture);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for ( i = 0; i < AKGL_TILEMAP_MAX_LAYERS; i++ ) {
|
|
|
|
|
if ( dest->layers[i].texture != NULL ) {
|
|
|
|
|
SDL_DestroyTexture(dest->tilesets[i].texture);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
SUCCEED_RETURN(e);
|
2026-05-13 09:57:24 -04:00
|
|
|
}
|