Compare commits
38 Commits
feature/re
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
f695a035c8
|
|||
|
73b1a4cab0
|
|||
|
aad196d84e
|
|||
|
9443fa8532
|
|||
|
dc2e88b72f
|
|||
|
53e4f5c14f
|
|||
|
b8dee456ca
|
|||
|
36dfd47a06
|
|||
|
23dbc7d985
|
|||
|
6f62e674d5
|
|||
|
8ae99120b5
|
|||
|
c79d93dd58
|
|||
|
ccd26494d9
|
|||
|
5439b8004b
|
|||
|
0f01126bad
|
|||
|
d928a8af0f
|
|||
|
4a02f0364f
|
|||
|
cc0916cd1f
|
|||
|
4c771227f5
|
|||
|
ff6b282112
|
|||
|
0bd1ae1df8
|
|||
|
e0a59e2447
|
|||
|
5dda86d887
|
|||
|
a0b2dda4cf
|
|||
|
359ae23414
|
|||
|
f416cb5dee
|
|||
|
ef24d7b843
|
|||
|
87a5b1da21
|
|||
|
c3847160da
|
|||
|
284ffd7b4a
|
|||
|
90cbf41d75
|
|||
|
6763b5629f
|
|||
|
f475dfb6ee
|
|||
|
7cff27f035
|
|||
| 0601a8d767 | |||
| 4b901886a2 | |||
| 62ba23a1a0 | |||
| 93bc3addfe |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1 +1,3 @@
|
|||||||
./build/*
|
./build/*
|
||||||
|
.aider*
|
||||||
|
*~
|
||||||
|
|||||||
24
.gitmodules
vendored
Normal file
24
.gitmodules
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
[submodule "deps/semver"]
|
||||||
|
path = deps/semver
|
||||||
|
url = git@github.com:h2non/semver.c.git
|
||||||
|
[submodule "deps/SDL"]
|
||||||
|
path = deps/SDL
|
||||||
|
url = git@github.com:libsdl-org/SDL.git
|
||||||
|
[submodule "deps/SDL_image"]
|
||||||
|
path = deps/SDL_image
|
||||||
|
url = git@github.com:libsdl-org/SDL_image.git
|
||||||
|
[submodule "deps/SDL_mixer"]
|
||||||
|
path = deps/SDL_mixer
|
||||||
|
url = git@github.com:libsdl-org/SDL_mixer.git
|
||||||
|
[submodule "deps/SDL_ttf"]
|
||||||
|
path = deps/SDL_ttf
|
||||||
|
url = git@github.com:libsdl-org/SDL_ttf.git
|
||||||
|
[submodule "deps/libsdlerror"]
|
||||||
|
path = deps/libakerror
|
||||||
|
url = https://source.home.aklabs.net/andrew/libsdlerror.git
|
||||||
|
[submodule "deps/libakstdlib"]
|
||||||
|
path = deps/libakstdlib
|
||||||
|
url = https://source.home.aklabs.net/andrew/libakstdlib.git
|
||||||
|
[submodule "deps/jansson"]
|
||||||
|
path = deps/jansson
|
||||||
|
url = git@github.com:akheron/jansson.git
|
||||||
146
CMakeLists.txt
146
CMakeLists.txt
@@ -1,28 +1,66 @@
|
|||||||
cmake_minimum_required(VERSION 3.10)
|
cmake_minimum_required(VERSION 3.10)
|
||||||
project(sdl3game LANGUAGES C)
|
project(akgl LANGUAGES C)
|
||||||
|
|
||||||
include(CTest)
|
include(CTest)
|
||||||
|
|
||||||
find_package(PkgConfig REQUIRED)
|
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
||||||
find_package(SDL3 REQUIRED)
|
|
||||||
find_package(SDL3_image REQUIRED)
|
|
||||||
find_package(SDL3_mixer REQUIRED)
|
|
||||||
find_package(sdlerror REQUIRED)
|
|
||||||
find_package(jansson REQUIRED)
|
|
||||||
find_package(box2d REQUIRED)
|
|
||||||
|
|
||||||
# Check for SDL3 using pkg-config
|
add_subdirectory(deps/jansson EXCLUDE_FROM_ALL)
|
||||||
pkg_check_modules(SDL3 REQUIRED sdl3)
|
add_subdirectory(deps/libakerror EXCLUDE_FROM_ALL)
|
||||||
pkg_check_modules(SDL3_image REQUIRED sdl3-image)
|
add_subdirectory(deps/libakstdlib EXCLUDE_FROM_ALL)
|
||||||
pkg_check_modules(SDL3_mixer REQUIRED sdl3-mixer)
|
add_subdirectory(deps/SDL EXCLUDE_FROM_ALL)
|
||||||
pkg_check_modules(jansson REQUIRED jansson)
|
add_subdirectory(deps/SDL_image EXCLUDE_FROM_ALL)
|
||||||
pkg_check_modules(sdlerror REQUIRED sdlerror)
|
add_subdirectory(deps/SDL_mixer EXCLUDE_FROM_ALL)
|
||||||
|
add_subdirectory(deps/SDL_ttf EXCLUDE_FROM_ALL)
|
||||||
|
|
||||||
|
else()
|
||||||
|
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
|
||||||
|
if(NOT TARGET SDL3::SDL3)
|
||||||
|
find_package(SDL3 REQUIRED)
|
||||||
|
endif()
|
||||||
|
if(NOT TARGET SDL3_image::SDL3_image)
|
||||||
|
find_package(SDL3_image REQUIRED)
|
||||||
|
endif()
|
||||||
|
if(NOT TARGET SDL3_mixer::SDL3_mixer)
|
||||||
|
find_package(SDL3_mixer REQUIRED)
|
||||||
|
endif()
|
||||||
|
if(NOT TARGET SDL3_ttf::SDL3_ttf)
|
||||||
|
find_package(SDL3_ttf REQUIRED)
|
||||||
|
endif()
|
||||||
|
if(NOT TARGET akerror::akerror)
|
||||||
|
find_package(akerror REQUIRED)
|
||||||
|
endif()
|
||||||
|
if(NOT TARGET akstdlib::akstdlib)
|
||||||
|
find_package(akstdlib REQUIRED)
|
||||||
|
endif()
|
||||||
|
if(NOT TARGET jansson::jansson)
|
||||||
|
find_package(jansson)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(GAMECONTROLLERDB_H "include/akgl/SDL_GameControllerDB.h")
|
||||||
|
set(prefix ${CMAKE_INSTALL_PREFIX})
|
||||||
|
set(exec_prefix "\${prefix}")
|
||||||
|
set(libdir "\${exec_prefix}/lib")
|
||||||
|
set(includedir "\${prefix}/include")
|
||||||
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/akgl.pc.in ${CMAKE_CURRENT_BINARY_DIR}/akgl.pc @ONLY)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${GAMECONTROLLERDB_H}
|
||||||
|
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/mkcontrollermappings.sh ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
COMMENT "Generating controller mappings ..."
|
||||||
|
)
|
||||||
|
|
||||||
# Add include directories
|
# Add include directories
|
||||||
include_directories(${SDL3_INCLUDE_DIRS})
|
include_directories(${SDL3_INCLUDE_DIRS})
|
||||||
add_library(sdl3game SHARED
|
add_library(akgl SHARED
|
||||||
|
deps/semver/semver.c
|
||||||
src/actor.c
|
src/actor.c
|
||||||
src/actor_state_string_names.c
|
src/actor_state_string_names.c
|
||||||
|
src/text.c
|
||||||
src/assets.c
|
src/assets.c
|
||||||
src/character.c
|
src/character.c
|
||||||
src/draw.c
|
src/draw.c
|
||||||
@@ -35,10 +73,12 @@ add_library(sdl3game SHARED
|
|||||||
src/staticstring.c
|
src/staticstring.c
|
||||||
src/tilemap.c
|
src/tilemap.c
|
||||||
src/util.c
|
src/util.c
|
||||||
|
${GAMECONTROLLERDB_H}
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(charviewer util/charviewer.c)
|
add_library(akgl::akgl ALIAS akgl)
|
||||||
|
|
||||||
|
add_executable(charviewer util/charviewer.c)
|
||||||
add_executable(test_actor tests/actor.c)
|
add_executable(test_actor tests/actor.c)
|
||||||
add_executable(test_bitmasks tests/bitmasks.c)
|
add_executable(test_bitmasks tests/bitmasks.c)
|
||||||
add_executable(test_character tests/character.c)
|
add_executable(test_character tests/character.c)
|
||||||
@@ -47,6 +87,7 @@ add_executable(test_sprite tests/sprite.c)
|
|||||||
add_executable(test_staticstring tests/staticstring.c)
|
add_executable(test_staticstring tests/staticstring.c)
|
||||||
add_executable(test_tilemap tests/tilemap.c)
|
add_executable(test_tilemap tests/tilemap.c)
|
||||||
add_executable(test_util tests/util.c)
|
add_executable(test_util tests/util.c)
|
||||||
|
add_executable(test_semver_unit deps/semver/semver_unit.c)
|
||||||
add_test(NAME actor COMMAND test_actor)
|
add_test(NAME actor COMMAND test_actor)
|
||||||
add_test(NAME bitmasks COMMAND test_bitmasks)
|
add_test(NAME bitmasks COMMAND test_bitmasks)
|
||||||
add_test(NAME character COMMAND test_character)
|
add_test(NAME character COMMAND test_character)
|
||||||
@@ -55,36 +96,55 @@ add_test(NAME sprite COMMAND test_sprite)
|
|||||||
add_test(NAME staticstring COMMAND test_staticstring)
|
add_test(NAME staticstring COMMAND test_staticstring)
|
||||||
add_test(NAME tilemap COMMAND test_tilemap)
|
add_test(NAME tilemap COMMAND test_tilemap)
|
||||||
add_test(NAME util COMMAND test_util)
|
add_test(NAME util COMMAND test_util)
|
||||||
|
add_test(NAME semver_unit COMMAND test_semver_unit)
|
||||||
|
|
||||||
# Specify include directories for the library's headers (if applicable)
|
# Specify include directories for the library's headers (if applicable)
|
||||||
target_include_directories(sdl3game PUBLIC
|
target_include_directories(akgl PUBLIC
|
||||||
include/
|
include/
|
||||||
|
deps/semver/
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(test_actor PRIVATE sdlerror::sdlerror sdl3game SDL3::SDL3 SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer box2d::box2d jansson::jansson -lm)
|
target_link_libraries(akgl
|
||||||
target_link_libraries(test_bitmasks PRIVATE sdlerror::sdlerror sdl3game SDL3::SDL3 SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer box2d::box2d jansson::jansson -lm)
|
PUBLIC
|
||||||
target_link_libraries(test_character PRIVATE sdlerror::sdlerror sdl3game SDL3::SDL3 SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer box2d::box2d jansson::jansson -lm)
|
SDL3::SDL3
|
||||||
target_link_libraries(test_registry PRIVATE sdlerror::sdlerror sdl3game SDL3::SDL3 SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer box2d::box2d jansson::jansson -lm)
|
SDL3_image::SDL3_image
|
||||||
target_link_libraries(test_sprite PRIVATE sdlerror::sdlerror sdl3game SDL3::SDL3 SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer box2d::box2d jansson::jansson -lm)
|
SDL3_mixer::SDL3_mixer
|
||||||
target_link_libraries(test_staticstring PRIVATE sdlerror::sdlerror sdl3game SDL3::SDL3 SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer box2d::box2d jansson::jansson -lm)
|
SDL3_ttf::SDL3_ttf
|
||||||
target_link_libraries(test_tilemap PRIVATE sdlerror::sdlerror sdl3game SDL3::SDL3 SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer box2d::box2d jansson::jansson -lm)
|
akstdlib::akstdlib
|
||||||
target_link_libraries(test_util PRIVATE sdlerror::sdlerror sdl3game SDL3::SDL3 SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer box2d::box2d jansson::jansson -lm)
|
akerror::akerror
|
||||||
|
jansson::jansson
|
||||||
|
)
|
||||||
|
|
||||||
target_link_libraries(charviewer PRIVATE sdlerror::sdlerror sdl3game SDL3::SDL3 SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer box2d::box2d jansson::jansson -lm)
|
target_link_libraries(test_actor PRIVATE akstdlib::akstdlib akerror::akerror akgl SDL3::SDL3 SDL3_ttf::SDL3_ttf SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer jansson::jansson -lm)
|
||||||
|
target_link_libraries(test_bitmasks PRIVATE akstdlib::akstdlib akerror::akerror akgl SDL3::SDL3 SDL3_ttf::SDL3_ttf SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer jansson::jansson -lm)
|
||||||
|
target_link_libraries(test_character PRIVATE akstdlib::akstdlib akerror::akerror akgl SDL3::SDL3 SDL3_ttf::SDL3_ttf SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer jansson::jansson -lm)
|
||||||
|
target_link_libraries(test_registry PRIVATE akstdlib::akstdlib akerror::akerror akgl SDL3::SDL3 SDL3_ttf::SDL3_ttf SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer jansson::jansson -lm)
|
||||||
|
target_link_libraries(test_sprite PRIVATE akstdlib::akstdlib akerror::akerror akgl SDL3::SDL3 SDL3_ttf::SDL3_ttf SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer jansson::jansson -lm)
|
||||||
|
target_link_libraries(test_staticstring PRIVATE akstdlib::akstdlib akerror::akerror akgl SDL3::SDL3 SDL3_ttf::SDL3_ttf SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer jansson::jansson -lm)
|
||||||
|
target_link_libraries(test_tilemap PRIVATE akstdlib::akstdlib akerror::akerror akgl SDL3::SDL3 SDL3_ttf::SDL3_ttf SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer jansson::jansson -lm)
|
||||||
|
target_link_libraries(test_util PRIVATE akstdlib::akstdlib akerror::akerror akgl SDL3::SDL3 SDL3_ttf::SDL3_ttf SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer jansson::jansson -lm)
|
||||||
|
|
||||||
set(main_lib_dest "lib/sdl3game-${MY_LIBRARY_VERSION}")
|
target_link_libraries(charviewer PRIVATE akstdlib::akstdlib akerror::akerror akgl SDL3::SDL3 SDL3_ttf::SDL3_ttf SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer jansson::jansson -lm)
|
||||||
install(TARGETS sdl3game DESTINATION "lib/")
|
|
||||||
install(FILES "include/sdl3game/actor.h" DESTINATION "include/sdl3game/")
|
set(main_lib_dest "lib/akgl-${MY_LIBRARY_VERSION}")
|
||||||
install(FILES "include/sdl3game/assets.h" DESTINATION "include/sdl3game/")
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/akgl.pc DESTINATION "lib/pkgconfig/")
|
||||||
install(FILES "include/sdl3game/character.h" DESTINATION "include/sdl3game/")
|
install(TARGETS akgl DESTINATION "lib/")
|
||||||
install(FILES "include/sdl3game/draw.h" DESTINATION "include/sdl3game/")
|
install(FILES "deps/semver/semver.h" DESTINATION "include/")
|
||||||
install(FILES "include/sdl3game/game.h" DESTINATION "include/sdl3game/")
|
install(FILES "include/akgl/actor.h" DESTINATION "include/akgl/")
|
||||||
install(FILES "include/sdl3game/controller.h" DESTINATION "include/sdl3game/")
|
install(FILES "include/akgl/types.h" DESTINATION "include/akgl/")
|
||||||
install(FILES "include/sdl3game/heap.h" DESTINATION "include/sdl3game/")
|
install(FILES "include/akgl/text.h" DESTINATION "include/akgl/")
|
||||||
install(FILES "include/sdl3game/iterator.h" DESTINATION "include/sdl3game/")
|
install(FILES "include/akgl/assets.h" DESTINATION "include/akgl/")
|
||||||
install(FILES "include/sdl3game/json_helpers.h" DESTINATION "include/sdl3game/")
|
install(FILES "include/akgl/character.h" DESTINATION "include/akgl/")
|
||||||
install(FILES "include/sdl3game/registry.h" DESTINATION "include/sdl3game/")
|
install(FILES "include/akgl/error.h" DESTINATION "include/akgl/")
|
||||||
install(FILES "include/sdl3game/sprite.h" DESTINATION "include/sdl3game/")
|
install(FILES "include/akgl/draw.h" DESTINATION "include/akgl/")
|
||||||
install(FILES "include/sdl3game/staticstring.h" DESTINATION "include/sdl3game/")
|
install(FILES "include/akgl/game.h" DESTINATION "include/akgl/")
|
||||||
install(FILES "include/sdl3game/tilemap.h" DESTINATION "include/sdl3game/")
|
install(FILES "include/akgl/controller.h" DESTINATION "include/akgl/")
|
||||||
install(FILES "include/sdl3game/util.h" DESTINATION "include/sdl3game/")
|
install(FILES "include/akgl/heap.h" DESTINATION "include/akgl/")
|
||||||
|
install(FILES "include/akgl/iterator.h" DESTINATION "include/akgl/")
|
||||||
|
install(FILES "include/akgl/json_helpers.h" DESTINATION "include/akgl/")
|
||||||
|
install(FILES "include/akgl/registry.h" DESTINATION "include/akgl/")
|
||||||
|
install(FILES "include/akgl/sprite.h" DESTINATION "include/akgl/")
|
||||||
|
install(FILES "include/akgl/staticstring.h" DESTINATION "include/akgl/")
|
||||||
|
install(FILES "include/akgl/tilemap.h" DESTINATION "include/akgl/")
|
||||||
|
install(FILES "include/akgl/util.h" DESTINATION "include/akgl/")
|
||||||
|
install(FILES ${GAMECONTROLLERDB_H} DESTINATION "include/akgl/")
|
||||||
|
|||||||
2
TODO.txt
2
TODO.txt
@@ -1,5 +1,3 @@
|
|||||||
Character definitions should allow for specifying multiple states per sprite mapping, rather than only one state per map. Use an array instead.
|
|
||||||
|
|
||||||
Rendering should move to the SDL GPU renderer so i can do lighting and particles etc
|
Rendering should move to the SDL GPU renderer so i can do lighting and particles etc
|
||||||
- Example suitable for my most primitive use case: https://github.com/TheSpydog/SDL_gpu_examples/blob/main/Examples/Blit2DArray.c
|
- Example suitable for my most primitive use case: https://github.com/TheSpydog/SDL_gpu_examples/blob/main/Examples/Blit2DArray.c
|
||||||
- Try vulkan and D3D tutorials to come up to speed on the moving pieces, then figure ou the details from the examples and API docs
|
- Try vulkan and D3D tutorials to come up to speed on the moving pieces, then figure ou the details from the examples and API docs
|
||||||
|
|||||||
10
akgl.pc.in
Normal file
10
akgl.pc.in
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
prefix=@CMAKE_INSTALL_PREFIX@
|
||||||
|
exec_prefix=${prefix}
|
||||||
|
libdir=${exec_prefix}/lib
|
||||||
|
includedir=${exec_prefix}/include
|
||||||
|
|
||||||
|
Name: akgl
|
||||||
|
Description: AKLabs Game library
|
||||||
|
Version: @PROJECT_VERSION@
|
||||||
|
Cflags: -I${includedir}/
|
||||||
|
Libs: -L${libdir} -lakgl
|
||||||
1
deps/SDL
vendored
Submodule
1
deps/SDL
vendored
Submodule
Submodule deps/SDL added at d9d5536704
1
deps/SDL_image
vendored
Submodule
1
deps/SDL_image
vendored
Submodule
Submodule deps/SDL_image added at bec9134a26
1
deps/SDL_mixer
vendored
Submodule
1
deps/SDL_mixer
vendored
Submodule
Submodule deps/SDL_mixer added at a5e1890afc
1
deps/SDL_ttf
vendored
Submodule
1
deps/SDL_ttf
vendored
Submodule
Submodule deps/SDL_ttf added at a1ce3670ae
1
deps/jansson
vendored
Submodule
1
deps/jansson
vendored
Submodule
Submodule deps/jansson added at 1eb7a81297
1
deps/libakerror
vendored
Submodule
1
deps/libakerror
vendored
Submodule
Submodule deps/libakerror added at 4a09ca87fd
1
deps/libakstdlib
vendored
Submodule
1
deps/libakstdlib
vendored
Submodule
Submodule deps/libakstdlib added at b9d703f48a
1
deps/semver
vendored
Submodule
1
deps/semver
vendored
Submodule
Submodule deps/semver added at bd1db234a6
2238
include/akgl/SDL_GameControllerDB.h
Normal file
2238
include/akgl/SDL_GameControllerDB.h
Normal file
File diff suppressed because it is too large
Load Diff
107
include/akgl/actor.h
Normal file
107
include/akgl/actor.h
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
#ifndef _AKGL_ACTOR_H_
|
||||||
|
#define _AKGL_ACTOR_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "types.h"
|
||||||
|
#include "character.h"
|
||||||
|
|
||||||
|
// ---- LOW WORD STATUSES ----
|
||||||
|
|
||||||
|
#define AKGL_ACTOR_STATE_FACE_DOWN 1 << 0 // 1 0000 0000 0000 0001
|
||||||
|
#define AKGL_ACTOR_STATE_FACE_LEFT 1 << 1 // 2 0000 0000 0000 0010
|
||||||
|
#define AKGL_ACTOR_STATE_FACE_RIGHT 1 << 2 // 4 0000 0000 0000 0100
|
||||||
|
#define AKGL_ACTOR_STATE_FACE_UP 1 << 3 // 8 0000 0000 0000 1000
|
||||||
|
#define AKGL_ACTOR_STATE_ALIVE 1 << 4 // 16 0000 0000 0001 0000
|
||||||
|
#define AKGL_ACTOR_STATE_DYING 1 << 5 // 32 0000 0000 0010 0000
|
||||||
|
#define AKGL_ACTOR_STATE_DEAD 1 << 6 // 64 0000 0000 0100 0000
|
||||||
|
#define AKGL_ACTOR_STATE_MOVING_LEFT 1 << 7 // 128 0000 0000 1000 0000
|
||||||
|
#define AKGL_ACTOR_STATE_MOVING_RIGHT 1 << 8 // 256 0000 0001 0000 0000
|
||||||
|
#define AKGL_ACTOR_STATE_MOVING_UP 1 << 9 // 512 0000 0010 0000 0000
|
||||||
|
#define AKGL_ACTOR_STATE_MOVING_DOWN 1 << 10 // 1024 0000 0100 0000 0000
|
||||||
|
#define AKGL_ACTOR_STATE_UNDEFINED_11 1 << 11 // 2048 0000 1000 0000 0000
|
||||||
|
#define AKGL_ACTOR_STATE_UNDEFINED_12 1 << 12 // 4096 0001 0000 0000 0000
|
||||||
|
#define AKGL_ACTOR_STATE_UNDEFINED_13 1 << 13 // 8192 0010 0000 0000 0000
|
||||||
|
#define AKGL_ACTOR_STATE_UNDEFINED_14 1 << 14 // 16384 0100 0000 0000 0000
|
||||||
|
#define AKGL_ACTOR_STATE_UNDEFINED_15 1 << 15 // 32768 1000 0000 0000 0000
|
||||||
|
|
||||||
|
// ----- HIGH WORD STATUSES -----
|
||||||
|
|
||||||
|
#define AKGL_ACTOR_STATE_UNDEFINED_16 1 << 16 // 65536 0000 0000 0000 0001
|
||||||
|
#define AKGL_ACTOR_STATE_UNDEFINED_17 1 << 17 // 131072 0000 0000 0000 0010
|
||||||
|
#define AKGL_ACTOR_STATE_UNDEFINED_18 1 << 18 // 262144 0000 0000 0000 0100
|
||||||
|
#define AKGL_ACTOR_STATE_UNDEFINED_19 1 << 19 // 524288 0000 0000 0000 1000
|
||||||
|
#define AKGL_ACTOR_STATE_UNDEFINED_20 1 << 20 // 1048576 0000 0000 0001 0000
|
||||||
|
#define AKGL_ACTOR_STATE_UNDEFINED_21 1 << 21 // 2097152 0000 0000 0010 0000
|
||||||
|
#define AKGL_ACTOR_STATE_UNDEFINED_22 1 << 22 // 4194304 0000 0000 0100 0000
|
||||||
|
#define AKGL_ACTOR_STATE_UNDEFINED_23 1 << 23 // 8388608 0000 0000 1000 0000
|
||||||
|
#define AKGL_ACTOR_STATE_UNDEFINED_24 1 << 24 // 16777216 0000 0001 0000 0000
|
||||||
|
#define AKGL_ACTOR_STATE_UNDEFINED_25 1 << 25 // 33554432 0000 0010 0000 0000
|
||||||
|
#define AKGL_ACTOR_STATE_UNDEFINED_26 1 << 26 // 67108864 0000 0100 0000 0000
|
||||||
|
#define AKGL_ACTOR_STATE_UNDEFINED_27 1 << 27 // 134217728 0000 1000 0000 0000
|
||||||
|
#define AKGL_ACTOR_STATE_UNDEFINED_28 1 << 28 // 268435456 0001 0000 0000 0000
|
||||||
|
#define AKGL_ACTOR_STATE_UNDEFINED_29 1 << 29 // 536870912 0010 0000 0000 0000
|
||||||
|
#define AKGL_ACTOR_STATE_UNDEFINED_30 1 << 30 // 1073741824 0100 0000 0000 0000
|
||||||
|
#define AKGL_ACTOR_STATE_UNDEFINED_31 1 << 31 // 2147483648 1000 0000 0000 0000
|
||||||
|
|
||||||
|
#define AKGL_ACTOR_MAX_STATES 32
|
||||||
|
|
||||||
|
// This is an array of strings equal to actor states from 1-32.
|
||||||
|
// This is built by a utility script and not kept in git, see
|
||||||
|
// the Makefile for lib_src/actor_state_string_names.c
|
||||||
|
extern char *AKGL_ACTOR_STATE_STRING_NAMES[AKGL_ACTOR_MAX_STATES+1];
|
||||||
|
|
||||||
|
#define AKGL_ACTOR_STATE_FACE_ALL (AKGL_ACTOR_STATE_FACE_DOWN | AKGL_ACTOR_STATE_FACE_LEFT | AKGL_ACTOR_STATE_FACE_RIGHT | AKGL_ACTOR_STATE_FACE_UP)
|
||||||
|
#define AKGL_ACTOR_STATE_MOVING_ALL (AKGL_ACTOR_STATE_MOVING_LEFT | AKGL_ACTOR_STATE_MOVING_RIGHT | AKGL_ACTOR_STATE_MOVING_UP | AKGL_ACTOR_STATE_MOVING_DOWN)
|
||||||
|
|
||||||
|
#define AKGL_ACTOR_MAX_NAME_LENGTH 128
|
||||||
|
#define AKGL_ACTOR_MAX_CHILDREN 8
|
||||||
|
|
||||||
|
#define AKGL_MAX_HEAP_ACTOR 64
|
||||||
|
|
||||||
|
typedef struct akgl_Actor {
|
||||||
|
uint8_t refcount;
|
||||||
|
char name[AKGL_ACTOR_MAX_NAME_LENGTH];
|
||||||
|
akgl_Character *basechar;
|
||||||
|
uint8_t curSpriteFrameId;
|
||||||
|
SDL_Time curSpriteFrameTimer;
|
||||||
|
bool curSpriteReversing;
|
||||||
|
uint32_t layer;
|
||||||
|
int32_t state;
|
||||||
|
bool movement_controls_face;
|
||||||
|
void *actorData;
|
||||||
|
bool visible;
|
||||||
|
SDL_Time logictimer;
|
||||||
|
float32_t x;
|
||||||
|
float32_t y;
|
||||||
|
float32_t scale;
|
||||||
|
struct akgl_Actor *children[AKGL_ACTOR_MAX_CHILDREN];
|
||||||
|
struct akgl_Actor *parent;
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *(*updatefunc)(struct akgl_Actor *obj);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *(*renderfunc)(struct akgl_Actor *obj, SDL_Renderer *renderer);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *(*facefunc)(struct akgl_Actor *obj);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *(*movementlogicfunc)(struct akgl_Actor *obj, SDL_Time curtimems);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *(*changeframefunc)(struct akgl_Actor *obj, akgl_Sprite *curSprite, SDL_Time curtimems);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *(*addchild)(struct akgl_Actor *obj, struct akgl_Actor *child);
|
||||||
|
} akgl_Actor;
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_actor_initialize(akgl_Actor *obj, char *name);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_actor_set_character(akgl_Actor *obj, char *basecharname);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_actor_render(akgl_Actor *obj, SDL_Renderer *renderer);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_actor_update(akgl_Actor *obj);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_actor_logic_movement(akgl_Actor *obj, SDL_Time curtimems);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_actor_logic_changeframe(akgl_Actor *obj, akgl_Sprite *curSprite, SDL_Time curtimems);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_actor_automatic_face(akgl_Actor *obj);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_actor_add_child(akgl_Actor *obj, akgl_Actor *child);
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_left_on(akgl_Actor *obj, SDL_Event *event);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_left_off(akgl_Actor *obj, SDL_Event *event);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_right_on(akgl_Actor *obj, SDL_Event *event);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_right_off(akgl_Actor *obj, SDL_Event *event);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_up_on(akgl_Actor *obj, SDL_Event *event);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_up_off(akgl_Actor *obj, SDL_Event *event);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_down_on(akgl_Actor *obj, SDL_Event *event);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_down_off(akgl_Actor *obj, SDL_Event *event);
|
||||||
|
|
||||||
|
void akgl_registry_iterate_actor(void *userdata, SDL_PropertiesID registry, const char *name);
|
||||||
|
|
||||||
|
#endif // _AKGL_ACTOR_H_
|
||||||
8
include/akgl/assets.h
Normal file
8
include/akgl/assets.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef _ASSETS_H_
|
||||||
|
#define _ASSETS_H_
|
||||||
|
|
||||||
|
#include <akerror.h>
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_load_start_bgm(char *fname);
|
||||||
|
|
||||||
|
#endif //_ASSETS_H_
|
||||||
32
include/akgl/character.h
Normal file
32
include/akgl/character.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#ifndef _AKGL_CHARACTER_H_
|
||||||
|
#define _AKGL_CHARACTER_H_
|
||||||
|
|
||||||
|
#include <SDL3/SDL_properties.h>
|
||||||
|
#include "types.h"
|
||||||
|
#include "sprite.h"
|
||||||
|
|
||||||
|
#define AKGL_SPRITE_MAX_CHARACTER_NAME_LENGTH 128
|
||||||
|
#define AKGL_MAX_HEAP_CHARACTER 256
|
||||||
|
|
||||||
|
typedef struct akgl_Character {
|
||||||
|
uint8_t refcount;
|
||||||
|
char name[AKGL_SPRITE_MAX_CHARACTER_NAME_LENGTH];
|
||||||
|
SDL_PropertiesID state_sprites;
|
||||||
|
uint64_t movementspeed;
|
||||||
|
float32_t vx;
|
||||||
|
float32_t vy;
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *(*sprite_add)(struct akgl_Character *, akgl_Sprite *, int);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *(*sprite_get)(struct akgl_Character *, int, akgl_Sprite **);
|
||||||
|
} akgl_Character;
|
||||||
|
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_character_initialize(akgl_Character *basechar, char *name);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_character_sprite_add(akgl_Character *basechar, akgl_Sprite *ref, int state);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_character_sprite_get(akgl_Character *basechar, int state, akgl_Sprite **dest);
|
||||||
|
|
||||||
|
// This is an SDL iterator so we can't return our error state from it.
|
||||||
|
void akgl_character_state_sprites_iterate(void *userdata, SDL_PropertiesID props, const char *name);
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_character_load_json(char *filename);
|
||||||
|
|
||||||
|
#endif // _AKGL_CHARACTER_H_
|
||||||
47
include/akgl/controller.h
Normal file
47
include/akgl/controller.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#ifndef _CONTROLLER_H_
|
||||||
|
#define _CONTROLLER_H_
|
||||||
|
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
#include <akerror.h>
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
#define AKGL_MAX_CONTROL_MAPS 8
|
||||||
|
#define AKGL_MAX_CONTROLS 32
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t event_on;
|
||||||
|
uint32_t event_off;
|
||||||
|
uint8_t button;
|
||||||
|
SDL_Keycode key;
|
||||||
|
uint8_t axis;
|
||||||
|
uint8_t axis_range_min;
|
||||||
|
uint8_t axis_range_max;
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *(*handler_on)(akgl_Actor *obj, SDL_Event *event);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *(*handler_off)(akgl_Actor *obj, SDL_Event *event);
|
||||||
|
} akgl_Control;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
akgl_Actor *target;
|
||||||
|
uint16_t nextMap;
|
||||||
|
akgl_Control controls[AKGL_MAX_CONTROLS];
|
||||||
|
SDL_KeyboardID kbid;
|
||||||
|
SDL_JoystickID jsid;
|
||||||
|
SDL_MouseID mouseid;
|
||||||
|
SDL_PenID penid;
|
||||||
|
} akgl_ControlMap;
|
||||||
|
|
||||||
|
extern akgl_ControlMap GAME_ControlMaps[AKGL_MAX_CONTROL_MAPS];
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_controller_list_keyboards(void);
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_controller_handle_event(void *appstate, SDL_Event *event);
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_controller_handle_button_down(void *appstate, SDL_Event *event);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_controller_handle_button_up(void *appstate, SDL_Event *event);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_controller_handle_added(void *appstate, SDL_Event *event);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_controller_handle_removed(void *appstate, SDL_Event *event);
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_controller_pushmap(int controlmapid, akgl_Control *control);
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_controller_default(int controlmapid, char *actorname, int kbid, int jsid);
|
||||||
|
#endif // _CONTROLLER_H_
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#ifndef _DRAW_H_
|
#ifndef _DRAW_H_
|
||||||
#define _DRAW_H_
|
#define _DRAW_H_
|
||||||
|
|
||||||
void GAME_draw_background(int w, int h);
|
void akgl_draw_background(int w, int h);
|
||||||
|
|
||||||
#endif //_DRAW_H_
|
#endif //_DRAW_H_
|
||||||
6
include/akgl/error.h
Normal file
6
include/akgl/error.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef _ERROR_H_
|
||||||
|
#define _ERROR_H_
|
||||||
|
|
||||||
|
#define AKGL_ERR_SDL AKERR_LAST_ERRNO_VALUE + 1
|
||||||
|
|
||||||
|
#endif // _ERROR_H_
|
||||||
64
include/akgl/game.h
Normal file
64
include/akgl/game.h
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
#ifndef _AKGL_GAME_H_
|
||||||
|
#define _AKGL_GAME_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "types.h"
|
||||||
|
#include <SDL3_mixer/SDL_mixer.h>
|
||||||
|
#include "tilemap.h"
|
||||||
|
|
||||||
|
#define AKGL_VERSION "0.1.0"
|
||||||
|
|
||||||
|
#define AKGL_GAME_AUDIO_TRACK_BGM 1
|
||||||
|
#define AKGL_GAME_AUDIO_MAX_TRACKS 64
|
||||||
|
|
||||||
|
#define AKGL_TIME_ONESEC_NS 1000000000
|
||||||
|
#define AKGL_TIME_ONESEC_MS 1000000
|
||||||
|
|
||||||
|
/* ==================== GAME STATE VARIABLES =================== */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float32_t w;
|
||||||
|
float32_t h;
|
||||||
|
SDL_Texture *texture;
|
||||||
|
} akgl_Frame;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int32_t flags;
|
||||||
|
} akgl_GameState;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char libversion[32];
|
||||||
|
char version[32];
|
||||||
|
char name[256];
|
||||||
|
char uri[256];
|
||||||
|
akgl_GameState state;
|
||||||
|
int16_t fps;
|
||||||
|
SDL_Time gameStartTime;
|
||||||
|
SDL_Time lastIterTime;
|
||||||
|
SDL_Time lastFPSTime;
|
||||||
|
int16_t framesSinceUpdate;
|
||||||
|
void (*lowfpsfunc)(void);
|
||||||
|
} akgl_Game;
|
||||||
|
|
||||||
|
extern SDL_Window *window;
|
||||||
|
extern SDL_Renderer *renderer;
|
||||||
|
extern akgl_Tilemap gamemap;
|
||||||
|
extern MIX_Audio *bgm;
|
||||||
|
extern MIX_Mixer *akgl_mixer;
|
||||||
|
extern MIX_Track *akgl_tracks[AKGL_GAME_AUDIO_MAX_TRACKS];
|
||||||
|
extern SDL_FRect camera;
|
||||||
|
extern akgl_Game game;
|
||||||
|
|
||||||
|
#define AKGL_BITMASK_HAS(x, y) (x & y) == y
|
||||||
|
#define AKGL_BITMASK_ADD(x, y) x |= y
|
||||||
|
#define AKGL_BITMASK_DEL(x, y) x &= ~(y)
|
||||||
|
#define AKGL_BITMASK_CLEAR(x) x = 0;
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_game_init();
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_game_init_screen();
|
||||||
|
void akgl_game_updateFPS();
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_game_save(char *fpath);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_game_load(char *fpath);
|
||||||
|
void akgl_game_lowfps(void);
|
||||||
|
|
||||||
|
#endif //_AKGL_GAME_H_
|
||||||
45
include/akgl/heap.h
Normal file
45
include/akgl/heap.h
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#ifndef _AKGL_HEAP_H_
|
||||||
|
#define _AKGL_HEAP_H_
|
||||||
|
|
||||||
|
#include "sprite.h"
|
||||||
|
#include "actor.h"
|
||||||
|
#include "character.h"
|
||||||
|
#include "staticstring.h"
|
||||||
|
#include <akerror.h>
|
||||||
|
|
||||||
|
#ifndef AKGL_MAX_HEAP_ACTOR
|
||||||
|
#define AKGL_MAX_HEAP_ACTOR 64
|
||||||
|
#endif
|
||||||
|
#ifndef AKGL_MAX_HEAP_SPRITE
|
||||||
|
#define AKGL_MAX_HEAP_SPRITE (AKGL_MAX_HEAP_ACTOR * 16)
|
||||||
|
#endif
|
||||||
|
#ifndef AKGL_MAX_HEAP_SPRITESHEET
|
||||||
|
#define AKGL_MAX_HEAP_SPRITESHEET AKGL_MAX_HEAP_SPRITE
|
||||||
|
#endif
|
||||||
|
#ifndef AKGL_MAX_HEAP_CHARACTER
|
||||||
|
#define AKGL_MAX_HEAP_CHARACTER 256
|
||||||
|
#endif
|
||||||
|
#ifndef AKGL_MAX_HEAP_STRING
|
||||||
|
#define AKGL_MAX_HEAP_STRING 256
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern akgl_Actor HEAP_ACTOR[AKGL_MAX_HEAP_ACTOR];
|
||||||
|
extern akgl_Sprite HEAP_SPRITE[AKGL_MAX_HEAP_SPRITE];
|
||||||
|
extern akgl_SpriteSheet HEAP_SPRITESHEET[AKGL_MAX_HEAP_SPRITESHEET];
|
||||||
|
extern akgl_Character HEAP_CHARACTER[AKGL_MAX_HEAP_CHARACTER];
|
||||||
|
extern akgl_String HEAP_STRING[AKGL_MAX_HEAP_STRING];
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_init();
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_next_actor(akgl_Actor **dest);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_next_sprite(akgl_Sprite **dest);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_next_spritesheet(akgl_SpriteSheet **dest);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_next_character(akgl_Character **dest);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_next_string(akgl_String **dest);
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_release_actor(akgl_Actor *ptr);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_release_sprite(akgl_Sprite *ptr);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_release_spritesheet(akgl_SpriteSheet *ptr);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_release_character(akgl_Character *ptr);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_heap_release_string(akgl_String *ptr);
|
||||||
|
|
||||||
|
#endif //_AKGL_HEAP_H_
|
||||||
43
include/akgl/iterator.h
Normal file
43
include/akgl/iterator.h
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
#ifndef _AKGL_ITERATOR_H_
|
||||||
|
#define _AKGL_ITERATOR_H_
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t flags;
|
||||||
|
uint8_t layerid;
|
||||||
|
} akgl_Iterator;
|
||||||
|
|
||||||
|
#define AKGL_ITERATOR_OP_UPDATE 1 // 1
|
||||||
|
#define AKGL_ITERATOR_OP_RENDER 1 << 1 // 2
|
||||||
|
#define AKGL_ITERATOR_OP_RELEASE 1 << 2 // 4
|
||||||
|
#define AKGL_ITERATOR_OP_LAYERMASK 1 << 3 // 8
|
||||||
|
#define AKGL_ITERATOR_OP_TILEMAPSCALE 1 << 4 // 16
|
||||||
|
#define AKGL_ITERATOR_OP_UNDEFINED_5 1 << 5 // 32
|
||||||
|
#define AKGL_ITERATOR_OP_UNDEFINED_6 1 << 6 // 64
|
||||||
|
#define AKGL_ITERATOR_OP_UNDEFINED_7 1 << 7 // 128
|
||||||
|
#define AKGL_ITERATOR_OP_UNDEFINED_8 1 << 8 // 256
|
||||||
|
#define AKGL_ITERATOR_OP_UNDEFINED_9 1 << 9 // 512
|
||||||
|
#define AKGL_ITERATOR_OP_UNDEFINED_10 1 << 10 // 1024
|
||||||
|
#define AKGL_ITERATOR_OP_UNDEFINED_11 1 << 11 // 2048
|
||||||
|
#define AKGL_ITERATOR_OP_UNDEFINED_12 1 << 12 // 4096
|
||||||
|
#define AKGL_ITERATOR_OP_UNDEFINED_13 1 << 13 // 8192
|
||||||
|
#define AKGL_ITERATOR_OP_UNDEFINED_14 1 << 14 // 16384
|
||||||
|
#define AKGL_ITERATOR_OP_UNDEFINED_15 1 << 15 // 32768
|
||||||
|
#define AKGL_ITERATOR_OP_UNDEFINED_16 1 << 16 // 65536
|
||||||
|
#define AKGL_ITERATOR_OP_UNDEFINED_17 1 << 17 // 131072
|
||||||
|
#define AKGL_ITERATOR_OP_UNDEFINED_18 1 << 18 // 262144
|
||||||
|
#define AKGL_ITERATOR_OP_UNDEFINED_19 1 << 19 // 524288
|
||||||
|
#define AKGL_ITERATOR_OP_UNDEFINED_20 1 << 20 // 1048576
|
||||||
|
#define AKGL_ITERATOR_OP_UNDEFINED_21 1 << 21 // 2097152
|
||||||
|
#define AKGL_ITERATOR_OP_UNDEFINED_22 1 << 22 // 4194304
|
||||||
|
#define AKGL_ITERATOR_OP_UNDEFINED_23 1 << 23 // 8388608
|
||||||
|
#define AKGL_ITERATOR_OP_UNDEFINED_24 1 << 24 // 16777216
|
||||||
|
#define AKGL_ITERATOR_OP_UNDEFINED_25 1 << 25 // 33554432
|
||||||
|
#define AKGL_ITERATOR_OP_UNDEFINED_26 1 << 26 // 67108864
|
||||||
|
#define AKGL_ITERATOR_OP_UNDEFINED_27 1 << 27 // 134217728
|
||||||
|
#define AKGL_ITERATOR_OP_UNDEFINED_28 1 << 28 // 268435456
|
||||||
|
#define AKGL_ITERATOR_OP_UNDEFINED_29 1 << 29 // 536870912
|
||||||
|
#define AKGL_ITERATOR_OP_UNDEFINED_30 1 << 30 // 1073741824
|
||||||
|
#define AKGL_ITERATOR_OP_UNDEFINED_31 1 << 31 // 2147483648
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _AKGL_ITERATOR_H_
|
||||||
17
include/akgl/json_helpers.h
Normal file
17
include/akgl/json_helpers.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#ifndef _JSON_HELPERS_H_
|
||||||
|
#define _JSON_HELPERS_H_
|
||||||
|
|
||||||
|
#include <akerror.h>
|
||||||
|
#include "staticstring.h"
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_object_value(json_t *obj, char *key, json_t **dest);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_boolean_value(json_t *obj, char *key, bool *dest);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_integer_value(json_t *obj, char *key, int *dest);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_number_value(json_t *obj, char *key, float *dest);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_string_value(json_t *obj, char *key, akgl_String **dest);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_array_value(json_t *obj, char *key, json_t **dest);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_array_index_object(json_t *array, int index, json_t **dest);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_array_index_integer(json_t *array, int index, int *dest);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_array_index_string(json_t *array, int index, akgl_String **dest);
|
||||||
|
|
||||||
|
#endif // _JSON_HELPERS_H_
|
||||||
29
include/akgl/registry.h
Normal file
29
include/akgl/registry.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#ifndef _REGISTRY_H_
|
||||||
|
#define _REGISTRY_H_
|
||||||
|
|
||||||
|
#include <akgl/error.h>
|
||||||
|
#include <akgl/staticstring.h>
|
||||||
|
|
||||||
|
extern SDL_PropertiesID AKGL_REGISTRY_ACTOR;
|
||||||
|
extern SDL_PropertiesID AKGL_REGISTRY_SPRITE;
|
||||||
|
extern SDL_PropertiesID AKGL_REGISTRY_SPRITESHEET;
|
||||||
|
extern SDL_PropertiesID AKGL_REGISTRY_CHARACTER;
|
||||||
|
extern SDL_PropertiesID AKGL_REGISTRY_ACTOR_STATE_STRINGS;
|
||||||
|
extern SDL_PropertiesID AKGL_REGISTRY_FONT;
|
||||||
|
extern SDL_PropertiesID AKGL_REGISTRY_MUSIC;
|
||||||
|
extern SDL_PropertiesID AKGL_REGISTRY_PROPERTIES;
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_registry_init();
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_registry_init_music();
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_registry_init_font();
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_registry_init_actor();
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_registry_init_sprite();
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_registry_init_spritesheet();
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_registry_init_character();
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_registry_init_properties();
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_registry_load_properties(char *fname);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_registry_init_actor_state_strings();
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_set_property(char *name, char *value);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_property(char *name, akgl_String **dest, char *def);
|
||||||
|
|
||||||
|
#endif //_REGISTRY_H_
|
||||||
46
include/akgl/sprite.h
Normal file
46
include/akgl/sprite.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#ifndef _AKGL_SPRITE_H_
|
||||||
|
#define _AKGL_SPRITE_H_
|
||||||
|
|
||||||
|
#include <SDL3/SDL_properties.h>
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
#include <akerror.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define AKGL_SPRITE_MAX_FRAMES 16
|
||||||
|
#define AKGL_SPRITE_MAX_NAME_LENGTH 128
|
||||||
|
#define AKGL_SPRITE_MAX_REGISTRY_SIZE 1024
|
||||||
|
#define AKGL_SPRITE_SHEET_MAX_FILENAME_LENGTH 512
|
||||||
|
|
||||||
|
#define AKGL_MAX_HEAP_SPRITE (AKGL_MAX_HEAP_ACTOR * 16)
|
||||||
|
#define AKGL_MAX_HEAP_SPRITESHEET AKGL_MAX_HEAP_SPRITE
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t refcount;
|
||||||
|
SDL_Texture *texture;
|
||||||
|
char name[AKGL_SPRITE_SHEET_MAX_FILENAME_LENGTH];
|
||||||
|
uint16_t sprite_w;
|
||||||
|
uint16_t sprite_h;
|
||||||
|
} akgl_SpriteSheet;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t refcount;
|
||||||
|
uint8_t frameids[AKGL_SPRITE_MAX_FRAMES]; // which IDs on the spritesheet belong to our frames
|
||||||
|
uint32_t frames; // how many frames are in this animation
|
||||||
|
uint32_t width;
|
||||||
|
uint32_t height;
|
||||||
|
uint32_t speed; // how many milliseconds a given sprite frame should be visible before cycling
|
||||||
|
bool loop; // when this sprite is done playing, it should immediately start again
|
||||||
|
bool loopReverse; // when this sprite is done playing, it should go in reverse order through its frames
|
||||||
|
char name[AKGL_SPRITE_MAX_NAME_LENGTH];
|
||||||
|
akgl_SpriteSheet *sheet;
|
||||||
|
} akgl_Sprite;
|
||||||
|
|
||||||
|
// initializes a new sprite to use the given sheet and otherwise sets to zero
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_sprite_initialize(akgl_Sprite *spr, char *name, akgl_SpriteSheet *sheet);
|
||||||
|
// loads a given image file into a new spritesheet
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_spritesheet_initialize(akgl_SpriteSheet *sheet, int sprite_w, int sprite_h, char *filename);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_sprite_load_json(char *filename);
|
||||||
|
|
||||||
|
akerr_ErrorContext *akgl_sprite_sheet_coords_for_frame(akgl_Sprite *self, SDL_FRect *srccoords, uint8_t frameid);
|
||||||
|
|
||||||
|
#endif //_AKGL_SPRITE_H_
|
||||||
17
include/akgl/staticstring.h
Normal file
17
include/akgl/staticstring.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#ifndef _STRING_H_
|
||||||
|
#define _STRING_H_
|
||||||
|
|
||||||
|
#include "string.h"
|
||||||
|
#include <akerror.h>
|
||||||
|
|
||||||
|
#define AKGL_MAX_STRING_LENGTH 256
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int refcount;
|
||||||
|
char data[AKGL_MAX_STRING_LENGTH];
|
||||||
|
} akgl_String;
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_string_initialize(akgl_String *obj, char *init);
|
||||||
|
|
||||||
|
#endif //_STRING_H_
|
||||||
9
include/akgl/text.h
Normal file
9
include/akgl/text.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#ifndef _TEXT_H_
|
||||||
|
#define _TEXT_H_
|
||||||
|
|
||||||
|
#include <SDL3_ttf/SDL_ttf.h>
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_text_loadfont(char *name, char *filepath, int size);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_text_rendertextat(TTF_Font *font, char *text, SDL_Color color, int wraplength, int x, int y);
|
||||||
|
|
||||||
|
#endif // _TEXT_H_
|
||||||
123
include/akgl/tilemap.h
Normal file
123
include/akgl/tilemap.h
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
#ifndef _TILEMAP_H_
|
||||||
|
#define _TILEMAP_H_
|
||||||
|
|
||||||
|
#include "actor.h"
|
||||||
|
#include "staticstring.h"
|
||||||
|
#include <jansson.h>
|
||||||
|
|
||||||
|
#define AKGL_TILEMAP_MAX_WIDTH 512
|
||||||
|
#define AKGL_TILEMAP_MAX_HEIGHT 512
|
||||||
|
#define AKGL_TILEMAP_MAX_LAYERS 16
|
||||||
|
#define AKGL_TILEMAP_MAX_TILESETS 16
|
||||||
|
#define AKGL_TILEMAP_MAX_TILES_PER_IMAGE 65536
|
||||||
|
#define AKGL_TILEMAP_MAX_TILESET_NAME_SIZE 512
|
||||||
|
#define AKGL_TILEMAP_MAX_TILESET_FILENAME_SIZE 512
|
||||||
|
#define AKGL_TILEMAP_MAX_OBJECT_NAME_SIZE 512
|
||||||
|
#define AKGL_TILEMAP_MAX_OBJECTS_PER_LAYER 128
|
||||||
|
|
||||||
|
#define AKGL_TILEMAP_OBJECT_TYPE_ACTOR 1
|
||||||
|
|
||||||
|
#define AKGL_TILEMAP_LAYER_TYPE_TILES 1
|
||||||
|
#define AKGL_TILEMAP_LAYER_TYPE_OBJECTS 2
|
||||||
|
#define AKGL_TILEMAP_LAYER_TYPE_IMAGE 3
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
int gid;
|
||||||
|
int id;
|
||||||
|
int height;
|
||||||
|
int width;
|
||||||
|
int rotation;
|
||||||
|
int type;
|
||||||
|
bool visible;
|
||||||
|
akgl_Actor *actorptr;
|
||||||
|
char name[AKGL_TILEMAP_MAX_OBJECT_NAME_SIZE];
|
||||||
|
} akgl_TilemapObject;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
short type;
|
||||||
|
float opacity;
|
||||||
|
bool visible;
|
||||||
|
int height;
|
||||||
|
int width;
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int id;
|
||||||
|
SDL_Texture *texture;
|
||||||
|
int data[AKGL_TILEMAP_MAX_WIDTH * AKGL_TILEMAP_MAX_HEIGHT];
|
||||||
|
akgl_TilemapObject objects[AKGL_TILEMAP_MAX_OBJECTS_PER_LAYER];
|
||||||
|
} akgl_TilemapLayer;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int columns;
|
||||||
|
int firstgid;
|
||||||
|
char imagefilename[AKGL_TILEMAP_MAX_TILESET_FILENAME_SIZE];
|
||||||
|
int imageheight;
|
||||||
|
int imagewidth;
|
||||||
|
char name[AKGL_TILEMAP_MAX_TILESET_NAME_SIZE];
|
||||||
|
SDL_Texture *texture;
|
||||||
|
// Use this as a lookup table instead of storing tiles
|
||||||
|
// in individual textures to blit them from a single
|
||||||
|
// texture at runtime
|
||||||
|
// FIXME: This is probably not very efficient. For a map
|
||||||
|
// with a single tileset it makes sense. For a map with
|
||||||
|
// multiple tilesets you may have set A start at firstgid 1
|
||||||
|
// and have 1728 tiles. Set B may start at firstgid 1729 and
|
||||||
|
// have 1728 more tiles. This means Set B has 1728 empty
|
||||||
|
// tile_offsets[] entries before firstgid 1729 because of the
|
||||||
|
// way akgl_tilemap_load_tilesets() works. This is really inefficient
|
||||||
|
// and should be improved in the future, and will eventually
|
||||||
|
// lead to premature exhaustion of AKGL_TILEMAP_MAX_TILES_PER_IMAGE
|
||||||
|
// because set D or E may only have 64 tiles but they may be
|
||||||
|
// at the upper end of the array bound already because of this.
|
||||||
|
int tile_offsets[AKGL_TILEMAP_MAX_TILES_PER_IMAGE][2];
|
||||||
|
int tilecount;
|
||||||
|
int tileheight;
|
||||||
|
int tilewidth;
|
||||||
|
int spacing;
|
||||||
|
int margin;
|
||||||
|
} akgl_Tileset;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int tilewidth;
|
||||||
|
int tileheight;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int numlayers;
|
||||||
|
int orientation; // 0 = orthogonal, 1 = isometric
|
||||||
|
int numtilesets;
|
||||||
|
int p_foreground_y;
|
||||||
|
int p_vanishing_y;
|
||||||
|
int p_foreground_h;
|
||||||
|
int p_vanishing_h;
|
||||||
|
float p_foreground_scale;
|
||||||
|
float p_vanishing_scale;
|
||||||
|
float p_scale;
|
||||||
|
float p_rate;
|
||||||
|
akgl_Tileset tilesets[AKGL_TILEMAP_MAX_TILESETS];
|
||||||
|
akgl_TilemapLayer layers[AKGL_TILEMAP_MAX_LAYERS];
|
||||||
|
} akgl_Tilemap;
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_tilemap_load(char *fname, akgl_Tilemap *dest);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_tilemap_draw(SDL_Renderer *renderer, akgl_Tilemap *dest, SDL_FRect *viewport, int layeridx);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_tilemap_draw_tileset(SDL_Renderer *renderer, akgl_Tilemap *dest, int tilesetidx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These functions are part of the internal API and should not be called by the user.
|
||||||
|
* They are only exposed here for unit testing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_tilemap_property(json_t *obj, char *key, char *type, json_t **dest);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_properties_string(json_t *obj, char *key, akgl_String **dest);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_properties_integer(json_t *obj, char *key, int *dest);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_tilemap_compute_tileset_offsets(akgl_Tilemap *dest, int tilesetidx);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_tilemap_load_layer_objects(akgl_Tilemap *dest, json_t *root, int layerid);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_tilemap_load_layer_tile(akgl_Tilemap *dest, json_t *root, int layerid);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_tilemap_load_layers(akgl_Tilemap *dest, json_t *root);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_tilemap_load_tilesets_each(json_t *tileset, akgl_Tilemap *dest, int tsidx);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_tilemap_load_tilesets(akgl_Tilemap *dest, json_t *root);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_tilemap_release(akgl_Tilemap *dest);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_tilemap_scale_actor(akgl_Tilemap *map, akgl_Actor *actor);
|
||||||
|
|
||||||
|
#endif //_TILEMAP_H_
|
||||||
9
include/akgl/types.h
Normal file
9
include/akgl/types.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#ifndef _AKGL_TYPES_H_
|
||||||
|
#define _AKGL_TYPES_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef float float32_t;
|
||||||
|
typedef double float64_t;
|
||||||
|
|
||||||
|
#endif // _AKGL_TYPES_H_
|
||||||
29
include/akgl/util.h
Normal file
29
include/akgl/util.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#ifndef _UTIL_H_
|
||||||
|
#define _UTIL_H_
|
||||||
|
|
||||||
|
#include <akerror.h>
|
||||||
|
|
||||||
|
typedef struct point {
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int z;
|
||||||
|
} point;
|
||||||
|
|
||||||
|
typedef struct RectanglePoints {
|
||||||
|
point topleft;
|
||||||
|
point topright;
|
||||||
|
point bottomleft;
|
||||||
|
point bottomright;
|
||||||
|
} RectanglePoints;
|
||||||
|
|
||||||
|
#define AKGL_COLLIDE_RECTANGLES(r1x, r1y, r1w, r1h, r2x, r2y, r2w, r2h) ((r1x < (r2x + r2w)) || ((r1x + r1w) > r2x)
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_rectangle_points(RectanglePoints *dest, SDL_FRect *rect);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_collide_point_rectangle(point *p, RectanglePoints *r, bool *collide);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_collide_rectangles(SDL_FRect *r1, SDL_FRect *r2, bool *collide);
|
||||||
|
|
||||||
|
// These are REALLY slow routines that are only useful in testing harnesses
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_compare_sdl_surfaces(SDL_Surface *s1, SDL_Surface *s2);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_render_and_compare(SDL_Texture *t1, SDL_Texture *t2, int x, int y, int w, int h, char *writeout);
|
||||||
|
|
||||||
|
#endif // _UTIL_H_
|
||||||
@@ -1,105 +0,0 @@
|
|||||||
#ifndef _ACTOR_H_
|
|
||||||
#define _ACTOR_H_
|
|
||||||
|
|
||||||
#include "character.h"
|
|
||||||
|
|
||||||
// ---- LOW WORD STATUSES ----
|
|
||||||
|
|
||||||
#define ACTOR_STATE_FACE_DOWN 1 << 0 // 1 0000 0000 0000 0001
|
|
||||||
#define ACTOR_STATE_FACE_LEFT 1 << 1 // 2 0000 0000 0000 0010
|
|
||||||
#define ACTOR_STATE_FACE_RIGHT 1 << 2 // 4 0000 0000 0000 0100
|
|
||||||
#define ACTOR_STATE_FACE_UP 1 << 3 // 8 0000 0000 0000 1000
|
|
||||||
#define ACTOR_STATE_ALIVE 1 << 4 // 16 0000 0000 0001 0000
|
|
||||||
#define ACTOR_STATE_DYING 1 << 5 // 32 0000 0000 0010 0000
|
|
||||||
#define ACTOR_STATE_DEAD 1 << 6 // 64 0000 0000 0100 0000
|
|
||||||
#define ACTOR_STATE_MOVING_LEFT 1 << 7 // 128 0000 0000 1000 0000
|
|
||||||
#define ACTOR_STATE_MOVING_RIGHT 1 << 8 // 256 0000 0001 0000 0000
|
|
||||||
#define ACTOR_STATE_MOVING_UP 1 << 9 // 512 0000 0010 0000 0000
|
|
||||||
#define ACTOR_STATE_MOVING_DOWN 1 << 10 // 1024 0000 0100 0000 0000
|
|
||||||
#define ACTOR_STATE_UNDEFINED_11 1 << 11 // 2048 0000 1000 0000 0000
|
|
||||||
#define ACTOR_STATE_UNDEFINED_12 1 << 12 // 4096 0001 0000 0000 0000
|
|
||||||
#define ACTOR_STATE_UNDEFINED_13 1 << 13 // 8192 0010 0000 0000 0000
|
|
||||||
#define ACTOR_STATE_UNDEFINED_14 1 << 14 // 16384 0100 0000 0000 0000
|
|
||||||
#define ACTOR_STATE_UNDEFINED_15 1 << 15 // 32768 1000 0000 0000 0000
|
|
||||||
|
|
||||||
// ----- HIGH WORD STATUSES -----
|
|
||||||
|
|
||||||
#define ACTOR_STATE_UNDEFINED_16 1 << 16 // 65536 0000 0000 0000 0001
|
|
||||||
#define ACTOR_STATE_UNDEFINED_17 1 << 17 // 131072 0000 0000 0000 0010
|
|
||||||
#define ACTOR_STATE_UNDEFINED_18 1 << 18 // 262144 0000 0000 0000 0100
|
|
||||||
#define ACTOR_STATE_UNDEFINED_19 1 << 19 // 524288 0000 0000 0000 1000
|
|
||||||
#define ACTOR_STATE_UNDEFINED_20 1 << 20 // 1048576 0000 0000 0001 0000
|
|
||||||
#define ACTOR_STATE_UNDEFINED_21 1 << 21 // 2097152 0000 0000 0010 0000
|
|
||||||
#define ACTOR_STATE_UNDEFINED_22 1 << 22 // 4194304 0000 0000 0100 0000
|
|
||||||
#define ACTOR_STATE_UNDEFINED_23 1 << 23 // 8388608 0000 0000 1000 0000
|
|
||||||
#define ACTOR_STATE_UNDEFINED_24 1 << 24 // 16777216 0000 0001 0000 0000
|
|
||||||
#define ACTOR_STATE_UNDEFINED_25 1 << 25 // 33554432 0000 0010 0000 0000
|
|
||||||
#define ACTOR_STATE_UNDEFINED_26 1 << 26 // 67108864 0000 0100 0000 0000
|
|
||||||
#define ACTOR_STATE_UNDEFINED_27 1 << 27 // 134217728 0000 1000 0000 0000
|
|
||||||
#define ACTOR_STATE_UNDEFINED_28 1 << 28 // 268435456 0001 0000 0000 0000
|
|
||||||
#define ACTOR_STATE_UNDEFINED_29 1 << 29 // 536870912 0010 0000 0000 0000
|
|
||||||
#define ACTOR_STATE_UNDEFINED_30 1 << 30 // 1073741824 0100 0000 0000 0000
|
|
||||||
#define ACTOR_STATE_UNDEFINED_31 1 << 31 // 2147483648 1000 0000 0000 0000
|
|
||||||
|
|
||||||
#define ACTOR_MAX_STATES 32
|
|
||||||
|
|
||||||
// This is an array of strings equal to actor states from 1-32.
|
|
||||||
// This is built by a utility script and not kept in git, see
|
|
||||||
// the Makefile for lib_src/actor_state_string_names.c
|
|
||||||
extern char *ACTOR_STATE_STRING_NAMES[ACTOR_MAX_STATES+1];
|
|
||||||
|
|
||||||
#define ACTOR_STATE_FACE_ALL (ACTOR_STATE_FACE_DOWN | ACTOR_STATE_FACE_LEFT | ACTOR_STATE_FACE_RIGHT | ACTOR_STATE_FACE_UP)
|
|
||||||
#define ACTOR_STATE_MOVING_ALL (ACTOR_STATE_MOVING_LEFT | ACTOR_STATE_MOVING_RIGHT | ACTOR_STATE_MOVING_UP | ACTOR_STATE_MOVING_DOWN)
|
|
||||||
|
|
||||||
#define ACTOR_MAX_NAME_LENGTH 128
|
|
||||||
#define ACTOR_MAX_CHILDREN 8
|
|
||||||
|
|
||||||
#define MAX_HEAP_ACTOR 64
|
|
||||||
|
|
||||||
typedef struct actor {
|
|
||||||
int refcount;
|
|
||||||
char name[ACTOR_MAX_NAME_LENGTH];
|
|
||||||
character *basechar;
|
|
||||||
int curSpriteFrameId;
|
|
||||||
SDL_Time curSpriteFrameTimer;
|
|
||||||
bool curSpriteReversing;
|
|
||||||
int layer;
|
|
||||||
int state;
|
|
||||||
bool movement_controls_face;
|
|
||||||
void *actorData;
|
|
||||||
bool visible;
|
|
||||||
int logictimer;
|
|
||||||
float x;
|
|
||||||
float y;
|
|
||||||
struct actor *children[ACTOR_MAX_CHILDREN];
|
|
||||||
struct actor *parent;
|
|
||||||
ErrorContext ERROR_NOIGNORE *(*updatefunc)(struct actor *obj);
|
|
||||||
ErrorContext ERROR_NOIGNORE *(*renderfunc)(struct actor *obj, SDL_Renderer *renderer);
|
|
||||||
ErrorContext ERROR_NOIGNORE *(*facefunc)(struct actor *obj);
|
|
||||||
ErrorContext ERROR_NOIGNORE *(*movementlogicfunc)(struct actor *obj, SDL_Time curtimems);
|
|
||||||
ErrorContext ERROR_NOIGNORE *(*changeframefunc)(struct actor *obj, sprite *curSprite, SDL_Time curtimems);
|
|
||||||
ErrorContext ERROR_NOIGNORE *(*addchild)(struct actor *obj, struct actor *child);
|
|
||||||
} actor;
|
|
||||||
|
|
||||||
ErrorContext ERROR_NOIGNORE *actor_initialize(actor *obj, char *name);
|
|
||||||
ErrorContext ERROR_NOIGNORE *actor_set_character(actor *obj, char *basecharname);
|
|
||||||
ErrorContext ERROR_NOIGNORE *actor_render(actor *obj, SDL_Renderer *renderer);
|
|
||||||
ErrorContext ERROR_NOIGNORE *actor_update(actor *obj);
|
|
||||||
ErrorContext ERROR_NOIGNORE *actor_logic_movement(actor *obj, SDL_Time curtimems);
|
|
||||||
ErrorContext ERROR_NOIGNORE *actor_logic_changeframe(actor *obj, sprite *curSprite, SDL_Time curtimems);
|
|
||||||
ErrorContext ERROR_NOIGNORE *actor_automatic_face(actor *obj);
|
|
||||||
ErrorContext ERROR_NOIGNORE *actor_add_child(actor *obj, actor *child);
|
|
||||||
|
|
||||||
ErrorContext ERROR_NOIGNORE *SDL3GActor_cmhf_left_on(actor *obj, SDL_Event *event);
|
|
||||||
ErrorContext ERROR_NOIGNORE *SDL3GActor_cmhf_left_off(actor *obj, SDL_Event *event);
|
|
||||||
ErrorContext ERROR_NOIGNORE *SDL3GActor_cmhf_right_on(actor *obj, SDL_Event *event);
|
|
||||||
ErrorContext ERROR_NOIGNORE *SDL3GActor_cmhf_right_off(actor *obj, SDL_Event *event);
|
|
||||||
ErrorContext ERROR_NOIGNORE *SDL3GActor_cmhf_up_on(actor *obj, SDL_Event *event);
|
|
||||||
ErrorContext ERROR_NOIGNORE *SDL3GActor_cmhf_up_off(actor *obj, SDL_Event *event);
|
|
||||||
ErrorContext ERROR_NOIGNORE *SDL3GActor_cmhf_down_on(actor *obj, SDL_Event *event);
|
|
||||||
ErrorContext ERROR_NOIGNORE *SDL3GActor_cmhf_down_off(actor *obj, SDL_Event *event);
|
|
||||||
|
|
||||||
|
|
||||||
void registry_iterate_actor(void *userdata, SDL_PropertiesID registry, const char *name);
|
|
||||||
|
|
||||||
#endif // _ACTOR_H_
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
#ifndef _ASSETS_H_
|
|
||||||
#define _ASSETS_H_
|
|
||||||
|
|
||||||
#include <sdlerror.h>
|
|
||||||
|
|
||||||
ErrorContext ERROR_NOIGNORE *load_start_bgm(char *fname);
|
|
||||||
|
|
||||||
#endif //_ASSETS_H_
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
#ifndef _CHARACTER_H_
|
|
||||||
#define _CHARACTER_H_
|
|
||||||
|
|
||||||
#include <SDL3/SDL_properties.h>
|
|
||||||
#include "sprite.h"
|
|
||||||
|
|
||||||
#define SPRITE_MAX_CHARACTER_NAME_LENGTH 128
|
|
||||||
#define MAX_HEAP_CHARACTER 256
|
|
||||||
|
|
||||||
typedef struct character {
|
|
||||||
int refcount;
|
|
||||||
char name[SPRITE_MAX_CHARACTER_NAME_LENGTH];
|
|
||||||
SDL_PropertiesID state_sprites;
|
|
||||||
ErrorContext ERROR_NOIGNORE *(*sprite_add)(struct character *, sprite *, int);
|
|
||||||
ErrorContext ERROR_NOIGNORE *(*sprite_get)(struct character *, int, sprite **);
|
|
||||||
int movementspeed;
|
|
||||||
float vx;
|
|
||||||
float vy;
|
|
||||||
} character;
|
|
||||||
|
|
||||||
|
|
||||||
ErrorContext ERROR_NOIGNORE *character_initialize(character *basechar, char *name);
|
|
||||||
ErrorContext ERROR_NOIGNORE *character_sprite_add(character *basechar, sprite *ref, int state);
|
|
||||||
ErrorContext ERROR_NOIGNORE *character_sprite_get(character *basechar, int state, sprite **dest);
|
|
||||||
|
|
||||||
// This is an SDL iterator so we can't return our error state from it.
|
|
||||||
void character_state_sprites_iterate(void *userdata, SDL_PropertiesID props, const char *name);
|
|
||||||
|
|
||||||
ErrorContext ERROR_NOIGNORE *character_load_json(char *filename);
|
|
||||||
|
|
||||||
#endif // _CHARACTER_H_
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
#ifndef _CONTROLLER_H_
|
|
||||||
#define _CONTROLLER_H_
|
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
|
||||||
#include <sdlerror.h>
|
|
||||||
|
|
||||||
#define MAX_CONTROL_MAPS 8
|
|
||||||
#define MAX_CONTROLS 32
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
Uint32 event_on;
|
|
||||||
Uint32 event_off;
|
|
||||||
Uint8 button;
|
|
||||||
SDL_Keycode key;
|
|
||||||
Uint8 axis;
|
|
||||||
Uint8 axis_range_min;
|
|
||||||
Uint8 axis_range_max;
|
|
||||||
ErrorContext ERROR_NOIGNORE *(*handler_on)(actor *obj, SDL_Event *event);
|
|
||||||
ErrorContext ERROR_NOIGNORE *(*handler_off)(actor *obj, SDL_Event *event);
|
|
||||||
} SDL3GControl;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
actor *target;
|
|
||||||
SDL3GControl controls[MAX_CONTROLS];
|
|
||||||
SDL_KeyboardID kbid;
|
|
||||||
SDL_JoystickID jsid;
|
|
||||||
SDL_MouseID mouseid;
|
|
||||||
SDL_PenID penid;
|
|
||||||
} SDL3GControlMap;
|
|
||||||
|
|
||||||
extern SDL3GControlMap GAME_ControlMaps[MAX_CONTROL_MAPS];
|
|
||||||
|
|
||||||
ErrorContext ERROR_NOIGNORE *controller_handle_event(void *appstate, SDL_Event *event);
|
|
||||||
|
|
||||||
ErrorContext ERROR_NOIGNORE *controller_handle_button_down(void *appstate, SDL_Event *event);
|
|
||||||
ErrorContext ERROR_NOIGNORE *controller_handle_button_up(void *appstate, SDL_Event *event);
|
|
||||||
ErrorContext ERROR_NOIGNORE *controller_handle_added(void *appstate, SDL_Event *event);
|
|
||||||
ErrorContext ERROR_NOIGNORE *controller_handle_removed(void *appstate, SDL_Event *event);
|
|
||||||
|
|
||||||
#endif // _CONTROLLER_H_
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
#ifndef _GAME_H_
|
|
||||||
#define _GAME_H_
|
|
||||||
|
|
||||||
#include <SDL3_mixer/SDL_mixer.h>
|
|
||||||
#include "tilemap.h"
|
|
||||||
|
|
||||||
/* ==================== GAME STATE VARIABLES =================== */
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
float w;
|
|
||||||
float h;
|
|
||||||
SDL_Texture *texture;
|
|
||||||
} GAME_frame;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int flags;
|
|
||||||
} GameState;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char name[256];
|
|
||||||
char version[32];
|
|
||||||
char uri[256];
|
|
||||||
int screenwidth;
|
|
||||||
int screenheight;
|
|
||||||
GameState state;
|
|
||||||
MIX_Mixer *mixer;
|
|
||||||
MIX_Track *tracks[64];
|
|
||||||
} Game;
|
|
||||||
|
|
||||||
#define GAME_AUDIO_TRACK_BGM 1
|
|
||||||
|
|
||||||
extern SDL_Window *window;
|
|
||||||
extern SDL_Renderer *renderer;
|
|
||||||
extern tilemap gamemap;
|
|
||||||
extern MIX_Audio *bgm;
|
|
||||||
extern SDL_FRect camera;
|
|
||||||
extern Game game;
|
|
||||||
|
|
||||||
#define BITMASK_HAS(x, y) (x & y) == y
|
|
||||||
#define BITMASK_ADD(x, y) x |= y
|
|
||||||
#define BITMASK_DEL(x, y) x &= ~(y)
|
|
||||||
#define BITMASK_CLEAR(x) x = 0;
|
|
||||||
|
|
||||||
ErrorContext ERROR_NOIGNORE *GAME_init();
|
|
||||||
|
|
||||||
#endif //_GAME_H_
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
#ifndef _HEAP_H_
|
|
||||||
#define _HEAP_H_
|
|
||||||
|
|
||||||
#include "sprite.h"
|
|
||||||
#include "actor.h"
|
|
||||||
#include "character.h"
|
|
||||||
#include "staticstring.h"
|
|
||||||
#include <sdlerror.h>
|
|
||||||
|
|
||||||
#define MAX_HEAP_ACTOR 64
|
|
||||||
#define MAX_HEAP_SPRITE (MAX_HEAP_ACTOR * 16)
|
|
||||||
#define MAX_HEAP_SPRITESHEET MAX_HEAP_SPRITE
|
|
||||||
#define MAX_HEAP_CHARACTER 256
|
|
||||||
#define MAX_HEAP_STRING 256
|
|
||||||
|
|
||||||
extern actor HEAP_ACTOR[MAX_HEAP_ACTOR];
|
|
||||||
extern sprite HEAP_SPRITE[MAX_HEAP_SPRITE];
|
|
||||||
extern spritesheet HEAP_SPRITESHEET[MAX_HEAP_SPRITESHEET];
|
|
||||||
extern character HEAP_CHARACTER[MAX_HEAP_CHARACTER];
|
|
||||||
extern string HEAP_STRING[MAX_HEAP_STRING];
|
|
||||||
|
|
||||||
ErrorContext ERROR_NOIGNORE *heap_init();
|
|
||||||
ErrorContext ERROR_NOIGNORE *heap_next_actor(actor **dest);
|
|
||||||
ErrorContext ERROR_NOIGNORE *heap_next_sprite(sprite **dest);
|
|
||||||
ErrorContext ERROR_NOIGNORE *heap_next_spritesheet(spritesheet **dest);
|
|
||||||
ErrorContext ERROR_NOIGNORE *heap_next_character(character **dest);
|
|
||||||
ErrorContext ERROR_NOIGNORE *heap_next_string(string **dest);
|
|
||||||
|
|
||||||
ErrorContext ERROR_NOIGNORE *heap_release_actor(actor *ptr);
|
|
||||||
ErrorContext ERROR_NOIGNORE *heap_release_sprite(sprite *ptr);
|
|
||||||
ErrorContext ERROR_NOIGNORE *heap_release_spritesheet(spritesheet *ptr);
|
|
||||||
ErrorContext ERROR_NOIGNORE *heap_release_character(character *ptr);
|
|
||||||
ErrorContext ERROR_NOIGNORE *heap_release_string(string *ptr);
|
|
||||||
|
|
||||||
#endif //_HEAP_H_
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
#ifndef _ITERATOR_H_
|
|
||||||
#define _ITERATOR_H_
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int flags;
|
|
||||||
int layerid;
|
|
||||||
} iterator;
|
|
||||||
|
|
||||||
#define ITERATOR_OP_UPDATE 1 // 1
|
|
||||||
#define ITERATOR_OP_RENDER 1 << 1 // 2
|
|
||||||
#define ITERATOR_OP_RELEASE 1 << 2 // 4
|
|
||||||
#define ITERATOR_OP_LAYERMASK 1 << 3 // 8
|
|
||||||
#define ITERATOR_OP_UNDEFINED_4 1 << 4 // 16
|
|
||||||
#define ITERATOR_OP_UNDEFINED_5 1 << 5 // 32
|
|
||||||
#define ITERATOR_OP_UNDEFINED_6 1 << 6 // 64
|
|
||||||
#define ITERATOR_OP_UNDEFINED_7 1 << 7 // 128
|
|
||||||
#define ITERATOR_OP_UNDEFINED_8 1 << 8 // 256
|
|
||||||
#define ITERATOR_OP_UNDEFINED_9 1 << 9 // 512
|
|
||||||
#define ITERATOR_OP_UNDEFINED_10 1 << 10 // 1024
|
|
||||||
#define ITERATOR_OP_UNDEFINED_11 1 << 11 // 2048
|
|
||||||
#define ITERATOR_OP_UNDEFINED_12 1 << 12 // 4096
|
|
||||||
#define ITERATOR_OP_UNDEFINED_13 1 << 13 // 8192
|
|
||||||
#define ITERATOR_OP_UNDEFINED_14 1 << 14 // 16384
|
|
||||||
#define ITERATOR_OP_UNDEFINED_15 1 << 15 // 32768
|
|
||||||
#define ITERATOR_OP_UNDEFINED_16 1 << 16 // 65536
|
|
||||||
#define ITERATOR_OP_UNDEFINED_17 1 << 17 // 131072
|
|
||||||
#define ITERATOR_OP_UNDEFINED_18 1 << 18 // 262144
|
|
||||||
#define ITERATOR_OP_UNDEFINED_19 1 << 19 // 524288
|
|
||||||
#define ITERATOR_OP_UNDEFINED_20 1 << 20 // 1048576
|
|
||||||
#define ITERATOR_OP_UNDEFINED_21 1 << 21 // 2097152
|
|
||||||
#define ITERATOR_OP_UNDEFINED_22 1 << 22 // 4194304
|
|
||||||
#define ITERATOR_OP_UNDEFINED_23 1 << 23 // 8388608
|
|
||||||
#define ITERATOR_OP_UNDEFINED_24 1 << 24 // 16777216
|
|
||||||
#define ITERATOR_OP_UNDEFINED_25 1 << 25 // 33554432
|
|
||||||
#define ITERATOR_OP_UNDEFINED_26 1 << 26 // 67108864
|
|
||||||
#define ITERATOR_OP_UNDEFINED_27 1 << 27 // 134217728
|
|
||||||
#define ITERATOR_OP_UNDEFINED_28 1 << 28 // 268435456
|
|
||||||
#define ITERATOR_OP_UNDEFINED_29 1 << 29 // 536870912
|
|
||||||
#define ITERATOR_OP_UNDEFINED_30 1 << 30 // 1073741824
|
|
||||||
#define ITERATOR_OP_UNDEFINED_31 1 << 31 // 2147483648
|
|
||||||
|
|
||||||
|
|
||||||
#endif // _ITERATOR_H_
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
#ifndef _JSON_HELPERS_H_
|
|
||||||
#define _JSON_HELPERS_H_
|
|
||||||
|
|
||||||
#include <sdlerror.h>
|
|
||||||
#include "staticstring.h"
|
|
||||||
|
|
||||||
ErrorContext ERROR_NOIGNORE *get_json_object_value(json_t *obj, char *key, json_t **dest);
|
|
||||||
ErrorContext ERROR_NOIGNORE *get_json_boolean_value(json_t *obj, char *key, bool *dest);
|
|
||||||
ErrorContext ERROR_NOIGNORE *get_json_integer_value(json_t *obj, char *key, int *dest);
|
|
||||||
ErrorContext ERROR_NOIGNORE *get_json_number_value(json_t *obj, char *key, float *dest);
|
|
||||||
ErrorContext ERROR_NOIGNORE *get_json_string_value(json_t *obj, char *key, string **dest);
|
|
||||||
ErrorContext ERROR_NOIGNORE *get_json_array_value(json_t *obj, char *key, json_t **dest);
|
|
||||||
ErrorContext ERROR_NOIGNORE *get_json_array_index_object(json_t *array, int index, json_t **dest);
|
|
||||||
ErrorContext ERROR_NOIGNORE *get_json_array_index_integer(json_t *array, int index, int *dest);
|
|
||||||
ErrorContext ERROR_NOIGNORE *get_json_array_index_string(json_t *array, int index, string **dest);
|
|
||||||
|
|
||||||
#endif // _JSON_HELPERS_H_
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
#ifndef _REGISTRY_H_
|
|
||||||
#define _REGISTRY_H_
|
|
||||||
|
|
||||||
#include "error.h"
|
|
||||||
|
|
||||||
extern SDL_PropertiesID REGISTRY_ACTOR;
|
|
||||||
extern SDL_PropertiesID REGISTRY_SPRITE;
|
|
||||||
extern SDL_PropertiesID REGISTRY_SPRITESHEET;
|
|
||||||
extern SDL_PropertiesID REGISTRY_CHARACTER;
|
|
||||||
extern SDL_PropertiesID REGISTRY_ACTOR_STATE_STRINGS;
|
|
||||||
|
|
||||||
ErrorContext ERROR_NOIGNORE *registry_init();
|
|
||||||
ErrorContext ERROR_NOIGNORE *registry_init_actor();
|
|
||||||
ErrorContext ERROR_NOIGNORE *registry_init_sprite();
|
|
||||||
ErrorContext ERROR_NOIGNORE *registry_init_spritesheet();
|
|
||||||
ErrorContext ERROR_NOIGNORE *registry_init_character();
|
|
||||||
ErrorContext ERROR_NOIGNORE *registry_init_actor_state_strings();
|
|
||||||
|
|
||||||
|
|
||||||
#endif //_REGISTRY_H_
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
#ifndef _SPRITE_H_
|
|
||||||
#define _SPRITE_H_
|
|
||||||
|
|
||||||
#include <SDL3/SDL_properties.h>
|
|
||||||
#include <sdlerror.h>
|
|
||||||
|
|
||||||
|
|
||||||
#define SPRITE_MAX_FRAMES 16
|
|
||||||
#define SPRITE_MAX_NAME_LENGTH 128
|
|
||||||
#define SPRITE_MAX_REGISTRY_SIZE 1024
|
|
||||||
#define SPRITE_SHEET_MAX_FILENAME_LENGTH 512
|
|
||||||
|
|
||||||
#define MAX_HEAP_SPRITE (MAX_HEAP_ACTOR * 16)
|
|
||||||
#define MAX_HEAP_SPRITESHEET MAX_HEAP_SPRITE
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int refcount;
|
|
||||||
SDL_Texture *texture;
|
|
||||||
char name[SPRITE_SHEET_MAX_FILENAME_LENGTH];
|
|
||||||
int sprite_w;
|
|
||||||
int sprite_h;
|
|
||||||
} spritesheet;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int refcount;
|
|
||||||
spritesheet *sheet;
|
|
||||||
int frameids[SPRITE_MAX_FRAMES]; // which IDs on the spritesheet belong to our frames
|
|
||||||
int frames; // how many frames are in this animation
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
int speed; // how many milliseconds a given sprite frame should be visible before cycling
|
|
||||||
bool loop; // when this sprite is done playing, it should immediately start again
|
|
||||||
bool loopReverse; // when this sprite is done playing, it should go in reverse order through its frames
|
|
||||||
char name[SPRITE_MAX_NAME_LENGTH];
|
|
||||||
} sprite;
|
|
||||||
|
|
||||||
// initializes a new sprite to use the given sheet and otherwise sets to zero
|
|
||||||
ErrorContext ERROR_NOIGNORE *sprite_initialize(sprite *spr, char *name, spritesheet *sheet);
|
|
||||||
// loads a given image file into a new spritesheet
|
|
||||||
ErrorContext ERROR_NOIGNORE *spritesheet_initialize(spritesheet *sheet, int sprite_w, int sprite_h, char *filename);
|
|
||||||
ErrorContext ERROR_NOIGNORE *sprite_load_json(char *filename);
|
|
||||||
|
|
||||||
#endif //_SPRITE_H_
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
#ifndef _STRING_H_
|
|
||||||
#define _STRING_H_
|
|
||||||
|
|
||||||
#include "string.h"
|
|
||||||
#include <sdlerror.h>
|
|
||||||
|
|
||||||
#define MAX_STRING_LENGTH 256
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
int refcount;
|
|
||||||
char data[MAX_STRING_LENGTH];
|
|
||||||
} string;
|
|
||||||
|
|
||||||
ErrorContext ERROR_NOIGNORE *string_initialize(string *obj, char *init);
|
|
||||||
|
|
||||||
#endif //_STRING_H_
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
#ifndef _TILEMAP_H_
|
|
||||||
#define _TILEMAP_H_
|
|
||||||
|
|
||||||
#include "actor.h"
|
|
||||||
#include "staticstring.h"
|
|
||||||
#include <jansson.h>
|
|
||||||
|
|
||||||
#define TILEMAP_MAX_WIDTH 512
|
|
||||||
#define TILEMAP_MAX_HEIGHT 512
|
|
||||||
#define TILEMAP_MAX_LAYERS 16
|
|
||||||
#define TILEMAP_MAX_TILESETS 16
|
|
||||||
#define TILEMAP_MAX_TILES_PER_IMAGE 65536
|
|
||||||
#define TILEMAP_MAX_TILESET_NAME_SIZE 512
|
|
||||||
#define TILEMAP_MAX_TILESET_FILENAME_SIZE 512
|
|
||||||
#define TILEMAP_MAX_OBJECT_NAME_SIZE 512
|
|
||||||
#define TILEMAP_MAX_OBJECTS_PER_LAYER 128
|
|
||||||
|
|
||||||
#define TILEMAP_OBJECT_TYPE_ACTOR 1
|
|
||||||
|
|
||||||
#define TILEMAP_LAYER_TYPE_TILES 1
|
|
||||||
#define TILEMAP_LAYER_TYPE_OBJECTS 2
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
float x;
|
|
||||||
float y;
|
|
||||||
int gid;
|
|
||||||
int id;
|
|
||||||
int height;
|
|
||||||
int width;
|
|
||||||
int rotation;
|
|
||||||
int type;
|
|
||||||
bool visible;
|
|
||||||
actor *actorptr;
|
|
||||||
char name[TILEMAP_MAX_OBJECT_NAME_SIZE];
|
|
||||||
} tilemap_object;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
short type;
|
|
||||||
float opacity;
|
|
||||||
bool visible;
|
|
||||||
int height;
|
|
||||||
int width;
|
|
||||||
int x;
|
|
||||||
int y;
|
|
||||||
int id;
|
|
||||||
int data[TILEMAP_MAX_WIDTH * TILEMAP_MAX_HEIGHT];
|
|
||||||
tilemap_object objects[TILEMAP_MAX_OBJECTS_PER_LAYER];
|
|
||||||
} tilemap_layer;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int columns;
|
|
||||||
int firstgid;
|
|
||||||
char imagefilename[TILEMAP_MAX_TILESET_FILENAME_SIZE];
|
|
||||||
int imageheight;
|
|
||||||
int imagewidth;
|
|
||||||
char name[TILEMAP_MAX_TILESET_NAME_SIZE];
|
|
||||||
SDL_Texture *texture;
|
|
||||||
// Use this as a lookup table instead of storing tiles
|
|
||||||
// in individual textures to blit them from a single
|
|
||||||
// texture at runtime
|
|
||||||
// FIXME: This is probably not very efficient. For a map
|
|
||||||
// with a single tileset it makes sense. For a map with
|
|
||||||
// multiple tilesets you may have set A start at firstgid 1
|
|
||||||
// and have 1728 tiles. Set B may start at firstgid 1729 and
|
|
||||||
// have 1728 more tiles. This means Set B has 1728 empty
|
|
||||||
// tile_offsets[] entries before firstgid 1729 because of the
|
|
||||||
// way tilemap_load_tilesets() works. This is really inefficient
|
|
||||||
// and should be improved in the future, and will eventually
|
|
||||||
// lead to premature exhaustion of TILEMAP_MAX_TILES_PER_IMAGE
|
|
||||||
// because set D or E may only have 64 tiles but they may be
|
|
||||||
// at the upper end of the array bound already because of this.
|
|
||||||
int tile_offsets[TILEMAP_MAX_TILES_PER_IMAGE][2];
|
|
||||||
int tilecount;
|
|
||||||
int tileheight;
|
|
||||||
int tilewidth;
|
|
||||||
int spacing;
|
|
||||||
int margin;
|
|
||||||
} tileset;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int tilewidth;
|
|
||||||
int tileheight;
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
int numlayers;
|
|
||||||
int orientation; // 0 = orthogonal, 1 = isometric
|
|
||||||
int numtilesets;
|
|
||||||
tileset tilesets[TILEMAP_MAX_TILESETS];
|
|
||||||
tilemap_layer layers[TILEMAP_MAX_LAYERS];
|
|
||||||
} tilemap;
|
|
||||||
|
|
||||||
ErrorContext ERROR_NOIGNORE *tilemap_load(char *fname, tilemap *dest);
|
|
||||||
ErrorContext ERROR_NOIGNORE *tilemap_draw(SDL_Renderer *renderer, tilemap *dest, SDL_FRect *viewport, int layeridx);
|
|
||||||
ErrorContext ERROR_NOIGNORE *tilemap_draw_tileset(SDL_Renderer *renderer, tilemap *dest, int tilesetidx);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* These functions are part of the internal API and should not be called by the user.
|
|
||||||
* They are only exposed here for unit testing.
|
|
||||||
*/
|
|
||||||
|
|
||||||
ErrorContext ERROR_NOIGNORE *get_json_tilemap_property(json_t *obj, char *key, char *type, json_t **dest);
|
|
||||||
ErrorContext ERROR_NOIGNORE *get_json_properties_string(json_t *obj, char *key, string **dest);
|
|
||||||
ErrorContext ERROR_NOIGNORE *get_json_properties_integer(json_t *obj, char *key, int *dest);
|
|
||||||
ErrorContext ERROR_NOIGNORE *tilemap_compute_tileset_offsets(tilemap *dest, int tilesetidx);
|
|
||||||
ErrorContext ERROR_NOIGNORE *tilemap_load_layer_objects(tilemap *dest, json_t *root, int layerid);
|
|
||||||
ErrorContext ERROR_NOIGNORE *tilemap_load_layer_tile(tilemap *dest, json_t *root, int layerid);
|
|
||||||
ErrorContext ERROR_NOIGNORE *tilemap_load_layers(tilemap *dest, json_t *root);
|
|
||||||
ErrorContext ERROR_NOIGNORE *tilemap_load_tilesets_each(json_t *tileset, tilemap *dest, int tsidx);
|
|
||||||
ErrorContext ERROR_NOIGNORE *tilemap_load_tilesets(tilemap *dest, json_t *root);
|
|
||||||
|
|
||||||
|
|
||||||
#endif //_TILEMAP_H_
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
#ifndef _UTIL_H_
|
|
||||||
#define _UTIL_H_
|
|
||||||
|
|
||||||
#include <sdlerror.h>
|
|
||||||
|
|
||||||
typedef struct point {
|
|
||||||
int x;
|
|
||||||
int y;
|
|
||||||
int z;
|
|
||||||
} point;
|
|
||||||
|
|
||||||
typedef struct RectanglePoints {
|
|
||||||
point topleft;
|
|
||||||
point topright;
|
|
||||||
point bottomleft;
|
|
||||||
point bottomright;
|
|
||||||
} RectanglePoints;
|
|
||||||
|
|
||||||
#define COLLIDE_RECTANGLES(r1x, r1y, r1w, r1h, r2x, r2y, r2w, r2h) ((r1x < (r2x + r2w)) || ((r1x + r1w) > r2x)
|
|
||||||
|
|
||||||
ErrorContext ERROR_NOIGNORE *rectangle_points(RectanglePoints *dest, SDL_FRect *rect);
|
|
||||||
ErrorContext ERROR_NOIGNORE *collide_point_rectangle(point *p, RectanglePoints *r, bool *collide);
|
|
||||||
ErrorContext ERROR_NOIGNORE *collide_rectangles(SDL_FRect *r1, SDL_FRect *r2, bool *collide);
|
|
||||||
|
|
||||||
// These are REALLY slow routines that are only useful in testing harnesses
|
|
||||||
ErrorContext ERROR_NOIGNORE *compare_sdl_surfaces(SDL_Surface *s1, SDL_Surface *s2);
|
|
||||||
ErrorContext ERROR_NOIGNORE *render_and_compare(SDL_Texture *t1, SDL_Texture *t2, int x, int y, int w, int h, char *writeout);
|
|
||||||
|
|
||||||
#endif // _UTIL_H_
|
|
||||||
32
mkcontrollermappings.sh
Executable file
32
mkcontrollermappings.sh
Executable file
@@ -0,0 +1,32 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
rootdir=$1
|
||||||
|
|
||||||
|
curl https://raw.githubusercontent.com/mdqinc/SDL_GameControllerDB/refs/heads/master/gamecontrollerdb.txt | grep -v '^#' | grep -v '^$' | sed s/',$'//g > mappings.txt
|
||||||
|
|
||||||
|
filelen=$(wc -l mappings.txt | cut -d ' ' -f 1)
|
||||||
|
|
||||||
|
cat > ${rootdir}/include/akgl/SDL_GameControllerDB.h <<EOF
|
||||||
|
#ifndef _SDL_GAMECONTROLLERDB_H_
|
||||||
|
#define _SDL_GAMECONTROLLERDB_H_
|
||||||
|
|
||||||
|
// Taken from https://raw.githubusercontent.com/mdqinc/SDL_GameControllerDB/refs/heads/master/gamecontrollerdb.txt on $(date)
|
||||||
|
|
||||||
|
#define AKGL_SDL_GAMECONTROLLER_DB_LEN ${filelen}
|
||||||
|
|
||||||
|
const char *SDL_GAMECONTROLLER_DB[] = {
|
||||||
|
EOF
|
||||||
|
|
||||||
|
counter=0
|
||||||
|
|
||||||
|
cat mappings.txt | while read LINE;
|
||||||
|
do
|
||||||
|
if [[ $counter -gt 0 ]]; then
|
||||||
|
printf ",\n" >> ${rootdir}/include/akgl/SDL_GameControllerDB.h;
|
||||||
|
fi
|
||||||
|
printf " \"${LINE}\"" >> ${rootdir}/include/akgl/SDL_GameControllerDB.h;
|
||||||
|
counter=$((counter + 1))
|
||||||
|
done
|
||||||
|
|
||||||
|
printf "\n};\n" >> ${rootdir}/include/akgl/SDL_GameControllerDB.h
|
||||||
|
printf "#endif // _SDL_GAMECONTROLLERDB_H_\n" >> ${rootdir}/include/akgl/SDL_GameControllerDB.h
|
||||||
11
rebuild.sh
Normal file
11
rebuild.sh
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
|
||||||
|
export CMAKE_PREFIX_PATH=/home/andrew/local:/home/andrew/local/lib/cmake
|
||||||
|
export CMAKE_MODULE_PATH=/home/andrew/local/lib/cmake
|
||||||
|
#export SDL3_DIR=/home/andrew/local
|
||||||
|
|
||||||
|
rm -fr ~/local/lib/*akgl* ~/local/include/akgl build
|
||||||
|
cmake -S . -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||||
|
cmake --build build --parallel 4
|
||||||
|
cmake --install build --prefix /home/andrew/local
|
||||||
347
src/actor.c
347
src/actor.c
@@ -1,38 +1,39 @@
|
|||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <SDL3_image/SDL_image.h>
|
#include <SDL3_image/SDL_image.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sdlerror.h>
|
#include <akerror.h>
|
||||||
|
|
||||||
#include <sdl3game/game.h>
|
#include <akgl/game.h>
|
||||||
#include <sdl3game/sprite.h>
|
#include <akgl/sprite.h>
|
||||||
#include <sdl3game/actor.h>
|
#include <akgl/actor.h>
|
||||||
#include <sdl3game/heap.h>
|
#include <akgl/heap.h>
|
||||||
#include <sdl3game/registry.h>
|
#include <akgl/registry.h>
|
||||||
#include <sdl3game/staticstring.h>
|
#include <akgl/staticstring.h>
|
||||||
#include <sdl3game/iterator.h>
|
#include <akgl/iterator.h>
|
||||||
|
|
||||||
ErrorContext *actor_initialize(actor *obj, char *name)
|
akerr_ErrorContext *akgl_actor_initialize(akgl_Actor *obj, char *name)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, obj, ERR_NULLPOINTER, "actor_initialize received null actor pointer");
|
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "akgl_actor_initialize received null actor pointer");
|
||||||
FAIL_ZERO_RETURN(errctx, name, ERR_NULLPOINTER, "actor_initialize received null name string pointer");
|
FAIL_ZERO_RETURN(errctx, name, AKERR_NULLPOINTER, "akgl_actor_initialize received null name string pointer");
|
||||||
|
|
||||||
memset(obj, 0x00, sizeof(actor));
|
memset(obj, 0x00, sizeof(akgl_Actor));
|
||||||
strncpy((char *)obj->name, name, ACTOR_MAX_NAME_LENGTH);
|
strncpy((char *)obj->name, name, AKGL_ACTOR_MAX_NAME_LENGTH);
|
||||||
obj->curSpriteReversing = false;
|
obj->curSpriteReversing = false;
|
||||||
|
obj->scale = 1.0;
|
||||||
obj->movement_controls_face = true;
|
obj->movement_controls_face = true;
|
||||||
|
|
||||||
obj->updatefunc = &actor_update;
|
obj->updatefunc = &akgl_actor_update;
|
||||||
obj->renderfunc = &actor_render;
|
obj->renderfunc = &akgl_actor_render;
|
||||||
obj->facefunc = &actor_automatic_face;
|
obj->facefunc = &akgl_actor_automatic_face;
|
||||||
obj->movementlogicfunc = &actor_logic_movement;
|
obj->movementlogicfunc = &akgl_actor_logic_movement;
|
||||||
obj->changeframefunc = &actor_logic_changeframe;
|
obj->changeframefunc = &akgl_actor_logic_changeframe;
|
||||||
obj->addchild = &actor_add_child;
|
obj->addchild = &akgl_actor_add_child;
|
||||||
|
|
||||||
FAIL_ZERO_RETURN(
|
FAIL_ZERO_RETURN(
|
||||||
errctx,
|
errctx,
|
||||||
SDL_SetPointerProperty(REGISTRY_ACTOR, name, (void *)obj),
|
SDL_SetPointerProperty(AKGL_REGISTRY_ACTOR, name, (void *)obj),
|
||||||
ERR_KEY,
|
AKERR_KEY,
|
||||||
"Unable to add actor to registry"
|
"Unable to add actor to registry"
|
||||||
);
|
);
|
||||||
obj->refcount += 1;
|
obj->refcount += 1;
|
||||||
@@ -40,34 +41,34 @@ ErrorContext *actor_initialize(actor *obj, char *name)
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *actor_set_character(actor *obj, char *basecharname)
|
akerr_ErrorContext *akgl_actor_set_character(akgl_Actor *obj, char *basecharname)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, obj, ERR_NULLPOINTER, "Null actor reference");
|
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "Null actor reference");
|
||||||
FAIL_ZERO_RETURN(errctx, basecharname, ERR_NULLPOINTER, "Null character reference");
|
FAIL_ZERO_RETURN(errctx, basecharname, AKERR_NULLPOINTER, "Null character reference");
|
||||||
|
|
||||||
obj->basechar = SDL_GetPointerProperty(REGISTRY_CHARACTER, basecharname, NULL);
|
obj->basechar = SDL_GetPointerProperty(AKGL_REGISTRY_CHARACTER, basecharname, NULL);
|
||||||
|
|
||||||
FAIL_ZERO_RETURN(errctx, obj->basechar, ERR_NULLPOINTER, "Character not found in the registry");
|
FAIL_ZERO_RETURN(errctx, obj->basechar, AKERR_NULLPOINTER, "Character not found in the registry");
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *actor_automatic_face(actor *obj)
|
akerr_ErrorContext *akgl_actor_automatic_face(akgl_Actor *obj)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, obj, ERR_NULLPOINTER, "Null actor reference");
|
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "Null actor reference");
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
if ( obj->movement_controls_face == true ) {
|
if ( obj->movement_controls_face == true ) {
|
||||||
// TODO : This doesn't really work properly
|
// TODO : This doesn't really work properly
|
||||||
BITMASK_DEL(obj->state, ACTOR_STATE_FACE_ALL);
|
AKGL_BITMASK_DEL(obj->state, AKGL_ACTOR_STATE_FACE_ALL);
|
||||||
if ( BITMASK_HAS(obj->state, ACTOR_STATE_MOVING_LEFT) ) {
|
if ( AKGL_BITMASK_HAS(obj->state, AKGL_ACTOR_STATE_MOVING_LEFT) ) {
|
||||||
BITMASK_ADD(obj->state, ACTOR_STATE_FACE_LEFT);
|
AKGL_BITMASK_ADD(obj->state, AKGL_ACTOR_STATE_FACE_LEFT);
|
||||||
} else if ( BITMASK_HAS(obj->state, ACTOR_STATE_MOVING_RIGHT) ) {
|
} else if ( AKGL_BITMASK_HAS(obj->state, AKGL_ACTOR_STATE_MOVING_RIGHT) ) {
|
||||||
BITMASK_ADD(obj->state, ACTOR_STATE_FACE_RIGHT);
|
AKGL_BITMASK_ADD(obj->state, AKGL_ACTOR_STATE_FACE_RIGHT);
|
||||||
} else if ( BITMASK_HAS(obj->state, ACTOR_STATE_MOVING_UP) ) {
|
} else if ( AKGL_BITMASK_HAS(obj->state, AKGL_ACTOR_STATE_MOVING_UP) ) {
|
||||||
BITMASK_ADD(obj->state, ACTOR_STATE_FACE_UP);
|
AKGL_BITMASK_ADD(obj->state, AKGL_ACTOR_STATE_FACE_UP);
|
||||||
} else if ( BITMASK_HAS(obj->state, ACTOR_STATE_MOVING_DOWN) ) {
|
} else if ( AKGL_BITMASK_HAS(obj->state, AKGL_ACTOR_STATE_MOVING_DOWN) ) {
|
||||||
BITMASK_ADD(obj->state, ACTOR_STATE_FACE_DOWN);
|
AKGL_BITMASK_ADD(obj->state, AKGL_ACTOR_STATE_FACE_DOWN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
@@ -76,10 +77,10 @@ ErrorContext *actor_automatic_face(actor *obj)
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *actor_logic_changeframe(actor *obj, sprite *curSprite, SDL_Time curtimems)
|
akerr_ErrorContext *akgl_actor_logic_changeframe(akgl_Actor *obj, akgl_Sprite *curSprite, SDL_Time curtime)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, obj, ERR_NULLPOINTER, "Null actor reference");
|
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "Null actor reference");
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
// are we currently looping in reverse?
|
// are we currently looping in reverse?
|
||||||
if ( curSprite->loop == true && obj->curSpriteReversing == true ) {
|
if ( curSprite->loop == true && obj->curSpriteReversing == true ) {
|
||||||
@@ -91,13 +92,14 @@ ErrorContext *actor_logic_changeframe(actor *obj, sprite *curSprite, SDL_Time cu
|
|||||||
obj->curSpriteFrameId -= 1;
|
obj->curSpriteFrameId -= 1;
|
||||||
}
|
}
|
||||||
// are we at the end of the animation?
|
// are we at the end of the animation?
|
||||||
} else if ( obj->curSpriteFrameId == (curSprite->frames-1) ) {
|
} else if ( obj->curSpriteFrameId >= (curSprite->frames-1) ) {
|
||||||
// are we set to loop in reverse?
|
// are we set to loop in reverse?
|
||||||
if ( curSprite->loop == true && curSprite->loopReverse == true ) {
|
if ( curSprite->loop == true && curSprite->loopReverse == true ) {
|
||||||
obj->curSpriteReversing = true;
|
obj->curSpriteReversing = true;
|
||||||
obj->curSpriteFrameId -= 1;
|
obj->curSpriteFrameId -= 1;
|
||||||
// are we set to loop forward?
|
// are we set to loop forward?
|
||||||
} else if ( curSprite->loop == true ) {
|
} else {
|
||||||
|
// we are at the end of the animation and we either loop forward or do not loop
|
||||||
obj->curSpriteFrameId = 0;
|
obj->curSpriteFrameId = 0;
|
||||||
}
|
}
|
||||||
// we are not looping in reverse and we are not at the end of the animation
|
// we are not looping in reverse and we are not at the end of the animation
|
||||||
@@ -110,83 +112,81 @@ ErrorContext *actor_logic_changeframe(actor *obj, sprite *curSprite, SDL_Time cu
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *actor_logic_movement(actor *obj, SDL_Time curtimems)
|
akerr_ErrorContext *akgl_actor_logic_movement(akgl_Actor *obj, SDL_Time curtime)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, obj, ERR_NULLPOINTER, "Null actor reference");
|
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "Null actor reference");
|
||||||
if ( obj->parent != NULL ) {
|
if ( obj->parent != NULL ) {
|
||||||
// Children don't move independently of their parents, they just have an offset
|
// Children don't move independently of their parents, they just have an offset
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
} else {
|
} else {
|
||||||
if ( BITMASK_HAS(obj->state, ACTOR_STATE_MOVING_LEFT) ) {
|
if ( AKGL_BITMASK_HAS(obj->state, AKGL_ACTOR_STATE_MOVING_LEFT) ) {
|
||||||
obj->x -= obj->basechar->vx;
|
obj->x -= obj->basechar->vx;
|
||||||
}
|
}
|
||||||
if ( BITMASK_HAS(obj->state, ACTOR_STATE_MOVING_RIGHT) ) {
|
if ( AKGL_BITMASK_HAS(obj->state, AKGL_ACTOR_STATE_MOVING_RIGHT) ) {
|
||||||
obj->x += obj->basechar->vx;
|
obj->x += obj->basechar->vx;
|
||||||
}
|
}
|
||||||
if ( BITMASK_HAS(obj->state, ACTOR_STATE_MOVING_UP) ) {
|
if ( AKGL_BITMASK_HAS(obj->state, AKGL_ACTOR_STATE_MOVING_UP) ) {
|
||||||
obj->y -= obj->basechar->vy;
|
obj->y -= obj->basechar->vy;
|
||||||
}
|
}
|
||||||
if ( BITMASK_HAS(obj->state, ACTOR_STATE_MOVING_DOWN) ) {
|
if ( AKGL_BITMASK_HAS(obj->state, AKGL_ACTOR_STATE_MOVING_DOWN) ) {
|
||||||
obj->y += obj->basechar->vy;
|
obj->y += obj->basechar->vy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *actor_update(actor *obj)
|
akerr_ErrorContext *akgl_actor_update(akgl_Actor *obj)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
SDL_Time curtime = 0;
|
SDL_Time curtime = 0;
|
||||||
SDL_Time curtimems = 0;
|
akgl_Sprite *curSprite = NULL;
|
||||||
sprite *curSprite = NULL;
|
|
||||||
|
|
||||||
FAIL_ZERO_RETURN(errctx, obj, ERR_NULLPOINTER, "NULL actor reference");
|
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL actor reference");
|
||||||
FAIL_ZERO_RETURN(errctx, obj->basechar, ERR_NULLPOINTER, "Actor has NULL base character reference");
|
FAIL_ZERO_RETURN(errctx, obj->basechar, AKERR_NULLPOINTER, "Actor has NULL base character reference");
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
SDL_GetCurrentTime(&curtime);
|
SDL_GetCurrentTime(&curtime);
|
||||||
curtimems = curtime / 1000000;
|
|
||||||
CATCH(errctx, obj->facefunc(obj));
|
CATCH(errctx, obj->facefunc(obj));
|
||||||
// is it time to apply movement logic?
|
// is it time to apply movement logic?
|
||||||
if ( (curtimems - obj->logictimer) >= obj->basechar->movementspeed ) {
|
if ( (curtime - obj->logictimer) >= obj->basechar->movementspeed ) {
|
||||||
CATCH(errctx, obj->movementlogicfunc(obj, curtimems));
|
CATCH(errctx, obj->movementlogicfunc(obj, curtime));
|
||||||
obj->logictimer = curtimems;
|
obj->logictimer = curtime;
|
||||||
}
|
}
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, false);
|
} FINISH(errctx, false);
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, character_sprite_get(obj->basechar, obj->state, &curSprite));
|
CATCH(errctx, akgl_character_sprite_get(obj->basechar, obj->state, &curSprite));
|
||||||
// is it time to change frames?
|
// is it time to change frames?
|
||||||
if ( (curtimems - obj->curSpriteFrameTimer) >= curSprite->speed ) {
|
if ( ((curtime) - obj->curSpriteFrameTimer) >= curSprite->speed) {
|
||||||
CATCH(errctx, obj->changeframefunc(obj, curSprite, curtimems));
|
CATCH(errctx, obj->changeframefunc(obj, curSprite, curtime));
|
||||||
obj->curSpriteFrameTimer = curtimems;
|
obj->curSpriteFrameTimer = curtime;
|
||||||
}
|
}
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} HANDLE(errctx, ERR_KEY) {
|
} HANDLE(errctx, AKERR_KEY) {
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
|
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ErrorContext *actor_visible(actor *obj, SDL_FRect *camera, bool *visible)
|
static akerr_ErrorContext *actor_visible(akgl_Actor *obj, SDL_FRect *camera, bool *visible)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
sprite *curSprite = NULL;
|
akgl_Sprite *curSprite = NULL;
|
||||||
|
|
||||||
FAIL_ZERO_RETURN(errctx, obj, ERR_NULLPOINTER, "NULL actor");
|
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL actor");
|
||||||
FAIL_ZERO_RETURN(errctx, renderer, ERR_NULLPOINTER, "NULL renderer");
|
FAIL_ZERO_RETURN(errctx, renderer, AKERR_NULLPOINTER, "NULL renderer");
|
||||||
FAIL_ZERO_RETURN(errctx, obj->basechar, ERR_NULLPOINTER, "Actor has NULL base character reference");
|
FAIL_ZERO_RETURN(errctx, obj->basechar, AKERR_NULLPOINTER, "Actor has NULL base character reference");
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, character_sprite_get(obj->basechar, obj->state, &curSprite));
|
CATCH(errctx, akgl_character_sprite_get(obj->basechar, obj->state, &curSprite));
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} HANDLE(errctx, ERR_KEY) {
|
} HANDLE(errctx, AKERR_KEY) {
|
||||||
// TODO: Actor has no sprite matching the current state. Should we treat this as an error and throw?
|
// TODO: Actor has no sprite matching the current state. Should we treat this as an error and throw?
|
||||||
*visible = false;
|
*visible = false;
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
@@ -203,24 +203,25 @@ static ErrorContext *actor_visible(actor *obj, SDL_FRect *camera, bool *visible)
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *actor_render(actor *obj, SDL_Renderer *renderer)
|
akerr_ErrorContext *akgl_actor_render(akgl_Actor *obj, SDL_Renderer *renderer)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
sprite *curSprite = NULL;
|
akgl_Sprite *curSprite = NULL;
|
||||||
bool visible = false;
|
bool visible = false;
|
||||||
SDL_FRect src;
|
SDL_FRect src;
|
||||||
SDL_FRect dest;
|
SDL_FRect dest;
|
||||||
|
|
||||||
FAIL_ZERO_RETURN(errctx, obj, ERR_NULLPOINTER, "NULL actor");
|
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL actor");
|
||||||
FAIL_ZERO_RETURN(errctx, renderer, ERR_NULLPOINTER, "NULL renderer");
|
FAIL_ZERO_RETURN(errctx, renderer, AKERR_NULLPOINTER, "NULL renderer");
|
||||||
FAIL_ZERO_RETURN(errctx, obj->basechar, ERR_NULLPOINTER, "Actor has NULL base character reference");
|
FAIL_ZERO_RETURN(errctx, obj->basechar, AKERR_NULLPOINTER, "Actor has NULL base character reference");
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, character_sprite_get(obj->basechar, obj->state, &curSprite));
|
CATCH(errctx, akgl_character_sprite_get(obj->basechar, obj->state, &curSprite));
|
||||||
CATCH(errctx, actor_visible(obj, &camera, &visible));
|
CATCH(errctx, actor_visible(obj, &camera, &visible));
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} HANDLE(errctx, ERR_KEY) {
|
} HANDLE(errctx, AKERR_KEY) {
|
||||||
|
} HANDLE_GROUP(errctx, AKERR_OUTOFBOUNDS) {
|
||||||
// If an actor doesn't have a sprite for a state, just log it and move on
|
// If an actor doesn't have a sprite for a state, just log it and move on
|
||||||
LOG_ERROR(errctx);
|
LOG_ERROR(errctx);
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
@@ -229,15 +230,24 @@ ErrorContext *actor_render(actor *obj, SDL_Renderer *renderer)
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
src.x = curSprite->width * curSprite->frameids[obj->curSpriteFrameId];
|
if ( (obj->curSpriteFrameId > curSprite->frames) ) {
|
||||||
if ( src.x >= curSprite->sheet->texture->w ) {
|
// This isn't necessarily an error - this actor's frame index is outside the range of
|
||||||
src.y = ((int)src.x / curSprite->sheet->texture->w) * curSprite->height;
|
// their current sprite. There are a number of reasons this could happen, and it will
|
||||||
src.x = ((int)src.x % curSprite->sheet->texture->w);
|
// get cleaned up on the next logic update. Just pass on rendering them this frame.
|
||||||
} else {
|
SUCCEED_RETURN(errctx);
|
||||||
src.y = 0;
|
|
||||||
}
|
}
|
||||||
src.w = curSprite->width;
|
|
||||||
src.h = curSprite->height;
|
ATTEMPT {
|
||||||
|
CATCH(errctx,
|
||||||
|
akgl_sprite_sheet_coords_for_frame(
|
||||||
|
curSprite,
|
||||||
|
&src,
|
||||||
|
obj->curSpriteFrameId)
|
||||||
|
);
|
||||||
|
} CLEANUP {
|
||||||
|
} PROCESS(errctx) {
|
||||||
|
} FINISH(errctx, true);
|
||||||
|
|
||||||
if ( obj->parent != NULL ) {
|
if ( obj->parent != NULL ) {
|
||||||
dest.x = (obj->parent->x + obj->x - camera.x);
|
dest.x = (obj->parent->x + obj->x - camera.x);
|
||||||
dest.y = (obj->parent->y + obj->y - camera.y);
|
dest.y = (obj->parent->y + obj->y - camera.y);
|
||||||
@@ -245,22 +255,22 @@ ErrorContext *actor_render(actor *obj, SDL_Renderer *renderer)
|
|||||||
dest.x = (obj->x - camera.x);
|
dest.x = (obj->x - camera.x);
|
||||||
dest.y = (obj->y - camera.y);
|
dest.y = (obj->y - camera.y);
|
||||||
}
|
}
|
||||||
dest.w = curSprite->width;
|
dest.w = curSprite->width * obj->scale;
|
||||||
dest.h = curSprite->width;
|
dest.h = curSprite->width * obj->scale;
|
||||||
|
|
||||||
SDL_RenderTexture(renderer, curSprite->sheet->texture, &src, &dest);
|
SDL_RenderTexture(renderer, curSprite->sheet->texture, &src, &dest);
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *actor_add_child(actor *obj, actor *child)
|
akerr_ErrorContext *akgl_actor_add_child(akgl_Actor *obj, akgl_Actor *child)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, obj, ERR_NULLPOINTER, "NULL parent pointer");
|
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL parent pointer");
|
||||||
FAIL_ZERO_RETURN(errctx, child, ERR_NULLPOINTER, "NULL child pointer");
|
FAIL_ZERO_RETURN(errctx, child, AKERR_NULLPOINTER, "NULL child pointer");
|
||||||
|
|
||||||
FAIL_NONZERO_RETURN(errctx, child->parent, ERR_RELATIONSHIP, "Child object already has a parent");
|
FAIL_NONZERO_RETURN(errctx, child->parent, AKERR_RELATIONSHIP, "Child object already has a parent");
|
||||||
for ( i = 0; i < ACTOR_MAX_CHILDREN ; i++ ) {
|
for ( i = 0; i < AKGL_ACTOR_MAX_CHILDREN ; i++ ) {
|
||||||
if ( obj->children[i] == NULL ) {
|
if ( obj->children[i] == NULL ) {
|
||||||
obj->children[i] = child;
|
obj->children[i] = child;
|
||||||
child->parent = obj;
|
child->parent = obj;
|
||||||
@@ -268,30 +278,35 @@ ErrorContext *actor_add_child(actor *obj, actor *child)
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FAIL_RETURN(errctx, ERR_OUTOFBOUNDS, "Parent object has no remaining child slots left");
|
FAIL_RETURN(errctx, AKERR_OUTOFBOUNDS, "Parent object has no remaining child slots left");
|
||||||
}
|
}
|
||||||
|
|
||||||
// SDL iterator so we can't return error information here, void only
|
// SDL iterator so we can't return error information here, void only
|
||||||
// this means we don't have anywhere to send exceptions up to, so if we hit an error, we log and exit(1) here
|
// this means we don't have anywhere to send exceptions up to, so if we hit an error, we log and exit(1) here
|
||||||
void registry_iterate_actor(void *userdata, SDL_PropertiesID registry, const char *name)
|
void akgl_registry_iterate_actor(void *userdata, SDL_PropertiesID registry, const char *name)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
iterator *opflags = (iterator *)userdata;
|
akgl_Iterator *opflags = (akgl_Iterator *)userdata;
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
FAIL_ZERO_BREAK(errctx, name, ERR_NULLPOINTER, "registry_iterate_actor received NULL property name");
|
FAIL_ZERO_BREAK(errctx, name, AKERR_NULLPOINTER, "registry_iterate_actor received NULL property name");
|
||||||
FAIL_ZERO_BREAK(errctx, opflags, ERR_NULLPOINTER, "received NULL iterator flags");
|
FAIL_ZERO_BREAK(errctx, opflags, AKERR_NULLPOINTER, "received NULL iterator flags");
|
||||||
actor *obj = (actor *)SDL_GetPointerProperty(registry, name, NULL);
|
akgl_Actor *obj = (akgl_Actor *)SDL_GetPointerProperty(registry, name, NULL);
|
||||||
FAIL_ZERO_BREAK(errctx, obj, ERR_KEY, "registry_iterate_actor received property name that was not in the registry");
|
FAIL_ZERO_BREAK(errctx, obj, AKERR_KEY, "registry_iterate_actor received property name that was not in the registry");
|
||||||
if ( BITMASK_HAS(opflags->flags, ITERATOR_OP_LAYERMASK) ) {
|
if ( AKGL_BITMASK_HAS(opflags->flags, AKGL_ITERATOR_OP_LAYERMASK) ) {
|
||||||
if ( obj->layer != opflags->layerid ) {
|
if ( obj->layer != opflags->layerid ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( BITMASK_HAS(opflags->flags, ITERATOR_OP_UPDATE) ) {
|
if ( AKGL_BITMASK_HAS(opflags->flags, AKGL_ITERATOR_OP_UPDATE) ) {
|
||||||
CATCH(errctx, obj->updatefunc(obj));
|
CATCH(errctx, obj->updatefunc(obj));
|
||||||
}
|
}
|
||||||
if ( BITMASK_HAS(opflags->flags, ITERATOR_OP_RENDER) ) {
|
if ( AKGL_BITMASK_HAS(opflags->flags, AKGL_ITERATOR_OP_TILEMAPSCALE) ) {
|
||||||
|
CATCH(errctx, akgl_tilemap_scale_actor(&gamemap, obj));
|
||||||
|
} else {
|
||||||
|
obj->scale = 1.0;
|
||||||
|
}
|
||||||
|
if ( AKGL_BITMASK_HAS(opflags->flags, AKGL_ITERATOR_OP_RENDER) ) {
|
||||||
CATCH(errctx, obj->renderfunc(obj, renderer));
|
CATCH(errctx, obj->renderfunc(obj, renderer));
|
||||||
}
|
}
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
@@ -299,122 +314,94 @@ void registry_iterate_actor(void *userdata, SDL_PropertiesID registry, const cha
|
|||||||
} FINISH_NORETURN(errctx);
|
} FINISH_NORETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext ERROR_NOIGNORE *SDL3GActor_cmhf_left_on(actor *obj, SDL_Event *event)
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_left_on(akgl_Actor *obj, SDL_Event *event)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, obj, ERR_NULLPOINTER, "NULL actor");
|
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL actor");
|
||||||
FAIL_ZERO_RETURN(errctx, event, ERR_NULLPOINTER, "NULL event");
|
FAIL_ZERO_RETURN(errctx, event, AKERR_NULLPOINTER, "NULL event");
|
||||||
if ( BITMASK_HAS(obj->state, ACTOR_STATE_MOVING_LEFT) ) {
|
//SDL_Log("event %d (button %d / key %d) moves actor left", event->type, event->gbutton.which, event->key.key);
|
||||||
SUCCEED_RETURN(errctx);
|
AKGL_BITMASK_DEL(obj->state, (AKGL_ACTOR_STATE_FACE_ALL | AKGL_ACTOR_STATE_MOVING_ALL));
|
||||||
}
|
AKGL_BITMASK_ADD(obj->state, (AKGL_ACTOR_STATE_MOVING_LEFT | AKGL_ACTOR_STATE_FACE_LEFT));
|
||||||
SDL_Log("event %d (button %d / key %d) moves actor left", event->type, event->gbutton.which, event->key.key);
|
//SDL_Log("new target actor state: %b", obj->state);
|
||||||
BITMASK_DEL(obj->state, (ACTOR_STATE_FACE_ALL | ACTOR_STATE_MOVING_ALL));
|
|
||||||
BITMASK_ADD(obj->state, (ACTOR_STATE_MOVING_LEFT | ACTOR_STATE_FACE_LEFT));
|
|
||||||
SDL_Log("new target actor state: %b", obj->state);
|
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext ERROR_NOIGNORE *SDL3GActor_cmhf_left_off(actor *obj, SDL_Event *event)
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_left_off(akgl_Actor *obj, SDL_Event *event)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, obj, ERR_NULLPOINTER, "NULL actor");
|
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL actor");
|
||||||
FAIL_ZERO_RETURN(errctx, event, ERR_NULLPOINTER, "NULL event");
|
FAIL_ZERO_RETURN(errctx, event, AKERR_NULLPOINTER, "NULL event");
|
||||||
if ( !BITMASK_HAS(obj->state, ACTOR_STATE_MOVING_LEFT) ) {
|
//SDL_Log("event %d (button %d / key %d) stops moving actor left", event->type, event->gbutton.which, event->key.key);
|
||||||
SUCCEED_RETURN(errctx);
|
AKGL_BITMASK_DEL(obj->state, AKGL_ACTOR_STATE_MOVING_LEFT);
|
||||||
}
|
//SDL_Log("new target actor state: %b", obj->state);
|
||||||
SDL_Log("event %d (button %d / key %d) stops moving actor left", event->type, event->gbutton.which, event->key.key);
|
|
||||||
BITMASK_DEL(obj->state, (ACTOR_STATE_FACE_ALL | ACTOR_STATE_MOVING_ALL));
|
|
||||||
BITMASK_ADD(obj->state, ACTOR_STATE_FACE_LEFT);
|
|
||||||
SDL_Log("new target actor state: %b", obj->state);
|
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext ERROR_NOIGNORE *SDL3GActor_cmhf_right_on(actor *obj, SDL_Event *event)
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_right_on(akgl_Actor *obj, SDL_Event *event)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, obj, ERR_NULLPOINTER, "NULL actor");
|
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL actor");
|
||||||
FAIL_ZERO_RETURN(errctx, event, ERR_NULLPOINTER, "NULL event");
|
FAIL_ZERO_RETURN(errctx, event, AKERR_NULLPOINTER, "NULL event");
|
||||||
if ( BITMASK_HAS(obj->state, ACTOR_STATE_MOVING_RIGHT) ) {
|
//SDL_Log("event %d (button %d / key %d) moves actor right", event->type, event->gbutton.which, event->key.key);
|
||||||
SUCCEED_RETURN(errctx);
|
AKGL_BITMASK_DEL(obj->state, (AKGL_ACTOR_STATE_FACE_ALL | AKGL_ACTOR_STATE_MOVING_ALL));
|
||||||
}
|
AKGL_BITMASK_ADD(obj->state, (AKGL_ACTOR_STATE_MOVING_RIGHT | AKGL_ACTOR_STATE_FACE_RIGHT));
|
||||||
SDL_Log("event %d (button %d / key %d) moves actor right", event->type, event->gbutton.which, event->key.key);
|
//SDL_Log("new target actor state: %b", obj->state);
|
||||||
BITMASK_DEL(obj->state, (ACTOR_STATE_FACE_ALL | ACTOR_STATE_MOVING_ALL));
|
|
||||||
BITMASK_ADD(obj->state, (ACTOR_STATE_MOVING_RIGHT | ACTOR_STATE_FACE_RIGHT));
|
|
||||||
SDL_Log("new target actor state: %b", obj->state);
|
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext ERROR_NOIGNORE *SDL3GActor_cmhf_right_off(actor *obj, SDL_Event *event)
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_right_off(akgl_Actor *obj, SDL_Event *event)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, obj, ERR_NULLPOINTER, "NULL actor");
|
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL actor");
|
||||||
FAIL_ZERO_RETURN(errctx, event, ERR_NULLPOINTER, "NULL event");
|
FAIL_ZERO_RETURN(errctx, event, AKERR_NULLPOINTER, "NULL event");
|
||||||
if ( !BITMASK_HAS(obj->state, ACTOR_STATE_MOVING_RIGHT) ) {
|
//SDL_Log("event %d (button %d / key %d) stops moving actor right", event->type, event->gbutton.which, event->key.key);
|
||||||
SUCCEED_RETURN(errctx);
|
AKGL_BITMASK_DEL(obj->state, AKGL_ACTOR_STATE_MOVING_RIGHT);
|
||||||
}
|
//SDL_Log("new target actor state: %b", obj->state);
|
||||||
SDL_Log("event %d (button %d / key %d) stops moving actor right", event->type, event->gbutton.which, event->key.key);
|
|
||||||
BITMASK_DEL(obj->state, (ACTOR_STATE_FACE_ALL | ACTOR_STATE_MOVING_ALL));
|
|
||||||
BITMASK_ADD(obj->state, ACTOR_STATE_FACE_RIGHT);
|
|
||||||
SDL_Log("new target actor state: %b", obj->state);
|
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext ERROR_NOIGNORE *SDL3GActor_cmhf_up_on(actor *obj, SDL_Event *event)
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_up_on(akgl_Actor *obj, SDL_Event *event)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, obj, ERR_NULLPOINTER, "NULL actor");
|
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL actor");
|
||||||
FAIL_ZERO_RETURN(errctx, event, ERR_NULLPOINTER, "NULL event");
|
FAIL_ZERO_RETURN(errctx, event, AKERR_NULLPOINTER, "NULL event");
|
||||||
if ( BITMASK_HAS(obj->state, ACTOR_STATE_MOVING_UP) ) {
|
//SDL_Log("event %d (button %d / key %d) moves actor up", event->type, event->gbutton.which, event->key.key);
|
||||||
SUCCEED_RETURN(errctx);
|
AKGL_BITMASK_DEL(obj->state, (AKGL_ACTOR_STATE_FACE_ALL | AKGL_ACTOR_STATE_MOVING_ALL));
|
||||||
}
|
AKGL_BITMASK_ADD(obj->state, (AKGL_ACTOR_STATE_FACE_UP | AKGL_ACTOR_STATE_MOVING_UP));
|
||||||
SDL_Log("event %d (button %d / key %d) moves actor up", event->type, event->gbutton.which, event->key.key);
|
//SDL_Log("new target actor state: %b", obj->state);
|
||||||
BITMASK_DEL(obj->state, (ACTOR_STATE_FACE_ALL | ACTOR_STATE_MOVING_ALL));
|
|
||||||
BITMASK_ADD(obj->state, (ACTOR_STATE_FACE_UP | ACTOR_STATE_MOVING_UP));
|
|
||||||
SDL_Log("new target actor state: %b", obj->state);
|
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext ERROR_NOIGNORE *SDL3GActor_cmhf_up_off(actor *obj, SDL_Event *event)
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_up_off(akgl_Actor *obj, SDL_Event *event)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, obj, ERR_NULLPOINTER, "NULL actor");
|
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL actor");
|
||||||
FAIL_ZERO_RETURN(errctx, event, ERR_NULLPOINTER, "NULL event");
|
FAIL_ZERO_RETURN(errctx, event, AKERR_NULLPOINTER, "NULL event");
|
||||||
if ( !BITMASK_HAS(obj->state, ACTOR_STATE_MOVING_UP) ) {
|
//SDL_Log("event %d (button %d / key %d) stops moving actor up", event->type, event->gbutton.which, event->key.key);
|
||||||
SUCCEED_RETURN(errctx);
|
AKGL_BITMASK_DEL(obj->state, AKGL_ACTOR_STATE_MOVING_UP);
|
||||||
}
|
//SDL_Log("new target actor state: %b", obj->state);
|
||||||
SDL_Log("event %d (button %d / key %d) stops moving actor up", event->type, event->gbutton.which, event->key.key);
|
|
||||||
BITMASK_DEL(obj->state, (ACTOR_STATE_FACE_ALL | ACTOR_STATE_MOVING_ALL));
|
|
||||||
BITMASK_ADD(obj->state, ACTOR_STATE_FACE_UP);
|
|
||||||
SDL_Log("new target actor state: %b", obj->state);
|
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext ERROR_NOIGNORE *SDL3GActor_cmhf_down_on(actor *obj, SDL_Event *event)
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_down_on(akgl_Actor *obj, SDL_Event *event)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, obj, ERR_NULLPOINTER, "NULL actor");
|
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL actor");
|
||||||
FAIL_ZERO_RETURN(errctx, event, ERR_NULLPOINTER, "NULL event");
|
FAIL_ZERO_RETURN(errctx, event, AKERR_NULLPOINTER, "NULL event");
|
||||||
if ( BITMASK_HAS(obj->state, ACTOR_STATE_MOVING_DOWN) ) {
|
//SDL_Log("event %d (button %d / key %d) moves actor down", event->type, event->gbutton.which, event->key.key);
|
||||||
SUCCEED_RETURN(errctx);
|
AKGL_BITMASK_DEL(obj->state, (AKGL_ACTOR_STATE_FACE_ALL | AKGL_ACTOR_STATE_MOVING_ALL));
|
||||||
}
|
AKGL_BITMASK_ADD(obj->state, (AKGL_ACTOR_STATE_MOVING_DOWN | AKGL_ACTOR_STATE_FACE_DOWN));
|
||||||
SDL_Log("event %d (button %d / key %d) moves actor down", event->type, event->gbutton.which, event->key.key);
|
//SDL_Log("new target actor state: %b", obj->state);
|
||||||
BITMASK_DEL(obj->state, (ACTOR_STATE_FACE_ALL | ACTOR_STATE_MOVING_ALL));
|
|
||||||
BITMASK_ADD(obj->state, (ACTOR_STATE_MOVING_DOWN | ACTOR_STATE_FACE_DOWN));
|
|
||||||
SDL_Log("new target actor state: %b", obj->state);
|
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext ERROR_NOIGNORE *SDL3GActor_cmhf_down_off(actor *obj, SDL_Event *event)
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_down_off(akgl_Actor *obj, SDL_Event *event)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, obj, ERR_NULLPOINTER, "NULL actor");
|
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL actor");
|
||||||
FAIL_ZERO_RETURN(errctx, event, ERR_NULLPOINTER, "NULL event");
|
FAIL_ZERO_RETURN(errctx, event, AKERR_NULLPOINTER, "NULL event");
|
||||||
if ( !BITMASK_HAS(obj->state, ACTOR_STATE_MOVING_DOWN) ) {
|
//SDL_Log("event %d (button %d / key %d) stops moving actor down", event->type, event->gbutton.which, event->key.key);
|
||||||
SUCCEED_RETURN(errctx);
|
AKGL_BITMASK_DEL(obj->state, AKGL_ACTOR_STATE_MOVING_DOWN);
|
||||||
}
|
//SDL_Log("new target actor state: %b", obj->state);
|
||||||
SDL_Log("event %d (button %d / key %d) stops moving actor down", event->type, event->gbutton.which, event->key.key);
|
|
||||||
BITMASK_DEL(obj->state, (ACTOR_STATE_FACE_ALL | ACTOR_STATE_MOVING_ALL));
|
|
||||||
BITMASK_ADD(obj->state, ACTOR_STATE_FACE_DOWN);
|
|
||||||
SDL_Log("new target actor state: %b", obj->state);
|
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +1,34 @@
|
|||||||
char *ACTOR_STATE_STRING_NAMES[32] = {
|
char *AKGL_ACTOR_STATE_STRING_NAMES[32] = {
|
||||||
"ACTOR_STATE_FACE_DOWN",
|
"AKGL_ACTOR_STATE_FACE_DOWN",
|
||||||
"ACTOR_STATE_FACE_LEFT",
|
"AKGL_ACTOR_STATE_FACE_LEFT",
|
||||||
"ACTOR_STATE_FACE_RIGHT",
|
"AKGL_ACTOR_STATE_FACE_RIGHT",
|
||||||
"ACTOR_STATE_FACE_UP",
|
"AKGL_ACTOR_STATE_FACE_UP",
|
||||||
"ACTOR_STATE_ALIVE",
|
"AKGL_ACTOR_STATE_ALIVE",
|
||||||
"ACTOR_STATE_DYING",
|
"AKGL_ACTOR_STATE_DYING",
|
||||||
"ACTOR_STATE_DEAD",
|
"AKGL_ACTOR_STATE_DEAD",
|
||||||
"ACTOR_STATE_MOVING_LEFT",
|
"AKGL_ACTOR_STATE_MOVING_LEFT",
|
||||||
"ACTOR_STATE_MOVING_RIGHT",
|
"AKGL_ACTOR_STATE_MOVING_RIGHT",
|
||||||
"ACTOR_STATE_MOVING_UP",
|
"AKGL_ACTOR_STATE_MOVING_UP",
|
||||||
"ACTOR_STATE_MOVING_DOWN",
|
"AKGL_ACTOR_STATE_MOVING_DOWN",
|
||||||
"ACTOR_STATE_UNDEFINED_11",
|
"AKGL_ACTOR_STATE_UNDEFINED_11",
|
||||||
"ACTOR_STATE_UNDEFINED_12",
|
"AKGL_ACTOR_STATE_UNDEFINED_12",
|
||||||
"ACTOR_STATE_UNDEFINED_13",
|
"AKGL_ACTOR_STATE_UNDEFINED_13",
|
||||||
"ACTOR_STATE_UNDEFINED_14",
|
"AKGL_ACTOR_STATE_UNDEFINED_14",
|
||||||
"ACTOR_STATE_UNDEFINED_15",
|
"AKGL_ACTOR_STATE_UNDEFINED_15",
|
||||||
"ACTOR_STATE_UNDEFINED_16",
|
"AKGL_ACTOR_STATE_UNDEFINED_16",
|
||||||
"ACTOR_STATE_UNDEFINED_17",
|
"AKGL_ACTOR_STATE_UNDEFINED_17",
|
||||||
"ACTOR_STATE_UNDEFINED_18",
|
"AKGL_ACTOR_STATE_UNDEFINED_18",
|
||||||
"ACTOR_STATE_UNDEFINED_19",
|
"AKGL_ACTOR_STATE_UNDEFINED_19",
|
||||||
"ACTOR_STATE_UNDEFINED_20",
|
"AKGL_ACTOR_STATE_UNDEFINED_20",
|
||||||
"ACTOR_STATE_UNDEFINED_21",
|
"AKGL_ACTOR_STATE_UNDEFINED_21",
|
||||||
"ACTOR_STATE_UNDEFINED_22",
|
"AKGL_ACTOR_STATE_UNDEFINED_22",
|
||||||
"ACTOR_STATE_UNDEFINED_23",
|
"AKGL_ACTOR_STATE_UNDEFINED_23",
|
||||||
"ACTOR_STATE_UNDEFINED_24",
|
"AKGL_ACTOR_STATE_UNDEFINED_24",
|
||||||
"ACTOR_STATE_UNDEFINED_25",
|
"AKGL_ACTOR_STATE_UNDEFINED_25",
|
||||||
"ACTOR_STATE_UNDEFINED_26",
|
"AKGL_ACTOR_STATE_UNDEFINED_26",
|
||||||
"ACTOR_STATE_UNDEFINED_27",
|
"AKGL_ACTOR_STATE_UNDEFINED_27",
|
||||||
"ACTOR_STATE_UNDEFINED_28",
|
"AKGL_ACTOR_STATE_UNDEFINED_28",
|
||||||
"ACTOR_STATE_UNDEFINED_29",
|
"AKGL_ACTOR_STATE_UNDEFINED_29",
|
||||||
"ACTOR_STATE_UNDEFINED_30",
|
"AKGL_ACTOR_STATE_UNDEFINED_30",
|
||||||
"ACTOR_STATE_UNDEFINED_31",
|
"AKGL_ACTOR_STATE_UNDEFINED_31",
|
||||||
};
|
};
|
||||||
|
|||||||
39
src/assets.c
39
src/assets.c
@@ -1,47 +1,48 @@
|
|||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <SDL3_image/SDL_image.h>
|
#include <SDL3_image/SDL_image.h>
|
||||||
#include <SDL3_mixer/SDL_mixer.h>
|
#include <SDL3_mixer/SDL_mixer.h>
|
||||||
#include <sdlerror.h>
|
#include <akerror.h>
|
||||||
#include <sdl3game/game.h>
|
#include <akgl/game.h>
|
||||||
#include <sdl3game/staticstring.h>
|
#include <akgl/staticstring.h>
|
||||||
#include <sdl3game/heap.h>
|
#include <akgl/heap.h>
|
||||||
|
#include <akgl/error.h>
|
||||||
|
|
||||||
ErrorContext *load_start_bgm(char *fname)
|
akerr_ErrorContext *akgl_load_start_bgm(char *fname)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
string *tmpstr = NULL;
|
//akgl_String *tmpstr = NULL;
|
||||||
MIX_Track *bgmtrack = NULL;
|
MIX_Track *bgmtrack = NULL;
|
||||||
SDL_PropertiesID bgmprops = 0;
|
SDL_PropertiesID bgmprops = 0;
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
FAIL_ZERO_BREAK(errctx, fname, ERR_NULLPOINTER, "load_start_bgm received NULL filename");
|
FAIL_ZERO_BREAK(errctx, fname, AKERR_NULLPOINTER, "akgl_load_start_bgm received NULL filename");
|
||||||
CATCH(errctx, heap_next_string(&tmpstr));
|
//CATCH(errctx, akgl_heap_next_string(&tmpstr));
|
||||||
CATCH(errctx, string_initialize(tmpstr, NULL));
|
//CATCH(errctx, akgl_string_initialize(tmpstr, NULL));
|
||||||
|
|
||||||
SDL_snprintf((char *)&tmpstr->data, MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), fname);
|
//SDL_snprintf((char *)&tmpstr->data, AKGL_MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), fname);
|
||||||
SDL_Log("Loading music asset from %s", (char *)&tmpstr->data);
|
SDL_Log("Loading music asset from %s", fname);
|
||||||
bgm = MIX_LoadAudio(game.mixer, (char *)&tmpstr->data, true);
|
bgm = MIX_LoadAudio(akgl_mixer, fname, true);
|
||||||
FAIL_ZERO_BREAK(errctx, bgm, ERR_NULLPOINTER, "Failed to load music asset %s : %s", (char *)&tmpstr->data, SDL_GetError());
|
FAIL_ZERO_BREAK(errctx, bgm, AKERR_NULLPOINTER, "Failed to load music asset %s : %s", fname, SDL_GetError());
|
||||||
|
|
||||||
bgmtrack = MIX_CreateTrack(game.mixer);
|
bgmtrack = MIX_CreateTrack(akgl_mixer);
|
||||||
FAIL_ZERO_BREAK(errctx, bgmtrack, ERR_NULLPOINTER, "Failed to create audio track for background music: %s", SDL_GetError());
|
FAIL_ZERO_BREAK(errctx, bgmtrack, AKERR_NULLPOINTER, "Failed to create audio track for background music: %s", SDL_GetError());
|
||||||
|
|
||||||
game.tracks[GAME_AUDIO_TRACK_BGM] = bgmtrack;
|
akgl_tracks[AKGL_GAME_AUDIO_TRACK_BGM] = bgmtrack;
|
||||||
|
|
||||||
FAIL_ZERO_BREAK(
|
FAIL_ZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
MIX_SetTrackAudio(bgmtrack, bgm),
|
MIX_SetTrackAudio(bgmtrack, bgm),
|
||||||
ERR_SDL,
|
AKGL_ERR_SDL,
|
||||||
"%s",
|
"%s",
|
||||||
SDL_GetError());
|
SDL_GetError());
|
||||||
|
|
||||||
SDL_SetNumberProperty(bgmprops, MIX_PROP_PLAY_LOOPS_NUMBER, -1);
|
SDL_SetNumberProperty(bgmprops, MIX_PROP_PLAY_LOOPS_NUMBER, -1);
|
||||||
|
|
||||||
if (!MIX_PlayTrack(bgmtrack, bgmprops)) {
|
if (!MIX_PlayTrack(bgmtrack, bgmprops)) {
|
||||||
FAIL_BREAK(errctx, ERR_SDL, "Failed to play music asset %s", fname);
|
FAIL_BREAK(errctx, AKGL_ERR_SDL, "Failed to play music asset %s", fname);
|
||||||
}
|
}
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
IGNORE(heap_release_string(tmpstr));
|
//IGNORE(akgl_heap_release_string(tmpstr));
|
||||||
if ( errctx != NULL ) {
|
if ( errctx != NULL ) {
|
||||||
if ( errctx->status != 0 && bgm != NULL) {
|
if ( errctx->status != 0 && bgm != NULL) {
|
||||||
MIX_DestroyAudio(bgm);
|
MIX_DestroyAudio(bgm);
|
||||||
|
|||||||
161
src/character.c
161
src/character.c
@@ -1,46 +1,46 @@
|
|||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <SDL3_image/SDL_image.h>
|
#include <SDL3_image/SDL_image.h>
|
||||||
#include <sdlerror.h>
|
#include <akerror.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <jansson.h>
|
#include <jansson.h>
|
||||||
|
|
||||||
#include <sdl3game/game.h>
|
#include <akgl/game.h>
|
||||||
#include <sdl3game/sprite.h>
|
#include <akgl/sprite.h>
|
||||||
#include <sdl3game/json_helpers.h>
|
#include <akgl/json_helpers.h>
|
||||||
#include <sdl3game/heap.h>
|
#include <akgl/heap.h>
|
||||||
#include <sdl3game/registry.h>
|
#include <akgl/registry.h>
|
||||||
#include <sdl3game/staticstring.h>
|
#include <akgl/staticstring.h>
|
||||||
#include <sdl3game/iterator.h>
|
#include <akgl/iterator.h>
|
||||||
#include <sdl3game/util.h>
|
#include <akgl/util.h>
|
||||||
|
|
||||||
ErrorContext *character_initialize(character *obj, char *name)
|
akerr_ErrorContext *akgl_character_initialize(akgl_Character *obj, char *name)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, obj, ERR_NULLPOINTER, "NULL character reference");
|
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL akgl_Character reference");
|
||||||
FAIL_ZERO_RETURN(errctx, name, ERR_NULLPOINTER, "NULL name string pointer");
|
FAIL_ZERO_RETURN(errctx, name, AKERR_NULLPOINTER, "NULL name string pointer");
|
||||||
memset(obj, 0x00, sizeof(character));
|
memset(obj, 0x00, sizeof(akgl_Character));
|
||||||
strncpy(obj->name, name, SPRITE_MAX_CHARACTER_NAME_LENGTH);
|
strncpy(obj->name, name, AKGL_SPRITE_MAX_CHARACTER_NAME_LENGTH);
|
||||||
obj->state_sprites = SDL_CreateProperties();
|
obj->state_sprites = SDL_CreateProperties();
|
||||||
FAIL_ZERO_RETURN(errctx, obj->state_sprites, ERR_NULLPOINTER, "Unable to initialize SDL_PropertiesID for character state map");
|
FAIL_ZERO_RETURN(errctx, obj->state_sprites, AKERR_NULLPOINTER, "Unable to initialize SDL_PropertiesID for character state map");
|
||||||
|
|
||||||
obj->sprite_add = &character_sprite_add;
|
obj->sprite_add = &akgl_character_sprite_add;
|
||||||
obj->sprite_get = &character_sprite_get;
|
obj->sprite_get = &akgl_character_sprite_get;
|
||||||
|
|
||||||
FAIL_ZERO_RETURN(
|
FAIL_ZERO_RETURN(
|
||||||
errctx,
|
errctx,
|
||||||
SDL_SetPointerProperty(REGISTRY_CHARACTER, name, (void *)obj),
|
SDL_SetPointerProperty(AKGL_REGISTRY_CHARACTER, name, (void *)obj),
|
||||||
ERR_KEY,
|
AKERR_KEY,
|
||||||
"Unable to add character to registry");
|
"Unable to add character to registry");
|
||||||
obj->refcount += 1;
|
obj->refcount += 1;
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *character_sprite_add(character *basechar, sprite *ref, int state)
|
akerr_ErrorContext *akgl_character_sprite_add(akgl_Character *basechar, akgl_Sprite *ref, int state)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
char stateval[32];
|
char stateval[32];
|
||||||
FAIL_ZERO_RETURN(errctx, basechar, ERR_NULLPOINTER, "NULL character reference");
|
FAIL_ZERO_RETURN(errctx, basechar, AKERR_NULLPOINTER, "NULL character reference");
|
||||||
FAIL_ZERO_RETURN(errctx, ref, ERR_NULLPOINTER, "NULL sprite reference");
|
FAIL_ZERO_RETURN(errctx, ref, AKERR_NULLPOINTER, "NULL sprite reference");
|
||||||
memset(&stateval, 0x00, 32);
|
memset(&stateval, 0x00, 32);
|
||||||
SDL_itoa(state, (char *)&stateval, 10);
|
SDL_itoa(state, (char *)&stateval, 10);
|
||||||
SDL_SetPointerProperty(basechar->state_sprites, (char *)&stateval, ref);
|
SDL_SetPointerProperty(basechar->state_sprites, (char *)&stateval, ref);
|
||||||
@@ -49,17 +49,17 @@ ErrorContext *character_sprite_add(character *basechar, sprite *ref, int state)
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *character_sprite_get(character *basechar, int state, sprite **dest)
|
akerr_ErrorContext *akgl_character_sprite_get(akgl_Character *basechar, int state, akgl_Sprite **dest)
|
||||||
{
|
{
|
||||||
sprite *target = NULL;
|
akgl_Sprite *target = NULL;
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
char stateval[32];
|
char stateval[32];
|
||||||
FAIL_ZERO_RETURN(errctx, dest, ERR_NULLPOINTER, "NULL pointer to sprite pointer (**dest)");
|
FAIL_ZERO_RETURN(errctx, dest, AKERR_NULLPOINTER, "NULL pointer to sprite pointer (**dest)");
|
||||||
FAIL_ZERO_RETURN(errctx, basechar, ERR_NULLPOINTER, "NULL character reference");
|
FAIL_ZERO_RETURN(errctx, basechar, AKERR_NULLPOINTER, "NULL character reference");
|
||||||
memset(&stateval, 0x00, 32);
|
memset(&stateval, 0x00, 32);
|
||||||
SDL_itoa(state, (char *)&stateval, 10);
|
SDL_itoa(state, (char *)&stateval, 10);
|
||||||
*dest = (sprite *)SDL_GetPointerProperty(basechar->state_sprites, (char *)&stateval, NULL);
|
*dest = (akgl_Sprite *)SDL_GetPointerProperty(basechar->state_sprites, (char *)&stateval, NULL);
|
||||||
FAIL_ZERO_RETURN(errctx, *dest, ERR_KEY, "Sprite for state %d (%b) not found in the character's registry", state, state);
|
FAIL_ZERO_RETURN(errctx, *dest, AKERR_KEY, "Sprite for state %d (%b) not found in the character's registry", state, state);
|
||||||
target = *dest;
|
target = *dest;
|
||||||
//SDL_Log("Sprite state %d (%s) has character %s", state, (char *)&stateval, target->name);
|
//SDL_Log("Sprite state %d (%s) has character %s", state, (char *)&stateval, target->name);
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
@@ -67,134 +67,137 @@ ErrorContext *character_sprite_get(character *basechar, int state, sprite **dest
|
|||||||
|
|
||||||
// SDL iterator so we can't return error information here, void only
|
// SDL iterator so we can't return error information here, void only
|
||||||
// this means we don't have anywhere to send exceptions up to, so if we hit an error, we log and exit(1) here
|
// this means we don't have anywhere to send exceptions up to, so if we hit an error, we log and exit(1) here
|
||||||
void character_state_sprites_iterate(void *userdata, SDL_PropertiesID registry, const char *name)
|
void akgl_character_state_sprites_iterate(void *userdata, SDL_PropertiesID registry, const char *name)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
sprite *spriteptr;
|
akgl_Sprite *spriteptr;
|
||||||
iterator *opflags = (iterator *)userdata;
|
akgl_Iterator *opflags = (akgl_Iterator *)userdata;
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
FAIL_ZERO_BREAK(errctx, opflags, ERR_NULLPOINTER, "Character state sprite iterator received null iterator op pointer");
|
FAIL_ZERO_BREAK(errctx, opflags, AKERR_NULLPOINTER, "Character state sprite iterator received null iterator op pointer");
|
||||||
FAIL_ZERO_BREAK(errctx, name, ERR_NULLPOINTER, "Character state sprite iterator received null sprite name");
|
FAIL_ZERO_BREAK(errctx, name, AKERR_NULLPOINTER, "Character state sprite iterator received null sprite name");
|
||||||
spriteptr = (sprite *)SDL_GetPointerProperty(registry, name, NULL);
|
spriteptr = (akgl_Sprite *)SDL_GetPointerProperty(registry, name, NULL);
|
||||||
FAIL_ZERO_BREAK(errctx, spriteptr, ERR_NULLPOINTER, "Character state sprite for %s not found", name);
|
FAIL_ZERO_BREAK(errctx, spriteptr, AKERR_NULLPOINTER, "Character state sprite for %s not found", name);
|
||||||
if ( BITMASK_HAS(opflags->flags, ITERATOR_OP_RELEASE) ) {
|
if ( AKGL_BITMASK_HAS(opflags->flags, AKGL_ITERATOR_OP_RELEASE) ) {
|
||||||
CATCH(errctx, heap_release_sprite(spriteptr));
|
CATCH(errctx, akgl_heap_release_sprite(spriteptr));
|
||||||
}
|
}
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH_NORETURN(errctx);
|
} FINISH_NORETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ErrorContext *character_load_json_state_int_from_strings(json_t *states, int *dest)
|
static akerr_ErrorContext *akgl_character_load_json_state_int_from_strings(json_t *states, int *dest)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
long newstate = 0;
|
long newstate = 0;
|
||||||
string *tmpstring = NULL;
|
akgl_String *tmpstring = NULL;
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, states, ERR_NULLPOINTER, "NULL states array");
|
FAIL_ZERO_RETURN(errctx, states, AKERR_NULLPOINTER, "NULL states array");
|
||||||
FAIL_ZERO_RETURN(errctx, states, ERR_NULLPOINTER, "NULL destination integer");
|
FAIL_ZERO_RETURN(errctx, states, AKERR_NULLPOINTER, "NULL destination integer");
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, heap_next_string(&tmpstring));
|
CATCH(errctx, akgl_heap_next_string(&tmpstring));
|
||||||
for ( i = 0; i < json_array_size((json_t *)states) ; i++ ) {
|
for ( i = 0; i < json_array_size((json_t *)states) ; i++ ) {
|
||||||
CATCH(errctx, get_json_array_index_string(states, i, &tmpstring));
|
CATCH(errctx, akgl_get_json_array_index_string(states, i, &tmpstring));
|
||||||
newstate = (long)SDL_GetNumberProperty(REGISTRY_ACTOR_STATE_STRINGS, (char *)&tmpstring->data, 0);
|
newstate = (long)SDL_GetNumberProperty(AKGL_REGISTRY_ACTOR_STATE_STRINGS, (char *)&tmpstring->data, 0);
|
||||||
FAIL_ZERO_BREAK(errctx, newstate, ERR_KEY, "Unknown actor state %s", (char *)&tmpstring->data);
|
FAIL_ZERO_BREAK(errctx, newstate, AKERR_KEY, "Unknown actor state %s", (char *)&tmpstring->data);
|
||||||
*dest = (*dest | (int)(newstate));
|
*dest = (*dest | (int)(newstate));
|
||||||
}
|
}
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
IGNORE(heap_release_string(tmpstring));
|
IGNORE(akgl_heap_release_string(tmpstring));
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ErrorContext *character_load_json_inner(json_t *json, character *obj)
|
static akerr_ErrorContext *akgl_character_load_json_inner(json_t *json, akgl_Character *obj)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
json_t *mappings = NULL;
|
json_t *mappings = NULL;
|
||||||
json_t *curmapping = NULL;
|
json_t *curmapping = NULL;
|
||||||
json_t *statearray = NULL;
|
json_t *statearray = NULL;
|
||||||
sprite *spriteptr = NULL;
|
akgl_Sprite *spriteptr = NULL;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
string *tmpstr = NULL;
|
akgl_String *tmpstr = NULL;
|
||||||
string *tmpstr2 = NULL;
|
akgl_String *tmpstr2 = NULL;
|
||||||
int stateval = 0;
|
int stateval = 0;
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, get_json_string_value((json_t *)json, "name", &tmpstr));
|
CATCH(errctx, akgl_get_json_string_value((json_t *)json, "name", &tmpstr));
|
||||||
CATCH(errctx, character_initialize((character *)obj, tmpstr->data));
|
CATCH(errctx, akgl_character_initialize((akgl_Character *)obj, tmpstr->data));
|
||||||
CATCH(errctx, get_json_array_value((json_t *)json, "sprite_mappings", &mappings));
|
CATCH(errctx, akgl_get_json_array_value((json_t *)json, "sprite_mappings", &mappings));
|
||||||
for ( i = 0; i < json_array_size((json_t *)mappings) ; i++ ) {
|
for ( i = 0; i < json_array_size((json_t *)mappings) ; i++ ) {
|
||||||
stateval = 0;
|
stateval = 0;
|
||||||
CATCH(errctx, get_json_array_index_object((json_t *)mappings, i, &curmapping));
|
CATCH(errctx, akgl_get_json_array_index_object((json_t *)mappings, i, &curmapping));
|
||||||
CATCH(errctx, get_json_string_value((json_t *)curmapping, "sprite", &tmpstr));
|
CATCH(errctx, akgl_get_json_string_value((json_t *)curmapping, "sprite", &tmpstr));
|
||||||
spriteptr = (sprite *)SDL_GetPointerProperty(
|
spriteptr = (akgl_Sprite *)SDL_GetPointerProperty(
|
||||||
REGISTRY_SPRITE,
|
AKGL_REGISTRY_SPRITE,
|
||||||
tmpstr->data,
|
tmpstr->data,
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
CATCH(errctx, get_json_string_value((json_t *)json, "name", &tmpstr2));
|
CATCH(errctx, akgl_get_json_string_value((json_t *)json, "name", &tmpstr2));
|
||||||
|
|
||||||
CATCH(errctx, get_json_array_value((json_t *)curmapping, "state", &statearray));
|
CATCH(errctx, akgl_get_json_array_value((json_t *)curmapping, "state", &statearray));
|
||||||
CATCH(errctx, character_load_json_state_int_from_strings(statearray, &stateval));
|
CATCH(errctx, akgl_character_load_json_state_int_from_strings(statearray, &stateval));
|
||||||
|
|
||||||
CATCH(errctx, get_json_string_value((json_t *)curmapping, "sprite", &tmpstr));
|
CATCH(errctx, akgl_get_json_string_value((json_t *)curmapping, "sprite", &tmpstr));
|
||||||
FAIL_ZERO_BREAK(
|
FAIL_ZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
spriteptr,
|
spriteptr,
|
||||||
ERR_NULLPOINTER,
|
AKERR_NULLPOINTER,
|
||||||
"Character %s for state %b references sprite %s but not found in the registry",
|
"Character %s for state %b references sprite %s but not found in the registry",
|
||||||
tmpstr2->data,
|
tmpstr2->data,
|
||||||
stateval,
|
stateval,
|
||||||
tmpstr->data
|
tmpstr->data
|
||||||
);
|
);
|
||||||
CATCH(errctx, character_sprite_add((character *)obj, (sprite *)spriteptr, stateval));
|
CATCH(errctx, akgl_character_sprite_add((akgl_Character *)obj, (akgl_Sprite *)spriteptr, stateval));
|
||||||
}
|
}
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
if ( tmpstr != NULL ) {
|
if ( tmpstr != NULL ) {
|
||||||
IGNORE(heap_release_string(tmpstr));
|
IGNORE(akgl_heap_release_string(tmpstr));
|
||||||
}
|
}
|
||||||
if ( tmpstr2 != NULL ) {
|
if ( tmpstr2 != NULL ) {
|
||||||
IGNORE(heap_release_string(tmpstr2));
|
IGNORE(akgl_heap_release_string(tmpstr2));
|
||||||
}
|
}
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *character_load_json(char *filename)
|
akerr_ErrorContext *akgl_character_load_json(char *filename)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
json_t *json;
|
json_t *json;
|
||||||
json_error_t error;
|
json_error_t error;
|
||||||
character *obj = NULL;
|
akgl_Character *obj = NULL;
|
||||||
//string *tmpstr = NULL;
|
//akgl_String *tmpstr = NULL;
|
||||||
|
|
||||||
FAIL_ZERO_RETURN(errctx, filename, ERR_NULLPOINTER, "Received null filename");
|
FAIL_ZERO_RETURN(errctx, filename, AKERR_NULLPOINTER, "Received null filename");
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, heap_next_character(&obj));
|
CATCH(errctx, akgl_heap_next_character(&obj));
|
||||||
//CATCH(errctx, heap_next_string(&tmpstr));
|
//CATCH(errctx, akgl_heap_next_string(&tmpstr));
|
||||||
//CATCH(errctx, string_initialize(tmpstr, NULL));
|
//CATCH(errctx, akgl_string_initialize(tmpstr, NULL));
|
||||||
//SDL_snprintf((char *)&tmpstr->data, MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), filename);
|
//SDL_snprintf((char *)&tmpstr->data, AKGL_MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), filename);
|
||||||
json = (json_t *)json_load_file(filename, 0, &error);
|
json = (json_t *)json_load_file(filename, 0, &error);
|
||||||
FAIL_ZERO_BREAK(
|
FAIL_ZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
json,
|
json,
|
||||||
ERR_NULLPOINTER,
|
AKERR_NULLPOINTER,
|
||||||
"Error while loading character from %s on line %d: %s", filename, error.line, error.text
|
"Error while loading character from %s on line %d: %s", filename, error.line, error.text
|
||||||
);
|
);
|
||||||
CATCH(errctx, character_load_json_inner(json, obj));
|
CATCH(errctx, akgl_character_load_json_inner(json, obj));
|
||||||
CATCH(errctx, get_json_number_value(json, "velocity_x", &obj->vx));
|
CATCH(errctx, akgl_get_json_integer_value(json, "movementspeed", (int *)&obj->movementspeed));
|
||||||
CATCH(errctx, get_json_number_value(json, "velocity_y", &obj->vy));
|
obj->movementspeed = obj->movementspeed * AKGL_TIME_ONESEC_MS;
|
||||||
|
CATCH(errctx, akgl_get_json_number_value(json, "velocity_x", &obj->vx));
|
||||||
|
CATCH(errctx, akgl_get_json_number_value(json, "velocity_y", &obj->vy));
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
//IGNORE(heap_release_string(tmpstr));
|
//IGNORE(akgl_heap_release_string(tmpstr));
|
||||||
if ( errctx != NULL ) {
|
if ( errctx != NULL ) {
|
||||||
if ( errctx->status != 0 ) {
|
if ( errctx->status != 0 ) {
|
||||||
IGNORE(heap_release_character(obj));
|
IGNORE(akgl_heap_release_character(obj));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
|
SDL_Log("Character %s loaded from %s", obj->name, filename);
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|||||||
222
src/controller.c
222
src/controller.c
@@ -1,30 +1,47 @@
|
|||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <sdlerror.h>
|
#include <akerror.h>
|
||||||
#include <sdl3game/heap.h>
|
#include <akgl/heap.h>
|
||||||
#include <sdl3game/registry.h>
|
#include <akgl/registry.h>
|
||||||
#include <sdl3game/game.h>
|
#include <akgl/game.h>
|
||||||
#include <sdl3game/controller.h>
|
#include <akgl/controller.h>
|
||||||
|
|
||||||
SDL3GControlMap GAME_ControlMaps[MAX_CONTROL_MAPS];
|
akgl_ControlMap GAME_ControlMaps[AKGL_MAX_CONTROL_MAPS];
|
||||||
|
|
||||||
ErrorContext *controller_handle_event(void *appstate, SDL_Event *event)
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_controller_list_keyboards(void)
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
SDL_KeyboardID *keyboards = SDL_GetKeyboards(&count);
|
||||||
|
PREPARE_ERROR(e);
|
||||||
|
|
||||||
|
FAIL_ZERO_RETURN(e, keyboards, AKERR_NULLPOINTER, "%s", SDL_GetError());
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
const char *name = SDL_GetKeyboardNameForID(keyboards[i]);
|
||||||
|
SDL_Log("Keyboard %d: ID %u, Name: %s\n", i, keyboards[i], name);
|
||||||
|
}
|
||||||
|
SUCCEED_RETURN(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
akerr_ErrorContext *akgl_controller_handle_event(void *appstate, SDL_Event *event)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int j = 0;
|
int j = 0;
|
||||||
int eventButtonComboMatch = 0;
|
int eventButtonComboMatch = 0;
|
||||||
SDL3GControlMap *curmap = NULL;
|
akgl_ControlMap *curmap = NULL;
|
||||||
SDL3GControl *curcontrol = NULL;
|
akgl_Control *curcontrol = NULL;
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
|
FAIL_ZERO_RETURN(errctx, appstate, AKERR_NULLPOINTER, "NULL appstate");
|
||||||
|
FAIL_ZERO_RETURN(errctx, event, AKERR_NULLPOINTER, "NULL event");
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
for ( i = 0 ; i < MAX_CONTROL_MAPS; i++ ) {
|
for ( i = 0 ; i < AKGL_MAX_CONTROL_MAPS; i++ ) {
|
||||||
curmap = &GAME_ControlMaps[i];
|
curmap = &GAME_ControlMaps[i];
|
||||||
if ( curmap->target == NULL ) {
|
if ( curmap->target == NULL ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//SDL_Log("Control map %d maps to actor %s", i, curmap->target->name);
|
//SDL_Log("Control map %d maps to actor %s", i, curmap->target->name);
|
||||||
//SDL_Log("event from keyboard %d", event->key.which);
|
//SDL_Log("event from keyboard %d", event->key.which);
|
||||||
for ( j = 0; j < MAX_CONTROLS; j++ ) {
|
for ( j = 0; j < AKGL_MAX_CONTROLS; j++ ) {
|
||||||
curcontrol = &curmap->controls[j];
|
curcontrol = &curmap->controls[j];
|
||||||
//SDL_Log("button/key is processed by controlmap %d control %d", i, j);
|
//SDL_Log("button/key is processed by controlmap %d control %d", i, j);
|
||||||
//SDL_Log("event %d -> control on %d off %d", event->type, curcontrol->event_on, curcontrol->event_off);
|
//SDL_Log("event %d -> control on %d off %d", event->type, curcontrol->event_on, curcontrol->event_off);
|
||||||
@@ -41,119 +58,119 @@ ErrorContext *controller_handle_event(void *appstate, SDL_Event *event)
|
|||||||
);
|
);
|
||||||
if ( event->type == curcontrol->event_on && eventButtonComboMatch) {
|
if ( event->type == curcontrol->event_on && eventButtonComboMatch) {
|
||||||
CATCH(errctx, curcontrol->handler_on(curmap->target, event));
|
CATCH(errctx, curcontrol->handler_on(curmap->target, event));
|
||||||
goto _controller_handle_event_success;
|
goto _akgl_controller_handle_event_success;
|
||||||
} else if ( event->type == curcontrol->event_off && eventButtonComboMatch ) {
|
} else if ( event->type == curcontrol->event_off && eventButtonComboMatch ) {
|
||||||
CATCH(errctx, curcontrol->handler_off(curmap->target, event));
|
CATCH(errctx, curcontrol->handler_off(curmap->target, event));
|
||||||
goto _controller_handle_event_success;
|
goto _akgl_controller_handle_event_success;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_controller_handle_event_success:
|
_akgl_controller_handle_event_success:
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *gamepad_handle_button_down(void *appstate, SDL_Event *event)
|
akerr_ErrorContext *gamepad_handle_button_down(void *appstate, SDL_Event *event)
|
||||||
{
|
{
|
||||||
actor *player = NULL;
|
akgl_Actor *player = NULL;
|
||||||
|
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
|
|
||||||
FAIL_ZERO_RETURN(errctx, appstate, ERR_NULLPOINTER, "NULL appstate");
|
FAIL_ZERO_RETURN(errctx, appstate, AKERR_NULLPOINTER, "NULL appstate");
|
||||||
FAIL_ZERO_RETURN(errctx, appstate, ERR_NULLPOINTER, "NULL event");
|
FAIL_ZERO_RETURN(errctx, appstate, AKERR_NULLPOINTER, "NULL event");
|
||||||
player = SDL_GetPointerProperty(REGISTRY_ACTOR, "player", NULL);
|
player = SDL_GetPointerProperty(AKGL_REGISTRY_ACTOR, "player", NULL);
|
||||||
FAIL_ZERO_RETURN(errctx, appstate, ERR_NULLPOINTER, "Player actor does not exist");
|
FAIL_ZERO_RETURN(errctx, appstate, AKERR_NULLPOINTER, "Player actor does not exist");
|
||||||
|
|
||||||
if ( event->gbutton.button == SDL_GAMEPAD_BUTTON_DPAD_DOWN ||
|
if ( event->gbutton.button == SDL_GAMEPAD_BUTTON_DPAD_DOWN ||
|
||||||
event->key.key == SDLK_DOWN ) {
|
event->key.key == SDLK_DOWN ) {
|
||||||
SDL_Log("Processing dpad down : state %d", player->state);
|
SDL_Log("Processing dpad down : state %d", player->state);
|
||||||
BITMASK_ADD(player->state, ACTOR_STATE_MOVING_DOWN);
|
AKGL_BITMASK_ADD(player->state, AKGL_ACTOR_STATE_MOVING_DOWN);
|
||||||
if ( !player->movement_controls_face ) {
|
if ( !player->movement_controls_face ) {
|
||||||
BITMASK_DEL(player->state, ACTOR_STATE_FACE_ALL);
|
AKGL_BITMASK_DEL(player->state, AKGL_ACTOR_STATE_FACE_ALL);
|
||||||
BITMASK_ADD(player->state, ACTOR_STATE_FACE_DOWN);
|
AKGL_BITMASK_ADD(player->state, AKGL_ACTOR_STATE_FACE_DOWN);
|
||||||
}
|
}
|
||||||
SDL_Log("New state : %d", player->state);
|
SDL_Log("New state : %d", player->state);
|
||||||
} else if ( event->gbutton.button == SDL_GAMEPAD_BUTTON_DPAD_UP ||
|
} else if ( event->gbutton.button == SDL_GAMEPAD_BUTTON_DPAD_UP ||
|
||||||
event->key.key == SDLK_UP ) {
|
event->key.key == SDLK_UP ) {
|
||||||
SDL_Log("Processing dpad up");
|
SDL_Log("Processing dpad up");
|
||||||
BITMASK_ADD(player->state, ACTOR_STATE_MOVING_UP);
|
AKGL_BITMASK_ADD(player->state, AKGL_ACTOR_STATE_MOVING_UP);
|
||||||
if ( !player->movement_controls_face ) {
|
if ( !player->movement_controls_face ) {
|
||||||
BITMASK_DEL(player->state, ACTOR_STATE_FACE_ALL);
|
AKGL_BITMASK_DEL(player->state, AKGL_ACTOR_STATE_FACE_ALL);
|
||||||
BITMASK_ADD(player->state, ACTOR_STATE_FACE_UP);
|
AKGL_BITMASK_ADD(player->state, AKGL_ACTOR_STATE_FACE_UP);
|
||||||
}
|
}
|
||||||
SDL_Log("New state : %d", player->state);
|
SDL_Log("New state : %d", player->state);
|
||||||
} else if ( event->gbutton.button == SDL_GAMEPAD_BUTTON_DPAD_LEFT ||
|
} else if ( event->gbutton.button == SDL_GAMEPAD_BUTTON_DPAD_LEFT ||
|
||||||
event->key.key == SDLK_LEFT ) {
|
event->key.key == SDLK_LEFT ) {
|
||||||
SDL_Log("Processing dpad left");
|
SDL_Log("Processing dpad left");
|
||||||
BITMASK_ADD(player->state, ACTOR_STATE_MOVING_LEFT);
|
AKGL_BITMASK_ADD(player->state, AKGL_ACTOR_STATE_MOVING_LEFT);
|
||||||
if ( !player->movement_controls_face ) {
|
if ( !player->movement_controls_face ) {
|
||||||
BITMASK_DEL(player->state, ACTOR_STATE_FACE_ALL);
|
AKGL_BITMASK_DEL(player->state, AKGL_ACTOR_STATE_FACE_ALL);
|
||||||
BITMASK_ADD(player->state, ACTOR_STATE_FACE_LEFT);
|
AKGL_BITMASK_ADD(player->state, AKGL_ACTOR_STATE_FACE_LEFT);
|
||||||
}
|
}
|
||||||
SDL_Log("New state : %d", player->state);
|
SDL_Log("New state : %d", player->state);
|
||||||
} else if ( event->gbutton.button == SDL_GAMEPAD_BUTTON_DPAD_RIGHT ||
|
} else if ( event->gbutton.button == SDL_GAMEPAD_BUTTON_DPAD_RIGHT ||
|
||||||
event->key.key == SDLK_RIGHT ) {
|
event->key.key == SDLK_RIGHT ) {
|
||||||
SDL_Log("Processing dpad right");
|
SDL_Log("Processing dpad right");
|
||||||
BITMASK_ADD(player->state, ACTOR_STATE_MOVING_RIGHT);
|
AKGL_BITMASK_ADD(player->state, AKGL_ACTOR_STATE_MOVING_RIGHT);
|
||||||
if ( !player->movement_controls_face ) {
|
if ( !player->movement_controls_face ) {
|
||||||
BITMASK_DEL(player->state, ACTOR_STATE_FACE_ALL);
|
AKGL_BITMASK_DEL(player->state, AKGL_ACTOR_STATE_FACE_ALL);
|
||||||
BITMASK_ADD(player->state, ACTOR_STATE_FACE_RIGHT);
|
AKGL_BITMASK_ADD(player->state, AKGL_ACTOR_STATE_FACE_RIGHT);
|
||||||
}
|
}
|
||||||
SDL_Log("New state : %d", player->state);
|
SDL_Log("New state : %d", player->state);
|
||||||
}
|
}
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *gamepad_handle_button_up(void *appstate, SDL_Event *event)
|
akerr_ErrorContext *gamepad_handle_button_up(void *appstate, SDL_Event *event)
|
||||||
{
|
{
|
||||||
actor *player = NULL;
|
akgl_Actor *player = NULL;
|
||||||
|
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
|
|
||||||
FAIL_ZERO_RETURN(errctx, appstate, ERR_NULLPOINTER, "NULL appstate");
|
FAIL_ZERO_RETURN(errctx, appstate, AKERR_NULLPOINTER, "NULL appstate");
|
||||||
FAIL_ZERO_RETURN(errctx, appstate, ERR_NULLPOINTER, "NULL event");
|
FAIL_ZERO_RETURN(errctx, appstate, AKERR_NULLPOINTER, "NULL event");
|
||||||
player = SDL_GetPointerProperty(REGISTRY_ACTOR, "player", NULL);
|
player = SDL_GetPointerProperty(AKGL_REGISTRY_ACTOR, "player", NULL);
|
||||||
FAIL_ZERO_RETURN(errctx, appstate, ERR_NULLPOINTER, "Player actor does not exist");
|
FAIL_ZERO_RETURN(errctx, appstate, AKERR_NULLPOINTER, "Player actor does not exist");
|
||||||
|
|
||||||
if ( event->gbutton.button == SDL_GAMEPAD_BUTTON_DPAD_DOWN ||
|
if ( event->gbutton.button == SDL_GAMEPAD_BUTTON_DPAD_DOWN ||
|
||||||
event->key.key == SDLK_DOWN ) {
|
event->key.key == SDLK_DOWN ) {
|
||||||
SDL_Log("processing down release");
|
SDL_Log("processing down release");
|
||||||
BITMASK_DEL(player->state, ACTOR_STATE_MOVING_DOWN);
|
AKGL_BITMASK_DEL(player->state, AKGL_ACTOR_STATE_MOVING_DOWN);
|
||||||
player->curSpriteFrameId = 0;
|
player->curSpriteFrameId = 0;
|
||||||
SDL_Log("New state : %d", player->state);
|
SDL_Log("New state : %d", player->state);
|
||||||
} else if ( event->gbutton.button == SDL_GAMEPAD_BUTTON_DPAD_UP ||
|
} else if ( event->gbutton.button == SDL_GAMEPAD_BUTTON_DPAD_UP ||
|
||||||
event->key.key == SDLK_UP ) {
|
event->key.key == SDLK_UP ) {
|
||||||
SDL_Log("processing up release");
|
SDL_Log("processing up release");
|
||||||
BITMASK_DEL(player->state, ACTOR_STATE_MOVING_UP);
|
AKGL_BITMASK_DEL(player->state, AKGL_ACTOR_STATE_MOVING_UP);
|
||||||
player->curSpriteFrameId = 0;
|
player->curSpriteFrameId = 0;
|
||||||
SDL_Log("New state : %d", player->state);
|
SDL_Log("New state : %d", player->state);
|
||||||
} else if ( event->gbutton.button == SDL_GAMEPAD_BUTTON_DPAD_RIGHT ||
|
} else if ( event->gbutton.button == SDL_GAMEPAD_BUTTON_DPAD_RIGHT ||
|
||||||
event->key.key == SDLK_RIGHT) {
|
event->key.key == SDLK_RIGHT) {
|
||||||
SDL_Log("processing right release");
|
SDL_Log("processing right release");
|
||||||
BITMASK_DEL(player->state, ACTOR_STATE_MOVING_RIGHT);
|
AKGL_BITMASK_DEL(player->state, AKGL_ACTOR_STATE_MOVING_RIGHT);
|
||||||
player->curSpriteFrameId = 0;
|
player->curSpriteFrameId = 0;
|
||||||
SDL_Log("New state : %d", player->state);
|
SDL_Log("New state : %d", player->state);
|
||||||
} else if ( event->gbutton.button == SDL_GAMEPAD_BUTTON_DPAD_LEFT ||
|
} else if ( event->gbutton.button == SDL_GAMEPAD_BUTTON_DPAD_LEFT ||
|
||||||
event->key.key == SDLK_LEFT ) {
|
event->key.key == SDLK_LEFT ) {
|
||||||
SDL_Log("processing left release");
|
SDL_Log("processing left release");
|
||||||
BITMASK_DEL(player->state, ACTOR_STATE_MOVING_LEFT);
|
AKGL_BITMASK_DEL(player->state, AKGL_ACTOR_STATE_MOVING_LEFT);
|
||||||
player->curSpriteFrameId = 0;
|
player->curSpriteFrameId = 0;
|
||||||
SDL_Log("New state : %d", player->state);
|
SDL_Log("New state : %d", player->state);
|
||||||
}
|
}
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *gamepad_handle_added(void *appstate, SDL_Event *event)
|
akerr_ErrorContext *gamepad_handle_added(void *appstate, SDL_Event *event)
|
||||||
{
|
{
|
||||||
SDL_JoystickID which;
|
SDL_JoystickID which;
|
||||||
SDL_Gamepad *gamepad = NULL;
|
SDL_Gamepad *gamepad = NULL;
|
||||||
char *mapping = NULL;
|
char *mapping = NULL;
|
||||||
|
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, appstate, ERR_NULLPOINTER, "NULL appstate");
|
FAIL_ZERO_RETURN(errctx, appstate, AKERR_NULLPOINTER, "NULL appstate");
|
||||||
FAIL_ZERO_RETURN(errctx, appstate, ERR_NULLPOINTER, "NULL event");
|
FAIL_ZERO_RETURN(errctx, appstate, AKERR_NULLPOINTER, "NULL event");
|
||||||
|
|
||||||
which = event->gbutton.which;
|
which = event->gbutton.which;
|
||||||
gamepad = SDL_GetGamepadFromID(which);
|
gamepad = SDL_GetGamepadFromID(which);
|
||||||
@@ -175,14 +192,14 @@ ErrorContext *gamepad_handle_added(void *appstate, SDL_Event *event)
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *gamepad_handle_removed(void *appstate, SDL_Event *event)
|
akerr_ErrorContext *gamepad_handle_removed(void *appstate, SDL_Event *event)
|
||||||
{
|
{
|
||||||
SDL_JoystickID which;
|
SDL_JoystickID which;
|
||||||
SDL_Gamepad *gamepad = NULL;
|
SDL_Gamepad *gamepad = NULL;
|
||||||
|
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, appstate, ERR_NULLPOINTER, "NULL appstate");
|
FAIL_ZERO_RETURN(errctx, appstate, AKERR_NULLPOINTER, "NULL appstate");
|
||||||
FAIL_ZERO_RETURN(errctx, appstate, ERR_NULLPOINTER, "NULL event");
|
FAIL_ZERO_RETURN(errctx, appstate, AKERR_NULLPOINTER, "NULL event");
|
||||||
|
|
||||||
which = event->gbutton.which;
|
which = event->gbutton.which;
|
||||||
gamepad = SDL_GetGamepadFromID(which);
|
gamepad = SDL_GetGamepadFromID(which);
|
||||||
@@ -193,3 +210,112 @@ ErrorContext *gamepad_handle_removed(void *appstate, SDL_Event *event)
|
|||||||
SDL_Log("Gamepad #%u removed", (unsigned int) which);
|
SDL_Log("Gamepad #%u removed", (unsigned int) which);
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_controller_pushmap(int controlmapid, akgl_Control *control)
|
||||||
|
{
|
||||||
|
int newmapid = 0;
|
||||||
|
PREPARE_ERROR(errctx);
|
||||||
|
ATTEMPT {
|
||||||
|
FAIL_ZERO_RETURN(errctx, control, AKERR_NULLPOINTER, "NULL Control");
|
||||||
|
FAIL_NONZERO_RETURN(errctx, (controlmapid >= AKGL_MAX_CONTROL_MAPS), AKERR_OUTOFBOUNDS, "ID %d exceeds maximum %d", controlmapid, AKGL_MAX_CONTROL_MAPS);
|
||||||
|
newmapid = GAME_ControlMaps[controlmapid].nextMap;
|
||||||
|
FAIL_ZERO_RETURN(errctx, (AKGL_MAX_CONTROLS - newmapid), AKERR_OUTOFBOUNDS, "Control map ID %d is full", controlmapid);
|
||||||
|
memcpy((void *)&GAME_ControlMaps[controlmapid].controls[newmapid], control, sizeof(akgl_Control));
|
||||||
|
GAME_ControlMaps[controlmapid].nextMap = newmapid + 1;
|
||||||
|
} CLEANUP {
|
||||||
|
} PROCESS(errctx) {
|
||||||
|
} FINISH(errctx, true);
|
||||||
|
SUCCEED_RETURN(errctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_controller_default(int controlmapid, char *actorname, int kbid, int jsid)
|
||||||
|
{
|
||||||
|
akgl_ControlMap *controlmap;
|
||||||
|
akgl_Control control;
|
||||||
|
|
||||||
|
PREPARE_ERROR(errctx);
|
||||||
|
ATTEMPT {
|
||||||
|
// set up the control map
|
||||||
|
FAIL_NONZERO_RETURN(errctx, (controlmapid >= AKGL_MAX_CONTROL_MAPS), AKERR_OUTOFBOUNDS, "ID %d exceeds maximum %d", controlmapid, AKGL_MAX_CONTROL_MAPS);
|
||||||
|
memset((void *)&control, 0x00, sizeof(akgl_Control));
|
||||||
|
controlmap = &GAME_ControlMaps[controlmapid];
|
||||||
|
controlmap->kbid = kbid;
|
||||||
|
controlmap->jsid = jsid;
|
||||||
|
|
||||||
|
controlmap->target = SDL_GetPointerProperty(AKGL_REGISTRY_ACTOR, actorname, NULL);
|
||||||
|
FAIL_ZERO_BREAK(errctx, controlmap->target, AKERR_REGISTRY, "Actor %s not found in registry", actorname);
|
||||||
|
|
||||||
|
// ---- KEYBOARD CONTROLS ----
|
||||||
|
|
||||||
|
// Move down
|
||||||
|
control.key = SDLK_DOWN;
|
||||||
|
control.event_on = SDL_EVENT_KEY_DOWN;
|
||||||
|
control.event_off = SDL_EVENT_KEY_UP;
|
||||||
|
control.handler_on = &akgl_Actor_cmhf_down_on;
|
||||||
|
control.handler_off = &akgl_Actor_cmhf_down_off;
|
||||||
|
CATCH(errctx, akgl_controller_pushmap(controlmapid, &control));
|
||||||
|
|
||||||
|
// Move up
|
||||||
|
control.key = SDLK_UP;
|
||||||
|
control.event_on = SDL_EVENT_KEY_DOWN;
|
||||||
|
control.event_off = SDL_EVENT_KEY_UP;
|
||||||
|
control.handler_on = &akgl_Actor_cmhf_up_on;
|
||||||
|
control.handler_off = &akgl_Actor_cmhf_up_off;
|
||||||
|
CATCH(errctx, akgl_controller_pushmap(controlmapid, &control));
|
||||||
|
|
||||||
|
// Move left
|
||||||
|
control.key = SDLK_LEFT;
|
||||||
|
control.event_on = SDL_EVENT_KEY_DOWN;
|
||||||
|
control.event_off = SDL_EVENT_KEY_UP;
|
||||||
|
control.handler_on = &akgl_Actor_cmhf_left_on;
|
||||||
|
control.handler_off = &akgl_Actor_cmhf_left_off;
|
||||||
|
CATCH(errctx, akgl_controller_pushmap(controlmapid, &control));
|
||||||
|
|
||||||
|
// Move right
|
||||||
|
control.key = SDLK_RIGHT;
|
||||||
|
control.event_on = SDL_EVENT_KEY_DOWN;
|
||||||
|
control.event_off = SDL_EVENT_KEY_UP;
|
||||||
|
control.handler_on = &akgl_Actor_cmhf_right_on;
|
||||||
|
control.handler_off = &akgl_Actor_cmhf_right_off;
|
||||||
|
CATCH(errctx, akgl_controller_pushmap(controlmapid, &control));
|
||||||
|
|
||||||
|
control.key = 0;
|
||||||
|
// ----- GAMEPAD CONTROLS
|
||||||
|
// Move down
|
||||||
|
control.button = SDL_GAMEPAD_BUTTON_DPAD_DOWN;
|
||||||
|
control.event_on = SDL_EVENT_GAMEPAD_BUTTON_DOWN;
|
||||||
|
control.event_off = SDL_EVENT_GAMEPAD_BUTTON_UP;
|
||||||
|
control.handler_on = &akgl_Actor_cmhf_down_on;
|
||||||
|
control.handler_off = &akgl_Actor_cmhf_down_off;
|
||||||
|
CATCH(errctx, akgl_controller_pushmap(controlmapid, &control));
|
||||||
|
|
||||||
|
// Move up
|
||||||
|
control.button = SDL_GAMEPAD_BUTTON_DPAD_UP;
|
||||||
|
control.event_on = SDL_EVENT_GAMEPAD_BUTTON_DOWN;
|
||||||
|
control.event_off = SDL_EVENT_GAMEPAD_BUTTON_UP;
|
||||||
|
control.handler_on = &akgl_Actor_cmhf_up_on;
|
||||||
|
control.handler_off = &akgl_Actor_cmhf_up_off;
|
||||||
|
CATCH(errctx, akgl_controller_pushmap(controlmapid, &control));
|
||||||
|
|
||||||
|
// Move left
|
||||||
|
control.button = SDL_GAMEPAD_BUTTON_DPAD_LEFT;
|
||||||
|
control.event_on = SDL_EVENT_GAMEPAD_BUTTON_DOWN;
|
||||||
|
control.event_off = SDL_EVENT_GAMEPAD_BUTTON_UP;
|
||||||
|
control.handler_on = &akgl_Actor_cmhf_left_on;
|
||||||
|
control.handler_off = &akgl_Actor_cmhf_left_off;
|
||||||
|
CATCH(errctx, akgl_controller_pushmap(controlmapid, &control));
|
||||||
|
|
||||||
|
// Move right
|
||||||
|
control.button = SDL_GAMEPAD_BUTTON_DPAD_RIGHT;
|
||||||
|
control.event_on = SDL_EVENT_GAMEPAD_BUTTON_DOWN;
|
||||||
|
control.event_off = SDL_EVENT_GAMEPAD_BUTTON_UP;
|
||||||
|
control.handler_on = &akgl_Actor_cmhf_right_on;
|
||||||
|
control.handler_off = &akgl_Actor_cmhf_right_off;
|
||||||
|
CATCH(errctx, akgl_controller_pushmap(controlmapid, &control));
|
||||||
|
|
||||||
|
SUCCEED_RETURN(errctx);
|
||||||
|
|
||||||
|
} CLEANUP {
|
||||||
|
} PROCESS(errctx) {
|
||||||
|
} FINISH(errctx, true);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <SDL3_image/SDL_image.h>
|
#include <SDL3_image/SDL_image.h>
|
||||||
#include <SDL3_mixer/SDL_mixer.h>
|
#include <SDL3_mixer/SDL_mixer.h>
|
||||||
#include <sdl3game/game.h>
|
#include <akgl/game.h>
|
||||||
|
|
||||||
/* Draw a Gimpish background pattern to show transparency in the image */
|
/* Draw a Gimpish background pattern to show transparency in the image */
|
||||||
void GAME_draw_background(int w, int h)
|
void akgl_draw_background(int w, int h)
|
||||||
{
|
{
|
||||||
SDL_Color col[2] = {
|
SDL_Color col[2] = {
|
||||||
{ 0x66, 0x66, 0x66, 0xff },
|
{ 0x66, 0x66, 0x66, 0xff },
|
||||||
|
|||||||
404
src/game.c
404
src/game.c
@@ -1,86 +1,406 @@
|
|||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <SDL3_image/SDL_image.h>
|
#include <SDL3_image/SDL_image.h>
|
||||||
#include <SDL3_mixer/SDL_mixer.h>
|
#include <SDL3_mixer/SDL_mixer.h>
|
||||||
|
#include <SDL3_ttf/SDL_ttf.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sdlerror.h>
|
#include <akerror.h>
|
||||||
|
#include <semver.h>
|
||||||
|
|
||||||
#include <sdl3game/game.h>
|
#include <akstdlib.h>
|
||||||
#include <sdl3game/controller.h>
|
#include <akgl/game.h>
|
||||||
#include <sdl3game/tilemap.h>
|
#include <akgl/controller.h>
|
||||||
#include <sdl3game/sprite.h>
|
#include <akgl/tilemap.h>
|
||||||
#include <sdl3game/heap.h>
|
#include <akgl/sprite.h>
|
||||||
#include <sdl3game/registry.h>
|
#include <akgl/heap.h>
|
||||||
#include <sdl3game/staticstring.h>
|
#include <akgl/registry.h>
|
||||||
#include <sdl3game/iterator.h>
|
#include <akgl/staticstring.h>
|
||||||
|
#include <akgl/iterator.h>
|
||||||
|
#include <akgl/SDL_GameControllerDB.h>
|
||||||
|
|
||||||
SDL_Window *window = NULL;
|
SDL_Window *window = NULL;
|
||||||
SDL_Renderer *renderer = NULL;
|
SDL_Renderer *renderer = NULL;
|
||||||
GAME_frame ball;
|
akgl_Frame ball;
|
||||||
GAME_frame paddle1;
|
akgl_Frame paddle1;
|
||||||
GAME_frame paddle2;
|
akgl_Frame paddle2;
|
||||||
GAME_frame table;
|
akgl_Frame table;
|
||||||
tilemap gamemap;
|
akgl_Tilemap gamemap;
|
||||||
MIX_Audio *bgm = NULL;
|
MIX_Audio *bgm = NULL;
|
||||||
MIX_Mixer *GAME_mixer = NULL;
|
MIX_Mixer *akgl_mixer = NULL;
|
||||||
MIX_Track *GAME_tracks[64];
|
MIX_Track *akgl_tracks[AKGL_GAME_AUDIO_MAX_TRACKS];
|
||||||
SDL_FRect camera;
|
SDL_FRect camera;
|
||||||
Game game;
|
akgl_Game game;
|
||||||
|
|
||||||
ErrorContext ERROR_NOIGNORE *GAME_init()
|
void akgl_game_lowfps(void)
|
||||||
{
|
{
|
||||||
|
SDL_Log("Low FPS! %d", game.fps);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_game_init()
|
||||||
|
{
|
||||||
|
int screenwidth = 0;
|
||||||
|
int screenheight = 0;
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
FAIL_ZERO_BREAK(errctx, strlen((char *)&game.name), ERR_NULLPOINTER, "Must provide game name");
|
strncpy((char *)&game.libversion, AKGL_VERSION, 32);
|
||||||
FAIL_ZERO_BREAK(errctx, strlen((char *)&game.version), ERR_NULLPOINTER, "Must provide game version");
|
game.gameStartTime = SDL_GetTicksNS();
|
||||||
FAIL_ZERO_BREAK(errctx, strlen((char *)&game.uri), ERR_NULLPOINTER, "Must provide game uri");
|
game.lastIterTime = game.gameStartTime;
|
||||||
CATCH(errctx, heap_init());
|
game.lastFPSTime = game.gameStartTime;
|
||||||
CATCH(errctx, registry_init_actor());
|
game.lowfpsfunc = &akgl_game_lowfps;
|
||||||
CATCH(errctx, registry_init_sprite());
|
FAIL_ZERO_BREAK(errctx, strlen((char *)&game.name), AKERR_NULLPOINTER, "Must provide game name");
|
||||||
CATCH(errctx, registry_init_spritesheet());
|
FAIL_ZERO_BREAK(errctx, strlen((char *)&game.version), AKERR_NULLPOINTER, "Must provide game version");
|
||||||
CATCH(errctx, registry_init_character());
|
FAIL_ZERO_BREAK(errctx, strlen((char *)&game.uri), AKERR_NULLPOINTER, "Must provide game uri");
|
||||||
CATCH(errctx, registry_init_actor_state_strings());
|
CATCH(errctx, akgl_heap_init());
|
||||||
|
CATCH(errctx, akgl_registry_init_actor());
|
||||||
|
CATCH(errctx, akgl_registry_init_sprite());
|
||||||
|
CATCH(errctx, akgl_registry_init_spritesheet());
|
||||||
|
CATCH(errctx, akgl_registry_init_character());
|
||||||
|
CATCH(errctx, akgl_registry_init_font());
|
||||||
|
CATCH(errctx, akgl_registry_init_music());
|
||||||
|
CATCH(errctx, akgl_registry_init_properties());
|
||||||
|
CATCH(errctx, akgl_registry_init_actor_state_strings());
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, true)
|
} FINISH(errctx, true)
|
||||||
|
|
||||||
SDL_SetAppMetadata(game.name, game.version, game.uri);
|
SDL_SetAppMetadata(game.name, game.version, game.uri);
|
||||||
|
|
||||||
for ( i = 0 ; i < MAX_CONTROL_MAPS; i++ ) {
|
for ( i = 0 ; i < AKGL_MAX_CONTROL_MAPS; i++ ) {
|
||||||
memset(&GAME_ControlMaps[i], 0x00, sizeof(SDL3GControlMap));
|
memset(&GAME_ControlMaps[i], 0x00, sizeof(akgl_ControlMap));
|
||||||
}
|
}
|
||||||
|
|
||||||
FAIL_ZERO_RETURN(
|
FAIL_ZERO_RETURN(
|
||||||
errctx,
|
errctx,
|
||||||
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD | SDL_INIT_AUDIO),
|
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD | SDL_INIT_AUDIO),
|
||||||
ERR_SDL,
|
AKGL_ERR_SDL,
|
||||||
"Couldn't initialize SDL: %s",
|
"Couldn't initialize SDL: %s",
|
||||||
SDL_GetError());
|
SDL_GetError());
|
||||||
|
|
||||||
|
// Load the Game Controller DB
|
||||||
|
|
||||||
|
for ( i = 0; i < AKGL_SDL_GAMECONTROLLER_DB_LEN ; i++ ) {
|
||||||
|
if ( SDL_AddGamepadMapping(SDL_GAMECONTROLLER_DB[i]) == -1 ) {
|
||||||
|
FAIL_ZERO_RETURN(errctx, 0, AKGL_ERR_SDL, "%s", SDL_GetError());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SUCCEED_RETURN(errctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_game_init_screen()
|
||||||
|
{
|
||||||
|
akgl_String *width = NULL;
|
||||||
|
akgl_String *height = NULL;
|
||||||
|
int screenwidth;
|
||||||
|
int screenheight;
|
||||||
|
|
||||||
|
PREPARE_ERROR(e);
|
||||||
|
|
||||||
|
PASS(e, akgl_get_property("game.screenwidth", &width, "0"));
|
||||||
|
PASS(e, akgl_get_property("game.screenheight", &height, "0"));
|
||||||
|
PASS(e, aksl_atoi(width->data, &screenwidth));
|
||||||
|
PASS(e, aksl_atoi(height->data, &screenheight));
|
||||||
|
SDL_Log("Initializing screen (%sx%s = %dx%d)", width->data, height->data, screenwidth, screenheight);
|
||||||
|
PASS(e, akgl_heap_release_string(width));
|
||||||
|
PASS(e, akgl_heap_release_string(height));
|
||||||
|
|
||||||
FAIL_ZERO_RETURN(
|
FAIL_ZERO_RETURN(
|
||||||
errctx,
|
e,
|
||||||
SDL_CreateWindowAndRenderer(game.uri, game.screenwidth, game.screenheight, 0, &window, &renderer),
|
SDL_CreateWindowAndRenderer(game.uri, screenwidth, screenheight, 0, &window, &renderer),
|
||||||
ERR_SDL,
|
AKGL_ERR_SDL,
|
||||||
"Couldn't create window/renderer: %s",
|
"Couldn't create window/renderer: %s",
|
||||||
SDL_GetError());
|
SDL_GetError());
|
||||||
|
|
||||||
FAIL_ZERO_RETURN(
|
FAIL_ZERO_RETURN(
|
||||||
errctx,
|
e,
|
||||||
MIX_Init(),
|
MIX_Init(),
|
||||||
ERR_SDL,
|
AKGL_ERR_SDL,
|
||||||
"Couldn't initialize audio: %s",
|
"Couldn't initialize audio: %s",
|
||||||
SDL_GetError());
|
SDL_GetError());
|
||||||
game.mixer = MIX_CreateMixerDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, 0);
|
akgl_mixer = MIX_CreateMixerDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, 0);
|
||||||
FAIL_ZERO_RETURN(
|
FAIL_ZERO_RETURN(
|
||||||
errctx,
|
e,
|
||||||
game.mixer,
|
akgl_mixer,
|
||||||
ERR_SDL,
|
AKGL_ERR_SDL,
|
||||||
"Unable to create mixer device: %s",
|
"Unable to create mixer device: %s",
|
||||||
SDL_GetError());
|
SDL_GetError());
|
||||||
|
|
||||||
|
FAIL_ZERO_RETURN(
|
||||||
|
e,
|
||||||
|
TTF_Init(),
|
||||||
|
AKGL_ERR_SDL,
|
||||||
|
"Couldn't initialize front engine: %s",
|
||||||
|
SDL_GetError());
|
||||||
|
|
||||||
camera.x = 0;
|
camera.x = 0;
|
||||||
camera.y = 0;
|
camera.y = 0;
|
||||||
camera.w = game.screenwidth;
|
camera.w = screenwidth;
|
||||||
camera.h = game.screenheight;
|
camera.h = screenheight;
|
||||||
|
SUCCEED(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
void akgl_game_updateFPS()
|
||||||
|
{
|
||||||
|
SDL_Time curTime;
|
||||||
|
curTime = SDL_GetTicksNS();
|
||||||
|
if ( (curTime - game.lastFPSTime) > AKGL_TIME_ONESEC_NS ) {
|
||||||
|
game.fps = game.framesSinceUpdate;
|
||||||
|
game.framesSinceUpdate = 0;
|
||||||
|
game.lastFPSTime = curTime;
|
||||||
|
}
|
||||||
|
if ( game.fps < 30 ) {
|
||||||
|
game.lowfpsfunc();
|
||||||
|
}
|
||||||
|
game.framesSinceUpdate += 1;
|
||||||
|
game.lastIterTime = curTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* entity name -> pointer map tables
|
||||||
|
*/
|
||||||
|
|
||||||
|
void akgl_game_save_actorname_iterator(void *userdata, SDL_PropertiesID props, const char *name)
|
||||||
|
{
|
||||||
|
FILE *fp = (FILE *)userdata;
|
||||||
|
akgl_Actor *actor = NULL;
|
||||||
|
PREPARE_ERROR(errctx);
|
||||||
|
ATTEMPT {
|
||||||
|
FAIL_ZERO_BREAK(errctx, fp, AKERR_NULLPOINTER, "NULL file pointer");
|
||||||
|
CATCH(errctx, aksl_fwrite((char *)name, 1, AKGL_ACTOR_MAX_NAME_LENGTH, fp));
|
||||||
|
actor = SDL_GetPointerProperty(props, name, NULL);
|
||||||
|
CATCH(errctx, aksl_fwrite(&actor, 1, sizeof(akgl_Actor *), fp));
|
||||||
|
} CLEANUP {
|
||||||
|
} PROCESS(errctx) {
|
||||||
|
} FINISH_NORETURN(errctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void akgl_game_save_spritename_iterator(void *userdata, SDL_PropertiesID props, const char *name)
|
||||||
|
{
|
||||||
|
FILE *fp = (FILE *)userdata;
|
||||||
|
akgl_Sprite *sprite = NULL;
|
||||||
|
PREPARE_ERROR(errctx);
|
||||||
|
ATTEMPT {
|
||||||
|
FAIL_ZERO_BREAK(errctx, fp, AKERR_NULLPOINTER, "NULL file pointer");
|
||||||
|
sprite = SDL_GetPointerProperty(props, name, NULL);
|
||||||
|
CATCH(errctx, aksl_fwrite((char *)name, 1, AKGL_SPRITE_MAX_NAME_LENGTH, fp));
|
||||||
|
CATCH(errctx, aksl_fwrite(&sprite, 1, sizeof(akgl_Sprite *), fp));
|
||||||
|
} CLEANUP {
|
||||||
|
} PROCESS(errctx) {
|
||||||
|
} FINISH_NORETURN(errctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void akgl_game_save_spritesheetname_iterator(void *userdata, SDL_PropertiesID props, const char *name)
|
||||||
|
{
|
||||||
|
FILE *fp = (FILE *)userdata;
|
||||||
|
akgl_SpriteSheet *spritesheet = NULL;
|
||||||
|
PREPARE_ERROR(errctx);
|
||||||
|
ATTEMPT {
|
||||||
|
FAIL_ZERO_BREAK(errctx, fp, AKERR_NULLPOINTER, "NULL file pointer");
|
||||||
|
spritesheet = SDL_GetPointerProperty(props, name, NULL);
|
||||||
|
CATCH(errctx, aksl_fwrite((char *)name, 1, AKGL_SPRITE_SHEET_MAX_FILENAME_LENGTH, fp));
|
||||||
|
CATCH(errctx, aksl_fwrite(&spritesheet, 1, sizeof(akgl_SpriteSheet *), fp));
|
||||||
|
} CLEANUP {
|
||||||
|
} PROCESS(errctx) {
|
||||||
|
} FINISH_NORETURN(errctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void akgl_game_save_charactername_iterator(void *userdata, SDL_PropertiesID props, const char *name)
|
||||||
|
{
|
||||||
|
FILE *fp = (FILE *)userdata;
|
||||||
|
PREPARE_ERROR(errctx);
|
||||||
|
akgl_Character *character = NULL;
|
||||||
|
ATTEMPT {
|
||||||
|
FAIL_ZERO_BREAK(errctx, fp, AKERR_NULLPOINTER, "NULL file pointer");
|
||||||
|
character = SDL_GetPointerProperty(props, name, NULL);
|
||||||
|
CATCH(errctx, aksl_fwrite((char *)name, 1, AKGL_SPRITE_MAX_CHARACTER_NAME_LENGTH, fp));
|
||||||
|
CATCH(errctx, aksl_fwrite(&character, 1, sizeof(akgl_Character *), fp));
|
||||||
|
} CLEANUP {
|
||||||
|
} PROCESS(errctx) {
|
||||||
|
} FINISH_NORETURN(errctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_game_save_actors(FILE *fp)
|
||||||
|
{
|
||||||
|
PREPARE_ERROR(errctx);
|
||||||
|
char nullval = 0x00;
|
||||||
|
|
||||||
|
ATTEMPT {
|
||||||
|
FAIL_ZERO_BREAK(errctx, fp, AKERR_NULLPOINTER, "NULL file pointer");
|
||||||
|
// write the actor name pointer table
|
||||||
|
SDL_EnumerateProperties(
|
||||||
|
AKGL_REGISTRY_ACTOR,
|
||||||
|
&akgl_game_save_actorname_iterator,
|
||||||
|
(void *)fp);
|
||||||
|
CATCH(errctx, aksl_fwrite((void *)&nullval, 1, AKGL_ACTOR_MAX_NAME_LENGTH, fp));
|
||||||
|
CATCH(errctx, aksl_fwrite((void *)&nullval, 1, sizeof(akgl_Actor *), fp));
|
||||||
|
// write the sprite name pointer table
|
||||||
|
SDL_EnumerateProperties(
|
||||||
|
AKGL_REGISTRY_SPRITE,
|
||||||
|
&akgl_game_save_spritename_iterator,
|
||||||
|
(void *)fp);
|
||||||
|
CATCH(errctx, aksl_fwrite((void *)&nullval, 1, AKGL_SPRITE_MAX_NAME_LENGTH, fp));
|
||||||
|
CATCH(errctx, aksl_fwrite((void *)&nullval, 1, sizeof(akgl_Sprite *), fp));
|
||||||
|
// write the spritesheet name pointer table
|
||||||
|
SDL_EnumerateProperties(
|
||||||
|
AKGL_REGISTRY_SPRITESHEET,
|
||||||
|
&akgl_game_save_spritesheetname_iterator,
|
||||||
|
(void *)fp);
|
||||||
|
CATCH(errctx, aksl_fwrite((void *)&nullval, 1, AKGL_SPRITE_SHEET_MAX_FILENAME_LENGTH, fp));
|
||||||
|
CATCH(errctx, aksl_fwrite((void *)&nullval, 1, sizeof(akgl_SpriteSheet *), fp));
|
||||||
|
// write the character name pointer table
|
||||||
|
SDL_EnumerateProperties(
|
||||||
|
AKGL_REGISTRY_CHARACTER,
|
||||||
|
&akgl_game_save_charactername_iterator,
|
||||||
|
(void *)fp);
|
||||||
|
CATCH(errctx, aksl_fwrite((void *)&nullval, 1, AKGL_SPRITE_MAX_CHARACTER_NAME_LENGTH, fp));
|
||||||
|
CATCH(errctx, aksl_fwrite((void *)&nullval, 1, sizeof(akgl_Character *), fp));
|
||||||
|
} CLEANUP {
|
||||||
|
} PROCESS(errctx) {
|
||||||
|
} FINISH(errctx, true);
|
||||||
|
SUCCEED_RETURN(errctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_game_save(char *fpath)
|
||||||
|
{
|
||||||
|
FILE *fp = NULL;
|
||||||
|
PREPARE_ERROR(errctx);
|
||||||
|
|
||||||
|
ATTEMPT {
|
||||||
|
FAIL_ZERO_BREAK(errctx, fpath, AKERR_NULLPOINTER, "NULL file path");
|
||||||
|
CATCH(errctx, aksl_fopen(fpath, "wb", &fp));
|
||||||
|
CATCH(errctx, aksl_fwrite(&game, 1, sizeof(akgl_Game), fp));
|
||||||
|
CATCH(errctx, akgl_game_save_actors(fp));
|
||||||
|
} PROCESS(errctx) {
|
||||||
|
} CLEANUP {
|
||||||
|
if ( fp != NULL )
|
||||||
|
fclose(fp);
|
||||||
|
} FINISH(errctx, true);
|
||||||
|
SUCCEED_RETURN(errctx); // SUCCEED_NORETURN if in main().
|
||||||
|
}
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_game_load_objectnamemap(FILE *fp, SDL_PropertiesID map, int namelength, int ptrlength, SDL_PropertiesID registry)
|
||||||
|
{
|
||||||
|
void *ptr = NULL;
|
||||||
|
char ptrstring[32];
|
||||||
|
char objname[namelength];
|
||||||
|
int retval = 0;
|
||||||
|
|
||||||
|
PREPARE_ERROR(errctx);
|
||||||
|
while ( 1 ) {
|
||||||
|
CATCH(errctx, aksl_fread((void *)&objname, 1, namelength, fp));
|
||||||
|
CATCH(errctx, aksl_fread((void *)&ptr, 1, ptrlength, fp));
|
||||||
|
// End of the map
|
||||||
|
if ( ptr == 0x00 && objname[0] == 0x00 ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// The map allows us to say "Object X has a reference to object Y at
|
||||||
|
// address Z. The object they had at address Z was named A. Our current
|
||||||
|
// instance of object named A is at address B. So we map address Z to
|
||||||
|
// address B, so that we can reconnect function pointers on objects loaded
|
||||||
|
// from the save game state."
|
||||||
|
|
||||||
|
// SDL_Properties objects can only use string keys, so we can't use the
|
||||||
|
// old pointer as a key without first converting it to a string.
|
||||||
|
CATCH(errctx, aksl_memset((void *)&ptrstring, 0x00, 32));
|
||||||
|
snprintf((char *)&ptrstring, 32, "%p", ptr);
|
||||||
|
SDL_SetPointerProperty(
|
||||||
|
map,
|
||||||
|
ptrstring,
|
||||||
|
SDL_GetPointerProperty(registry, objname, NULL));
|
||||||
|
};
|
||||||
|
SUCCEED_RETURN(errctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_game_load_versioncmp(char *versiontype, char *newversion, char *curversion)
|
||||||
|
{
|
||||||
|
semver_t current_version = {};
|
||||||
|
semver_t compare_version = {};
|
||||||
|
PREPARE_ERROR(errctx);
|
||||||
|
FAIL_ZERO_RETURN(errctx, versiontype, AKERR_NULLPOINTER, "NULL argument");
|
||||||
|
FAIL_ZERO_RETURN(errctx, curversion, AKERR_NULLPOINTER, "NULL argument");
|
||||||
|
FAIL_ZERO_RETURN(errctx, newversion, AKERR_NULLPOINTER, "NULL argument");
|
||||||
|
|
||||||
|
ATTEMPT {
|
||||||
|
// Check save game library version
|
||||||
|
FAIL_NONZERO_BREAK(
|
||||||
|
errctx,
|
||||||
|
semver_parse((const char *)curversion, ¤t_version),
|
||||||
|
AKERR_VALUE,
|
||||||
|
"Invalid semantic %s version in current game: %s",
|
||||||
|
versiontype,
|
||||||
|
(char *)curversion);
|
||||||
|
FAIL_NONZERO_BREAK(
|
||||||
|
errctx,
|
||||||
|
semver_parse((const char *)newversion, &compare_version),
|
||||||
|
AKERR_VALUE,
|
||||||
|
"Invalid semantic %s version in save game: %s",
|
||||||
|
versiontype,
|
||||||
|
(char *)&newversion);
|
||||||
|
FAIL_ZERO_BREAK(
|
||||||
|
errctx,
|
||||||
|
semver_satisfies(compare_version, current_version, "="),
|
||||||
|
AKERR_API,
|
||||||
|
"Incompatible save game %s version (%s != %s)",
|
||||||
|
versiontype,
|
||||||
|
curversion,
|
||||||
|
(char *)&newversion);
|
||||||
|
} CLEANUP {
|
||||||
|
semver_free(¤t_version);
|
||||||
|
semver_free(&compare_version);
|
||||||
|
} PROCESS(errctx) {
|
||||||
|
} FINISH(errctx, true);
|
||||||
|
SUCCEED_RETURN(errctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_game_load(char *fpath)
|
||||||
|
{
|
||||||
|
akgl_Game savegame;
|
||||||
|
SDL_PropertiesID actormap;
|
||||||
|
SDL_PropertiesID spritemap;
|
||||||
|
SDL_PropertiesID spritesheetmap;
|
||||||
|
SDL_PropertiesID charactermap;
|
||||||
|
FILE *fp = NULL;
|
||||||
|
|
||||||
|
PREPARE_ERROR(errctx);
|
||||||
|
FAIL_ZERO_RETURN(errctx, fpath, AKERR_NULLPOINTER, "NULL file path");
|
||||||
|
|
||||||
|
ATTEMPT {
|
||||||
|
CATCH(errctx, aksl_fopen(fpath, "rb", &fp));
|
||||||
|
CATCH(errctx, aksl_fread((void *)&savegame, 1, sizeof(akgl_Game), fp));
|
||||||
|
CATCH(errctx, akgl_game_load_versioncmp("library", (char *)&savegame.libversion, (char *)AKGL_VERSION));
|
||||||
|
CATCH(errctx, akgl_game_load_versioncmp("game", (char *)&savegame.version, (char *)&game.version));
|
||||||
|
FAIL_NONZERO_RETURN(
|
||||||
|
errctx,
|
||||||
|
strncmp((char *)&savegame.name, (char *)&game.name, 256),
|
||||||
|
AKERR_API,
|
||||||
|
"Savegame is not compatible with this game");
|
||||||
|
FAIL_NONZERO_RETURN(
|
||||||
|
errctx,
|
||||||
|
strncmp((char *)&savegame.uri, (char *)&game.uri, 256),
|
||||||
|
AKERR_API,
|
||||||
|
"Savegame is not compatible with this game");
|
||||||
|
|
||||||
|
memcpy((void *)&game, (void *)&savegame, sizeof(akgl_Game));
|
||||||
|
// Load actor name map
|
||||||
|
actormap = SDL_CreateProperties();
|
||||||
|
CATCH(errctx, akgl_game_load_objectnamemap(fp, actormap, AKGL_ACTOR_MAX_NAME_LENGTH, sizeof(akgl_Actor *), AKGL_REGISTRY_ACTOR));
|
||||||
|
// Load sprite name map
|
||||||
|
spritemap = SDL_CreateProperties();
|
||||||
|
CATCH(errctx, akgl_game_load_objectnamemap(fp, spritemap, AKGL_ACTOR_MAX_NAME_LENGTH, sizeof(akgl_Sprite *), AKGL_REGISTRY_SPRITE));
|
||||||
|
// Load spritesheet name map
|
||||||
|
spritesheetmap = SDL_CreateProperties();
|
||||||
|
CATCH(errctx, akgl_game_load_objectnamemap(fp, spritesheetmap, AKGL_ACTOR_MAX_NAME_LENGTH, sizeof(akgl_SpriteSheet *), AKGL_REGISTRY_SPRITESHEET));
|
||||||
|
// Load character name map
|
||||||
|
charactermap = SDL_CreateProperties();
|
||||||
|
CATCH(errctx, akgl_game_load_objectnamemap(fp, charactermap, AKGL_ACTOR_MAX_NAME_LENGTH, sizeof(akgl_Character *), AKGL_REGISTRY_CHARACTER));
|
||||||
|
// Now that we have all of our pointer maps built, we can load the actual binary objects and reset their pointers
|
||||||
|
} CLEANUP {
|
||||||
|
if ( fp != NULL ) {
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
} PROCESS(errctx) {
|
||||||
|
} FINISH(errctx, true);
|
||||||
|
|
||||||
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|||||||
132
src/heap.c
132
src/heap.c
@@ -1,191 +1,187 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sdlerror.h>
|
#include <akerror.h>
|
||||||
|
|
||||||
#include <sdl3game/game.h>
|
#include <akgl/game.h>
|
||||||
#include <sdl3game/sprite.h>
|
#include <akgl/sprite.h>
|
||||||
#include <sdl3game/heap.h>
|
#include <akgl/heap.h>
|
||||||
#include <sdl3game/registry.h>
|
#include <akgl/registry.h>
|
||||||
#include <sdl3game/staticstring.h>
|
#include <akgl/staticstring.h>
|
||||||
#include <sdl3game/iterator.h>
|
#include <akgl/iterator.h>
|
||||||
|
#include <akgl/error.h>
|
||||||
|
|
||||||
actor HEAP_ACTOR[MAX_HEAP_ACTOR];
|
akgl_Actor HEAP_ACTOR[AKGL_MAX_HEAP_ACTOR];
|
||||||
sprite HEAP_SPRITE[MAX_HEAP_SPRITE];
|
akgl_Sprite HEAP_SPRITE[AKGL_MAX_HEAP_SPRITE];
|
||||||
spritesheet HEAP_SPRITESHEET[MAX_HEAP_SPRITESHEET];
|
akgl_SpriteSheet HEAP_SPRITESHEET[AKGL_MAX_HEAP_SPRITESHEET];
|
||||||
character HEAP_CHARACTER[MAX_HEAP_CHARACTER];
|
akgl_Character HEAP_CHARACTER[AKGL_MAX_HEAP_CHARACTER];
|
||||||
string HEAP_STRING[MAX_HEAP_STRING];
|
akgl_String HEAP_STRING[AKGL_MAX_HEAP_STRING];
|
||||||
|
|
||||||
ErrorContext *heap_init()
|
akerr_ErrorContext *akgl_heap_init()
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for ( i = 0; i < MAX_HEAP_ACTOR; i++) {
|
akerr_name_for_status(AKGL_ERR_SDL, "SDL Error");
|
||||||
memset(&HEAP_ACTOR[i], 0x00, sizeof(actor));
|
for ( i = 0; i < AKGL_MAX_HEAP_ACTOR; i++) {
|
||||||
|
memset(&HEAP_ACTOR[i], 0x00, sizeof(akgl_Actor));
|
||||||
}
|
}
|
||||||
for ( i = 0; i < MAX_HEAP_SPRITE; i++) {
|
for ( i = 0; i < AKGL_MAX_HEAP_SPRITE; i++) {
|
||||||
memset(&HEAP_SPRITE[i], 0x00, sizeof(sprite));
|
memset(&HEAP_SPRITE[i], 0x00, sizeof(akgl_Sprite));
|
||||||
}
|
}
|
||||||
for ( i = 0; i < MAX_HEAP_SPRITESHEET; i++) {
|
for ( i = 0; i < AKGL_MAX_HEAP_SPRITESHEET; i++) {
|
||||||
memset(&HEAP_SPRITESHEET[i], 0x00, sizeof(spritesheet));
|
memset(&HEAP_SPRITESHEET[i], 0x00, sizeof(akgl_SpriteSheet));
|
||||||
}
|
}
|
||||||
for ( i = 0; i < MAX_HEAP_CHARACTER; i++) {
|
for ( i = 0; i < AKGL_MAX_HEAP_CHARACTER; i++) {
|
||||||
memset(&HEAP_CHARACTER[i], 0x00, sizeof(character));
|
memset(&HEAP_CHARACTER[i], 0x00, sizeof(akgl_Character));
|
||||||
}
|
}
|
||||||
for ( i = 0; i < MAX_HEAP_STRING; i++) {
|
for ( i = 0; i < AKGL_MAX_HEAP_STRING; i++) {
|
||||||
memset(&HEAP_STRING[i], 0x00, sizeof(string));
|
memset(&HEAP_STRING[i], 0x00, sizeof(akgl_String));
|
||||||
}
|
}
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *heap_next_actor(actor **dest)
|
akerr_ErrorContext *akgl_heap_next_actor(akgl_Actor **dest)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
for (int i = 0; i < MAX_HEAP_ACTOR; i++ ) {
|
for (int i = 0; i < AKGL_MAX_HEAP_ACTOR; i++ ) {
|
||||||
if ( HEAP_ACTOR[i].refcount != 0 ) {
|
if ( HEAP_ACTOR[i].refcount != 0 ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
*dest = &HEAP_ACTOR[i];
|
*dest = &HEAP_ACTOR[i];
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
FAIL_RETURN(errctx, ERR_HEAP, "Unable to find unused actor on the heap");
|
FAIL_RETURN(errctx, AKERR_HEAP, "Unable to find unused actor on the heap");
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *heap_next_sprite(sprite **dest)
|
akerr_ErrorContext *akgl_heap_next_sprite(akgl_Sprite **dest)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
for (int i = 0; i < MAX_HEAP_SPRITE; i++ ) {
|
for (int i = 0; i < AKGL_MAX_HEAP_SPRITE; i++ ) {
|
||||||
if ( HEAP_SPRITE[i].refcount != 0 ) {
|
if ( HEAP_SPRITE[i].refcount != 0 ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
*dest = &HEAP_SPRITE[i];
|
*dest = &HEAP_SPRITE[i];
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
FAIL_RETURN(errctx, ERR_HEAP, "Unable to find unused sprite on the heap");
|
FAIL_RETURN(errctx, AKERR_HEAP, "Unable to find unused sprite on the heap");
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *heap_next_spritesheet(spritesheet **dest)
|
akerr_ErrorContext *akgl_heap_next_spritesheet(akgl_SpriteSheet **dest)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
for (int i = 0; i < MAX_HEAP_SPRITESHEET; i++ ) {
|
for (int i = 0; i < AKGL_MAX_HEAP_SPRITESHEET; i++ ) {
|
||||||
if ( HEAP_SPRITESHEET[i].refcount != 0 ) {
|
if ( HEAP_SPRITESHEET[i].refcount != 0 ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
*dest = &HEAP_SPRITESHEET[i];
|
*dest = &HEAP_SPRITESHEET[i];
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
FAIL_RETURN(errctx, ERR_HEAP, "Unable to find unused spritesheet on the heap");
|
FAIL_RETURN(errctx, AKERR_HEAP, "Unable to find unused spritesheet on the heap");
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *heap_next_character(character **dest)
|
akerr_ErrorContext *akgl_heap_next_character(akgl_Character **dest)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
for (int i = 0; i < MAX_HEAP_CHARACTER; i++ ) {
|
for (int i = 0; i < AKGL_MAX_HEAP_CHARACTER; i++ ) {
|
||||||
if ( HEAP_CHARACTER[i].refcount != 0 ) {
|
if ( HEAP_CHARACTER[i].refcount != 0 ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
*dest = &HEAP_CHARACTER[i];
|
*dest = &HEAP_CHARACTER[i];
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
FAIL_RETURN(errctx, ERR_HEAP, "Unable to find unused character on the heap");
|
FAIL_RETURN(errctx, AKERR_HEAP, "Unable to find unused character on the heap");
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *heap_next_string(string **dest)
|
akerr_ErrorContext *akgl_heap_next_string(akgl_String **dest)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
for (int i = 0; i < MAX_HEAP_STRING; i++ ) {
|
for (int i = 0; i < AKGL_MAX_HEAP_STRING; i++ ) {
|
||||||
if ( HEAP_STRING[i].refcount != 0 ) {
|
if ( HEAP_STRING[i].refcount != 0 ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
*dest = &HEAP_STRING[i];
|
*dest = &HEAP_STRING[i];
|
||||||
|
HEAP_STRING[i].refcount += 1;
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
FAIL_RETURN(errctx, ERR_HEAP, "Unable to find unused string on the heap");
|
FAIL_RETURN(errctx, AKERR_HEAP, "Unable to find unused string on the heap");
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *heap_release_actor(actor *ptr)
|
akerr_ErrorContext *akgl_heap_release_actor(akgl_Actor *ptr)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, ptr, ERR_NULLPOINTER, "NULL actor reference");
|
FAIL_ZERO_RETURN(errctx, ptr, AKERR_NULLPOINTER, "NULL actor reference");
|
||||||
if ( ptr->refcount > 0 ) {
|
if ( ptr->refcount > 0 ) {
|
||||||
ptr->refcount -= 1;
|
ptr->refcount -= 1;
|
||||||
}
|
}
|
||||||
if ( ptr->refcount == 0 ) {
|
if ( ptr->refcount == 0 ) {
|
||||||
for ( i = 0; i < ACTOR_MAX_CHILDREN; i++ ) {
|
for ( i = 0; i < AKGL_ACTOR_MAX_CHILDREN; i++ ) {
|
||||||
if ( ptr->children[i] != NULL ) {
|
if ( ptr->children[i] != NULL ) {
|
||||||
CATCH_AND_RETURN(errctx, heap_release_actor(ptr->children[i]));
|
CATCH_AND_RETURN(errctx, akgl_heap_release_actor(ptr->children[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( ptr->basechar != NULL ) {
|
SDL_ClearProperty(AKGL_REGISTRY_ACTOR, (char *)&ptr->name);
|
||||||
CATCH_AND_RETURN(errctx, heap_release_character(ptr->basechar));
|
memset(ptr, 0x00, sizeof(akgl_Actor));
|
||||||
}
|
|
||||||
memset(ptr, 0x00, sizeof(actor));
|
|
||||||
SDL_ClearProperty(REGISTRY_ACTOR, (char *)&ptr->name);
|
|
||||||
}
|
}
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *heap_release_character(character *basechar)
|
akerr_ErrorContext *akgl_heap_release_character(akgl_Character *basechar)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
iterator opflags;
|
akgl_Iterator opflags;
|
||||||
FAIL_ZERO_RETURN(errctx, basechar, ERR_NULLPOINTER, "NULL character reference");
|
FAIL_ZERO_RETURN(errctx, basechar, AKERR_NULLPOINTER, "NULL character reference");
|
||||||
BITMASK_CLEAR(opflags.flags);
|
AKGL_BITMASK_CLEAR(opflags.flags);
|
||||||
BITMASK_ADD(opflags.flags, ITERATOR_OP_RELEASE);
|
|
||||||
|
|
||||||
if ( basechar->refcount > 0 ) {
|
if ( basechar->refcount > 0 ) {
|
||||||
basechar->refcount -= 1;
|
basechar->refcount -= 1;
|
||||||
}
|
}
|
||||||
if ( basechar->refcount == 0 ) {
|
if ( basechar->refcount == 0 ) {
|
||||||
SDL_EnumerateProperties(basechar->state_sprites, &character_state_sprites_iterate, (void *)&opflags);
|
SDL_ClearProperty(AKGL_REGISTRY_CHARACTER, (char *)&basechar->name);
|
||||||
SDL_ClearProperty(REGISTRY_CHARACTER, (char *)&basechar->name);
|
memset(basechar, 0x00, sizeof(akgl_Character));
|
||||||
}
|
}
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *heap_release_sprite(sprite *ptr)
|
akerr_ErrorContext *akgl_heap_release_sprite(akgl_Sprite *ptr)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, ptr, ERR_NULLPOINTER, "Received NULL sprite reference");
|
FAIL_ZERO_RETURN(errctx, ptr, AKERR_NULLPOINTER, "Received NULL sprite reference");
|
||||||
if ( ptr->refcount > 0 ) {
|
if ( ptr->refcount > 0 ) {
|
||||||
ptr->refcount -= 1;
|
ptr->refcount -= 1;
|
||||||
}
|
}
|
||||||
if ( ptr->refcount == 0 ) {
|
if ( ptr->refcount == 0 ) {
|
||||||
ATTEMPT {
|
SDL_ClearProperty(AKGL_REGISTRY_SPRITE, (char *)&ptr->name);
|
||||||
CATCH(errctx, heap_release_spritesheet(ptr->sheet));
|
memset(ptr, 0x00, sizeof(akgl_Sprite));
|
||||||
} CLEANUP {
|
|
||||||
SDL_ClearProperty(REGISTRY_SPRITE, (char *)&ptr->name);
|
|
||||||
} PROCESS(errctx) {
|
|
||||||
} FINISH(errctx, true);
|
|
||||||
}
|
}
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *heap_release_spritesheet(spritesheet *ptr)
|
akerr_ErrorContext *akgl_heap_release_spritesheet(akgl_SpriteSheet *ptr)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, ptr, ERR_NULLPOINTER, "Received NULL spritesheet reference");
|
FAIL_ZERO_RETURN(errctx, ptr, AKERR_NULLPOINTER, "Received NULL spritesheet reference");
|
||||||
if ( ptr->refcount > 0 ) {
|
if ( ptr->refcount > 0 ) {
|
||||||
ptr->refcount -= 1;
|
ptr->refcount -= 1;
|
||||||
}
|
}
|
||||||
if ( ptr->refcount == 0 ) {
|
if ( ptr->refcount == 0 ) {
|
||||||
// TODO : If we go threaded, make sure this is only happening on the main thread
|
// TODO : If we go threaded, make sure this is only happening on the main thread
|
||||||
SDL_ClearProperty(REGISTRY_SPRITESHEET, (char *)&ptr->name);
|
SDL_ClearProperty(AKGL_REGISTRY_SPRITESHEET, (char *)&ptr->name);
|
||||||
if ( ptr-> texture != NULL )
|
if ( ptr-> texture != NULL )
|
||||||
SDL_DestroyTexture(ptr->texture);
|
SDL_DestroyTexture(ptr->texture);
|
||||||
ptr->texture = NULL;
|
ptr->texture = NULL;
|
||||||
|
memset(ptr, 0x00, sizeof(akgl_SpriteSheet));
|
||||||
}
|
}
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *heap_release_string(string *ptr)
|
akerr_ErrorContext *akgl_heap_release_string(akgl_String *ptr)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, ptr, ERR_NULLPOINTER, "Received NULL string reference");
|
FAIL_ZERO_RETURN(errctx, ptr, AKERR_NULLPOINTER, "Received NULL string reference");
|
||||||
if ( ptr->refcount > 0 ) {
|
if ( ptr->refcount > 0 ) {
|
||||||
ptr->refcount -= 1;
|
ptr->refcount -= 1;
|
||||||
}
|
}
|
||||||
if ( ptr->refcount == 0 ) {
|
if ( ptr->refcount == 0 ) {
|
||||||
memset(&ptr->data, 0x00, MAX_STRING_LENGTH);
|
memset(&ptr->data, 0x00, AKGL_MAX_STRING_LENGTH);
|
||||||
}
|
}
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,131 +1,131 @@
|
|||||||
#include <jansson.h>
|
#include <jansson.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sdlerror.h>
|
#include <akerror.h>
|
||||||
|
|
||||||
#include <sdl3game/json_helpers.h>
|
#include <akgl/json_helpers.h>
|
||||||
#include <sdl3game/game.h>
|
#include <akgl/game.h>
|
||||||
#include <sdl3game/heap.h>
|
#include <akgl/heap.h>
|
||||||
#include <sdl3game/staticstring.h>
|
#include <akgl/staticstring.h>
|
||||||
#include <sdl3game/registry.h>
|
#include <akgl/registry.h>
|
||||||
|
|
||||||
ErrorContext *get_json_object_value(json_t *obj, char *key, json_t **dest)
|
akerr_ErrorContext *akgl_get_json_object_value(json_t *obj, char *key, json_t **dest)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, obj, ERR_NULLPOINTER, "NULL object pointer");
|
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL object pointer");
|
||||||
json_t *value = json_object_get(obj, key);
|
json_t *value = json_object_get(obj, key);
|
||||||
FAIL_ZERO_RETURN(errctx, value, ERR_KEY, "Key %s not found in object", key);
|
FAIL_ZERO_RETURN(errctx, value, AKERR_KEY, "Key %s not found in object", key);
|
||||||
FAIL_ZERO_RETURN(errctx, (json_is_object(value)), ERR_TYPE, "Key %s in object has incorrect type", key);
|
FAIL_ZERO_RETURN(errctx, (json_is_object(value)), AKERR_TYPE, "Key %s in object has incorrect type", key);
|
||||||
*dest = value;
|
*dest = value;
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *get_json_boolean_value(json_t *obj, char *key, bool *dest)
|
akerr_ErrorContext *akgl_get_json_boolean_value(json_t *obj, char *key, bool *dest)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, obj, ERR_NULLPOINTER, "NULL object pointer");
|
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL object pointer");
|
||||||
json_t *value = json_object_get(obj, key);
|
json_t *value = json_object_get(obj, key);
|
||||||
FAIL_ZERO_RETURN(errctx, value, ERR_KEY, "Key %s not found in object", key);
|
FAIL_ZERO_RETURN(errctx, value, AKERR_KEY, "Key %s not found in object", key);
|
||||||
FAIL_ZERO_RETURN(errctx, (json_is_boolean(value)), ERR_TYPE, "Key %s in object has incorrect type", key);
|
FAIL_ZERO_RETURN(errctx, (json_is_boolean(value)), AKERR_TYPE, "Key %s in object has incorrect type", key);
|
||||||
*dest = json_boolean_value(value);
|
*dest = json_boolean_value(value);
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *get_json_integer_value(json_t *obj, char *key, int *dest)
|
akerr_ErrorContext *akgl_get_json_integer_value(json_t *obj, char *key, int *dest)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, obj, ERR_NULLPOINTER, "NULL object pointer");
|
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL object pointer");
|
||||||
json_t *value = json_object_get(obj, key);
|
json_t *value = json_object_get(obj, key);
|
||||||
FAIL_ZERO_RETURN(errctx, value, ERR_KEY, "Key %s not found in object", key);
|
FAIL_ZERO_RETURN(errctx, value, AKERR_KEY, "Key %s not found in object", key);
|
||||||
FAIL_ZERO_RETURN(errctx, (json_is_integer(value)), ERR_TYPE, "Key %s in object has incorrect type", key);
|
FAIL_ZERO_RETURN(errctx, (json_is_integer(value)), AKERR_TYPE, "Key %s in object has incorrect type", key);
|
||||||
*dest = json_integer_value(value);
|
*dest = json_integer_value(value);
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *get_json_number_value(json_t *obj, char *key, float *dest)
|
akerr_ErrorContext *akgl_get_json_number_value(json_t *obj, char *key, float *dest)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, obj, ERR_NULLPOINTER, "NULL pointer reference");
|
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL pointer reference");
|
||||||
json_t *value = json_object_get(obj, key);
|
json_t *value = json_object_get(obj, key);
|
||||||
FAIL_ZERO_RETURN(errctx, value, ERR_KEY, "Key %s not found in object", key);
|
FAIL_ZERO_RETURN(errctx, value, AKERR_KEY, "Key %s not found in object", key);
|
||||||
FAIL_ZERO_RETURN(errctx, (json_is_number(value)), ERR_TYPE, "Key %s in object has incorrect type", key);
|
FAIL_ZERO_RETURN(errctx, (json_is_number(value)), AKERR_TYPE, "Key %s in object has incorrect type", key);
|
||||||
*dest = json_number_value(value);
|
*dest = json_number_value(value);
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *get_json_string_value(json_t *obj, char *key, string **dest)
|
akerr_ErrorContext *akgl_get_json_string_value(json_t *obj, char *key, akgl_String **dest)
|
||||||
{
|
{
|
||||||
json_t *value = NULL;
|
json_t *value = NULL;
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, obj, ERR_NULLPOINTER, "NULL pointer reference");
|
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL pointer reference");
|
||||||
FAIL_ZERO_RETURN(errctx, key, ERR_NULLPOINTER, "NULL pointer reference");
|
FAIL_ZERO_RETURN(errctx, key, AKERR_NULLPOINTER, "NULL pointer reference");
|
||||||
FAIL_ZERO_RETURN(errctx, dest, ERR_NULLPOINTER, "NULL pointer reference");
|
FAIL_ZERO_RETURN(errctx, dest, AKERR_NULLPOINTER, "NULL pointer reference");
|
||||||
|
|
||||||
value = json_object_get(obj, key);
|
value = json_object_get(obj, key);
|
||||||
FAIL_ZERO_RETURN(errctx, value, ERR_KEY, "Key %s not found in object", key);
|
FAIL_ZERO_RETURN(errctx, value, AKERR_KEY, "Key %s not found in object", key);
|
||||||
FAIL_ZERO_RETURN(errctx, (json_is_string(value)), ERR_TYPE, "Key %s in object has incorrect type", key);
|
FAIL_ZERO_RETURN(errctx, (json_is_string(value)), AKERR_TYPE, "Key %s in object has incorrect type", key);
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
if ( *dest == NULL ) {
|
if ( *dest == NULL ) {
|
||||||
CATCH(errctx, heap_next_string(dest));
|
CATCH(errctx, akgl_heap_next_string(dest));
|
||||||
CATCH(errctx, string_initialize(*dest, NULL));
|
CATCH(errctx, akgl_string_initialize(*dest, NULL));
|
||||||
}
|
}
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, false);
|
} FINISH(errctx, false);
|
||||||
|
|
||||||
strncpy((char *)&(*dest)->data, json_string_value(value), MAX_STRING_LENGTH);
|
strncpy((char *)&(*dest)->data, json_string_value(value), AKGL_MAX_STRING_LENGTH);
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *get_json_array_value(json_t *obj, char *key, json_t **dest)
|
akerr_ErrorContext *akgl_get_json_array_value(json_t *obj, char *key, json_t **dest)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, obj, ERR_NULLPOINTER, "NULL pointer reference");
|
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL pointer reference");
|
||||||
json_t *value = json_object_get(obj, key);
|
json_t *value = json_object_get(obj, key);
|
||||||
FAIL_ZERO_RETURN(errctx, value, ERR_KEY, "Key %s not found in object", key);
|
FAIL_ZERO_RETURN(errctx, value, AKERR_KEY, "Key %s not found in object", key);
|
||||||
FAIL_ZERO_RETURN(errctx, (json_is_array(value)), ERR_TYPE, "Key %s in object has incorrect type", key);
|
FAIL_ZERO_RETURN(errctx, (json_is_array(value)), AKERR_TYPE, "Key %s in object has incorrect type", key);
|
||||||
*dest = value;
|
*dest = value;
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *get_json_array_index_object(json_t *array, int index, json_t **dest)
|
akerr_ErrorContext *akgl_get_json_array_index_object(json_t *array, int index, json_t **dest)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, array, ERR_NULLPOINTER, "NULL pointer reference");
|
FAIL_ZERO_RETURN(errctx, array, AKERR_NULLPOINTER, "NULL pointer reference");
|
||||||
json_t *value = json_array_get(array, index);
|
json_t *value = json_array_get(array, index);
|
||||||
FAIL_ZERO_RETURN(errctx, value, ERR_OUTOFBOUNDS, "Index %d out of bounds for array", index);
|
FAIL_ZERO_RETURN(errctx, value, AKERR_OUTOFBOUNDS, "Index %d out of bounds for array", index);
|
||||||
FAIL_ZERO_RETURN(errctx, (json_is_object(value)), ERR_TYPE, "Index %d in object has incorrect type", index);
|
FAIL_ZERO_RETURN(errctx, (json_is_object(value)), AKERR_TYPE, "Index %d in object has incorrect type", index);
|
||||||
*dest = value;
|
*dest = value;
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *get_json_array_index_integer(json_t *array, int index, int *dest)
|
akerr_ErrorContext *akgl_get_json_array_index_integer(json_t *array, int index, int *dest)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, array, ERR_NULLPOINTER, "NULL pointer reference");
|
FAIL_ZERO_RETURN(errctx, array, AKERR_NULLPOINTER, "NULL pointer reference");
|
||||||
json_t *value = json_array_get(array, index);
|
json_t *value = json_array_get(array, index);
|
||||||
FAIL_ZERO_RETURN(errctx, value, ERR_OUTOFBOUNDS, "Index %d out of bounds for array", index);
|
FAIL_ZERO_RETURN(errctx, value, AKERR_OUTOFBOUNDS, "Index %d out of bounds for array", index);
|
||||||
FAIL_ZERO_RETURN(errctx, (json_is_integer(value)), ERR_TYPE, "Index %d in object has incorrect type", index);
|
FAIL_ZERO_RETURN(errctx, (json_is_integer(value)), AKERR_TYPE, "Index %d in object has incorrect type", index);
|
||||||
*dest = json_integer_value(value);
|
*dest = json_integer_value(value);
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *get_json_array_index_string(json_t *array, int index, string **dest)
|
akerr_ErrorContext *akgl_get_json_array_index_string(json_t *array, int index, akgl_String **dest)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, array, ERR_NULLPOINTER, "NULL pointer reference");
|
FAIL_ZERO_RETURN(errctx, array, AKERR_NULLPOINTER, "NULL pointer reference");
|
||||||
FAIL_ZERO_RETURN(errctx, dest, ERR_NULLPOINTER, "NULL destination pointer reference");
|
FAIL_ZERO_RETURN(errctx, dest, AKERR_NULLPOINTER, "NULL destination pointer reference");
|
||||||
json_t *value = json_array_get(array, index);
|
json_t *value = json_array_get(array, index);
|
||||||
FAIL_ZERO_RETURN(errctx, value, ERR_OUTOFBOUNDS, "Index %d out of bounds for array", index);
|
FAIL_ZERO_RETURN(errctx, value, AKERR_OUTOFBOUNDS, "Index %d out of bounds for array", index);
|
||||||
FAIL_ZERO_RETURN(errctx, (json_is_string(value)), ERR_TYPE, "Index %d in object has incorrect type", index);
|
FAIL_ZERO_RETURN(errctx, (json_is_string(value)), AKERR_TYPE, "Index %d in object has incorrect type", index);
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
if ( *dest == NULL ) {
|
if ( *dest == NULL ) {
|
||||||
CATCH(errctx, heap_next_string(dest));
|
CATCH(errctx, akgl_heap_next_string(dest));
|
||||||
CATCH(errctx, string_initialize(*dest, NULL));
|
CATCH(errctx, akgl_string_initialize(*dest, NULL));
|
||||||
}
|
}
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, false);
|
} FINISH(errctx, false);
|
||||||
|
|
||||||
strncpy((char *)&(*dest)->data, json_string_value(value), MAX_STRING_LENGTH);
|
strncpy((char *)&(*dest)->data, json_string_value(value), AKGL_MAX_STRING_LENGTH);
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|||||||
177
src/registry.c
177
src/registry.c
@@ -1,77 +1,184 @@
|
|||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <sdlerror.h>
|
#include <akerror.h>
|
||||||
|
#include <jansson.h>
|
||||||
|
|
||||||
#include <sdl3game/sprite.h>
|
#include <akstdlib.h>
|
||||||
#include <sdl3game/registry.h>
|
#include <akgl/heap.h>
|
||||||
#include <sdl3game/iterator.h>
|
#include <akgl/sprite.h>
|
||||||
#include <sdl3game/actor.h>
|
#include <akgl/registry.h>
|
||||||
|
#include <akgl/iterator.h>
|
||||||
|
#include <akgl/actor.h>
|
||||||
|
#include <akgl/json_helpers.h>
|
||||||
|
|
||||||
SDL_PropertiesID REGISTRY_ACTOR;
|
SDL_PropertiesID AKGL_REGISTRY_ACTOR;
|
||||||
SDL_PropertiesID REGISTRY_ACTOR_STATE_STRINGS;
|
SDL_PropertiesID AKGL_REGISTRY_ACTOR_STATE_STRINGS;
|
||||||
SDL_PropertiesID REGISTRY_SPRITE;
|
SDL_PropertiesID AKGL_REGISTRY_SPRITE;
|
||||||
SDL_PropertiesID REGISTRY_SPRITESHEET;
|
SDL_PropertiesID AKGL_REGISTRY_SPRITESHEET;
|
||||||
SDL_PropertiesID REGISTRY_CHARACTER;
|
SDL_PropertiesID AKGL_REGISTRY_CHARACTER;
|
||||||
|
SDL_PropertiesID AKGL_REGISTRY_MUSIC;
|
||||||
|
SDL_PropertiesID AKGL_REGISTRY_FONT;
|
||||||
|
SDL_PropertiesID AKGL_REGISTRY_PROPERTIES;
|
||||||
|
|
||||||
ErrorContext *registry_init()
|
akerr_ErrorContext *akgl_registry_init()
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, registry_init_spritesheet());
|
CATCH(errctx, akgl_registry_init_spritesheet());
|
||||||
CATCH(errctx, registry_init_sprite());
|
CATCH(errctx, akgl_registry_init_sprite());
|
||||||
CATCH(errctx, registry_init_character());
|
CATCH(errctx, akgl_registry_init_character());
|
||||||
CATCH(errctx, registry_init_actor());
|
CATCH(errctx, akgl_registry_init_actor());
|
||||||
CATCH(errctx, registry_init_actor_state_strings());
|
CATCH(errctx, akgl_registry_init_actor_state_strings());
|
||||||
|
CATCH(errctx, akgl_registry_init_font());
|
||||||
|
CATCH(errctx, akgl_registry_init_music());
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *registry_init_actor()
|
akerr_ErrorContext *akgl_registry_init_actor()
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
REGISTRY_ACTOR = SDL_CreateProperties();
|
AKGL_REGISTRY_ACTOR = SDL_CreateProperties();
|
||||||
FAIL_ZERO_RETURN(errctx, REGISTRY_ACTOR, ERR_NULLPOINTER, "Error initializing actor registry");
|
FAIL_ZERO_RETURN(errctx, AKGL_REGISTRY_ACTOR, AKERR_NULLPOINTER, "Error initializing actor registry");
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *registry_init_actor_state_strings()
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_registry_init_font()
|
||||||
|
{
|
||||||
|
PREPARE_ERROR(errctx);
|
||||||
|
AKGL_REGISTRY_FONT = SDL_CreateProperties();
|
||||||
|
FAIL_ZERO_RETURN(errctx, AKGL_REGISTRY_FONT, AKERR_NULLPOINTER, "Error initializing font registry");
|
||||||
|
SUCCEED_RETURN(errctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
akerr_ErrorContext *akgl_registry_init_music()
|
||||||
|
{
|
||||||
|
PREPARE_ERROR(errctx);
|
||||||
|
AKGL_REGISTRY_MUSIC = SDL_CreateProperties();
|
||||||
|
FAIL_ZERO_RETURN(errctx, AKGL_REGISTRY_MUSIC, AKERR_NULLPOINTER, "Error initializing music registry");
|
||||||
|
SUCCEED_RETURN(errctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
akerr_ErrorContext *akgl_registry_init_properties()
|
||||||
|
{
|
||||||
|
PREPARE_ERROR(errctx);
|
||||||
|
AKGL_REGISTRY_PROPERTIES = SDL_CreateProperties();
|
||||||
|
FAIL_ZERO_RETURN(errctx, AKGL_REGISTRY_PROPERTIES, AKERR_NULLPOINTER, "Error initializing properties registry");
|
||||||
|
SUCCEED_RETURN(errctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
akerr_ErrorContext *akgl_registry_init_actor_state_strings()
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int flag = 0;
|
int flag = 0;
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
REGISTRY_ACTOR_STATE_STRINGS = SDL_CreateProperties();
|
AKGL_REGISTRY_ACTOR_STATE_STRINGS = SDL_CreateProperties();
|
||||||
FAIL_ZERO_RETURN(errctx, REGISTRY_ACTOR_STATE_STRINGS, ERR_NULLPOINTER, "Error initializing actor state strings registry");
|
FAIL_ZERO_RETURN(errctx, AKGL_REGISTRY_ACTOR_STATE_STRINGS, AKERR_NULLPOINTER, "Error initializing actor state strings registry");
|
||||||
for ( i = 0 ; i < ACTOR_MAX_STATES; i++ ) {
|
for ( i = 0 ; i < AKGL_ACTOR_MAX_STATES; i++ ) {
|
||||||
flag = (1 << i);
|
flag = (1 << i);
|
||||||
SDL_SetNumberProperty(
|
SDL_SetNumberProperty(
|
||||||
REGISTRY_ACTOR_STATE_STRINGS,
|
AKGL_REGISTRY_ACTOR_STATE_STRINGS,
|
||||||
ACTOR_STATE_STRING_NAMES[i],
|
AKGL_ACTOR_STATE_STRING_NAMES[i],
|
||||||
flag);
|
flag);
|
||||||
}
|
}
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *registry_init_sprite()
|
akerr_ErrorContext *akgl_registry_init_sprite()
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
REGISTRY_SPRITE = SDL_CreateProperties();
|
AKGL_REGISTRY_SPRITE = SDL_CreateProperties();
|
||||||
FAIL_ZERO_RETURN(errctx, REGISTRY_SPRITE, ERR_NULLPOINTER, "Error initializing sprite registry");
|
FAIL_ZERO_RETURN(errctx, AKGL_REGISTRY_SPRITE, AKERR_NULLPOINTER, "Error initializing sprite registry");
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *registry_init_spritesheet()
|
akerr_ErrorContext *akgl_registry_init_spritesheet()
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
REGISTRY_SPRITESHEET = SDL_CreateProperties();
|
AKGL_REGISTRY_SPRITESHEET = SDL_CreateProperties();
|
||||||
FAIL_ZERO_RETURN(errctx, REGISTRY_SPRITESHEET, ERR_NULLPOINTER, "Error initializing spritesheet registry");
|
FAIL_ZERO_RETURN(errctx, AKGL_REGISTRY_SPRITESHEET, AKERR_NULLPOINTER, "Error initializing spritesheet registry");
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *registry_init_character()
|
akerr_ErrorContext *akgl_registry_init_character()
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
REGISTRY_CHARACTER = SDL_CreateProperties();
|
AKGL_REGISTRY_CHARACTER = SDL_CreateProperties();
|
||||||
FAIL_ZERO_RETURN(errctx, REGISTRY_CHARACTER, ERR_NULLPOINTER, "Error initializing character registry");
|
FAIL_ZERO_RETURN(errctx, AKGL_REGISTRY_CHARACTER, AKERR_NULLPOINTER, "Error initializing character registry");
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_registry_load_properties(char *fname)
|
||||||
|
{
|
||||||
|
json_t *json = NULL;
|
||||||
|
json_t *props = NULL;
|
||||||
|
const char *pkey = NULL;
|
||||||
|
json_t *pvalue = NULL;
|
||||||
|
|
||||||
|
json_error_t error;
|
||||||
|
akgl_String *tmpstr;
|
||||||
|
|
||||||
|
PREPARE_ERROR(errctx);
|
||||||
|
FAIL_ZERO_RETURN(errctx, fname, AKERR_NULLPOINTER, "null filename");
|
||||||
|
ATTEMPT {
|
||||||
|
SDL_Log("Loading from %s", fname);
|
||||||
|
json = json_load_file(fname, 0, &error);
|
||||||
|
FAIL_ZERO_BREAK(
|
||||||
|
errctx,
|
||||||
|
json,
|
||||||
|
AKERR_NULLPOINTER,
|
||||||
|
"Error while loading properties from %s on line %d: %s-",
|
||||||
|
fname,
|
||||||
|
error.line,
|
||||||
|
error.text);
|
||||||
|
CATCH(errctx, akgl_get_json_object_value(json, "properties", &props));
|
||||||
|
} CLEANUP {
|
||||||
|
} PROCESS(errctx) {
|
||||||
|
} FINISH(errctx, true);
|
||||||
|
|
||||||
|
json_object_foreach(props, pkey, pvalue) {
|
||||||
|
ATTEMPT {
|
||||||
|
CATCH(errctx, akgl_heap_next_string(&tmpstr));
|
||||||
|
CATCH(errctx, akgl_get_json_string_value(props, (char *)pkey, &tmpstr));
|
||||||
|
SDL_SetStringProperty(AKGL_REGISTRY_PROPERTIES, pkey, tmpstr->data);
|
||||||
|
SDL_Log("Set property %s = %s", pkey, tmpstr->data);
|
||||||
|
CATCH(errctx, akgl_heap_release_string(tmpstr));
|
||||||
|
} CLEANUP {
|
||||||
|
} PROCESS(errctx) {
|
||||||
|
} FINISH(errctx, true);
|
||||||
|
}
|
||||||
|
SDL_Log("Properties loaded");
|
||||||
|
SUCCEED(errctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_set_property(char *name, char *src)
|
||||||
|
{
|
||||||
|
PREPARE_ERROR(e);
|
||||||
|
FAIL_ZERO_RETURN(e, name, AKERR_NULLPOINTER, "NULL char *");
|
||||||
|
FAIL_ZERO_RETURN(e, src, AKERR_NULLPOINTER, "NULL char *");
|
||||||
|
SDL_SetStringProperty(AKGL_REGISTRY_PROPERTIES, name, src);
|
||||||
|
SUCCEED_RETURN(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_property(char *name, akgl_String **dest, char *def)
|
||||||
|
{
|
||||||
|
PREPARE_ERROR(e);
|
||||||
|
FAIL_ZERO_RETURN(e, name, AKERR_NULLPOINTER, "NULL char *");
|
||||||
|
FAIL_ZERO_RETURN(e, dest, AKERR_NULLPOINTER, "NULL akgl_String *");
|
||||||
|
ATTEMPT {
|
||||||
|
if ( *dest == NULL ) {
|
||||||
|
CATCH(e, akgl_heap_next_string(dest));
|
||||||
|
}
|
||||||
|
CATCH(e,
|
||||||
|
aksl_memcpy(
|
||||||
|
(*dest)->data,
|
||||||
|
(void *)SDL_GetStringProperty(AKGL_REGISTRY_PROPERTIES, (const char *)name, (const char *)def),
|
||||||
|
AKGL_MAX_STRING_LENGTH)
|
||||||
|
);
|
||||||
|
} CLEANUP {
|
||||||
|
} PROCESS(e) {
|
||||||
|
} FINISH(e, true);
|
||||||
|
SUCCEED_RETURN(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
170
src/sprite.c
170
src/sprite.c
@@ -2,171 +2,193 @@
|
|||||||
#include <SDL3_image/SDL_image.h>
|
#include <SDL3_image/SDL_image.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <jansson.h>
|
#include <jansson.h>
|
||||||
#include <sdlerror.h>
|
#include <akerror.h>
|
||||||
|
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <sdl3game/game.h>
|
#include <akgl/game.h>
|
||||||
#include <sdl3game/sprite.h>
|
#include <akgl/sprite.h>
|
||||||
#include <sdl3game/json_helpers.h>
|
#include <akgl/json_helpers.h>
|
||||||
#include <sdl3game/heap.h>
|
#include <akgl/heap.h>
|
||||||
#include <sdl3game/registry.h>
|
#include <akgl/registry.h>
|
||||||
#include <sdl3game/staticstring.h>
|
#include <akgl/staticstring.h>
|
||||||
#include <sdl3game/iterator.h>
|
#include <akgl/iterator.h>
|
||||||
|
|
||||||
static ErrorContext *sprite_load_json_spritesheet(json_t *json, spritesheet **sheet, char *relative_path)
|
akerr_ErrorContext *akgl_sprite_sheet_coords_for_frame(akgl_Sprite *self, SDL_FRect *srccoords, uint8_t frameid)
|
||||||
|
{
|
||||||
|
PREPARE_ERROR(e);
|
||||||
|
|
||||||
|
FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "NULL sprite");
|
||||||
|
FAIL_ZERO_RETURN(e, srccoords, AKERR_NULLPOINTER, "NULL SDL_Rect");
|
||||||
|
FAIL_ZERO_RETURN(e, self->sheet, AKERR_NULLPOINTER, "NULL spritesheet");
|
||||||
|
|
||||||
|
srccoords->x = self->width * self->frameids[frameid];
|
||||||
|
if ( srccoords->x >= self->sheet->texture->w ) {
|
||||||
|
srccoords->y = ((int)srccoords->x / self->sheet->texture->w) * self->height;
|
||||||
|
srccoords->x = ((int)srccoords->x % self->sheet->texture->w);
|
||||||
|
} else {
|
||||||
|
srccoords->y = 0;
|
||||||
|
}
|
||||||
|
srccoords->w = self->width;
|
||||||
|
srccoords->h = self->height;
|
||||||
|
|
||||||
|
SUCCEED_RETURN(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
static akerr_ErrorContext *akgl_sprite_load_json_spritesheet(json_t *json, akgl_SpriteSheet **sheet, char *relative_path)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
json_t *spritesheet_json = NULL;
|
json_t *spritesheet_json = NULL;
|
||||||
int ss_frame_width = 0;
|
int ss_frame_width = 0;
|
||||||
int ss_frame_height = 0;
|
int ss_frame_height = 0;
|
||||||
string *ss_filename = NULL;
|
akgl_String *ss_filename = NULL;
|
||||||
string *tmpstr = NULL;
|
akgl_String *tmpstr = NULL;
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, heap_next_string(&tmpstr));
|
CATCH(errctx, akgl_heap_next_string(&tmpstr));
|
||||||
CATCH(errctx, string_initialize(tmpstr, NULL));
|
CATCH(errctx, akgl_string_initialize(tmpstr, NULL));
|
||||||
CATCH(errctx, get_json_object_value((json_t *)json, "spritesheet", &spritesheet_json));
|
CATCH(errctx, akgl_get_json_object_value((json_t *)json, "spritesheet", &spritesheet_json));
|
||||||
CATCH(errctx, get_json_string_value((json_t *)spritesheet_json, "filename", &ss_filename));
|
CATCH(errctx, akgl_get_json_string_value((json_t *)spritesheet_json, "filename", &ss_filename));
|
||||||
if ( ss_filename->data[0] != '/' ) {
|
if ( ss_filename->data[0] != '/' ) {
|
||||||
SDL_snprintf((char *)&tmpstr->data, MAX_STRING_LENGTH, "%s/%s", relative_path, ss_filename->data);
|
SDL_snprintf((char *)&tmpstr->data, AKGL_MAX_STRING_LENGTH, "%s/%s", relative_path, ss_filename->data);
|
||||||
} else {
|
} else {
|
||||||
SDL_snprintf((char *)&tmpstr->data, MAX_STRING_LENGTH, "%s", ss_filename->data);
|
SDL_snprintf((char *)&tmpstr->data, AKGL_MAX_STRING_LENGTH, "%s", ss_filename->data);
|
||||||
}
|
}
|
||||||
*sheet = SDL_GetPointerProperty(
|
*sheet = SDL_GetPointerProperty(
|
||||||
REGISTRY_SPRITESHEET,
|
AKGL_REGISTRY_SPRITESHEET,
|
||||||
(char *)&tmpstr->data,
|
(char *)&tmpstr->data,
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
if ( *sheet == NULL ) {
|
if ( *sheet == NULL ) {
|
||||||
CATCH(errctx, heap_next_spritesheet(sheet));
|
CATCH(errctx, akgl_heap_next_spritesheet(sheet));
|
||||||
CATCH(errctx, get_json_integer_value((json_t *)spritesheet_json, "frame_width", &ss_frame_width));
|
CATCH(errctx, akgl_get_json_integer_value((json_t *)spritesheet_json, "frame_width", &ss_frame_width));
|
||||||
CATCH(errctx, get_json_integer_value((json_t *)spritesheet_json, "frame_height", &ss_frame_width));
|
CATCH(errctx, akgl_get_json_integer_value((json_t *)spritesheet_json, "frame_height", &ss_frame_width));
|
||||||
CATCH(errctx,
|
CATCH(errctx,
|
||||||
spritesheet_initialize(
|
akgl_spritesheet_initialize(
|
||||||
(spritesheet *)*sheet,
|
(akgl_SpriteSheet *)*sheet,
|
||||||
ss_frame_width,
|
ss_frame_width,
|
||||||
ss_frame_height,
|
ss_frame_height,
|
||||||
(char *)&tmpstr->data)
|
(char *)&tmpstr->data)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
IGNORE(heap_release_string(ss_filename));
|
IGNORE(akgl_heap_release_string(ss_filename));
|
||||||
IGNORE(heap_release_string(tmpstr));
|
IGNORE(akgl_heap_release_string(tmpstr));
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
|
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *sprite_load_json(char *filename)
|
akerr_ErrorContext *akgl_sprite_load_json(char *filename)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
json_t *json = NULL;
|
json_t *json = NULL;
|
||||||
json_t *frames = NULL;
|
json_t *frames = NULL;
|
||||||
json_error_t error;
|
json_error_t error;
|
||||||
sprite *obj = NULL;
|
akgl_Sprite *obj = NULL;
|
||||||
spritesheet *sheet = NULL;
|
akgl_SpriteSheet *sheet = NULL;
|
||||||
string *spritename = NULL;
|
akgl_String *spritename = NULL;
|
||||||
//string *tmpstr = NULL;
|
//string *tmpstr = NULL;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
FAIL_ZERO_RETURN(errctx, filename, ERR_NULLPOINTER, "Received null filename");
|
FAIL_ZERO_RETURN(errctx, filename, AKERR_NULLPOINTER, "Received null filename");
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, heap_next_sprite(&obj));
|
CATCH(errctx, akgl_heap_next_sprite(&obj));
|
||||||
//CATCH(errctx, heap_next_string(&tmpstr));
|
//CATCH(errctx, akgl_heap_next_string(&tmpstr));
|
||||||
//CATCH(errctx, string_initialize(tmpstr, NULL));
|
//CATCH(errctx, akgl_string_initialize(tmpstr, NULL));
|
||||||
CATCH(errctx, heap_next_string(&spritename));
|
CATCH(errctx, akgl_heap_next_string(&spritename));
|
||||||
CATCH(errctx, string_initialize(spritename, NULL));
|
CATCH(errctx, akgl_string_initialize(spritename, NULL));
|
||||||
|
|
||||||
//SDL_snprintf((char *)&tmpstr->data, MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), filename);
|
//SDL_snprintf((char *)&tmpstr->data, AKGL_MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), filename);
|
||||||
json = (json_t *)json_load_file(filename, 0, &error);
|
json = (json_t *)json_load_file(filename, 0, &error);
|
||||||
FAIL_ZERO_BREAK(
|
FAIL_ZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
json,
|
json,
|
||||||
ERR_NULLPOINTER,
|
AKERR_NULLPOINTER,
|
||||||
"Error while loading sprite from %s on line %d: %s", filename, error.line, error.text
|
"Error while loading sprite from %s on line %d: %s", filename, error.line, error.text
|
||||||
);
|
);
|
||||||
|
|
||||||
CATCH(errctx, sprite_load_json_spritesheet((json_t *)json, &sheet, dirname(filename)));
|
CATCH(errctx, akgl_sprite_load_json_spritesheet((json_t *)json, &sheet, dirname(filename)));
|
||||||
CATCH(errctx, get_json_string_value((json_t *)json, "name", &spritename));
|
CATCH(errctx, akgl_get_json_string_value((json_t *)json, "name", &spritename));
|
||||||
CATCH(errctx,
|
CATCH(errctx,
|
||||||
sprite_initialize(
|
akgl_sprite_initialize(
|
||||||
(sprite *)obj,
|
(akgl_Sprite *)obj,
|
||||||
spritename->data,
|
spritename->data,
|
||||||
(spritesheet *)sheet)
|
(akgl_SpriteSheet *)sheet)
|
||||||
);
|
);
|
||||||
|
|
||||||
CATCH(errctx, get_json_integer_value((json_t *)json, "width", &obj->width));
|
CATCH(errctx, akgl_get_json_integer_value((json_t *)json, "width", &obj->width));
|
||||||
CATCH(errctx, get_json_integer_value((json_t *)json, "height", &obj->height));
|
CATCH(errctx, akgl_get_json_integer_value((json_t *)json, "height", &obj->height));
|
||||||
CATCH(errctx, get_json_integer_value((json_t *)json, "speed", &obj->speed));
|
CATCH(errctx, akgl_get_json_integer_value((json_t *)json, "speed", &obj->speed));
|
||||||
CATCH(errctx, get_json_boolean_value((json_t *)json, "loop", &obj->loop));
|
obj->speed = obj->speed * AKGL_TIME_ONESEC_MS;
|
||||||
CATCH(errctx, get_json_boolean_value((json_t *)json, "loopReverse", &obj->loopReverse));
|
CATCH(errctx, akgl_get_json_boolean_value((json_t *)json, "loop", &obj->loop));
|
||||||
|
CATCH(errctx, akgl_get_json_boolean_value((json_t *)json, "loopReverse", &obj->loopReverse));
|
||||||
|
|
||||||
CATCH(errctx, get_json_array_value((json_t *)json, "frames", &frames));
|
CATCH(errctx, akgl_get_json_array_value((json_t *)json, "frames", &frames));
|
||||||
obj->frames = json_array_size((json_t *)frames);
|
obj->frames = json_array_size((json_t *)frames);
|
||||||
for ( i = 0 ; i < obj->frames; i++ ) {
|
for ( i = 0 ; i < obj->frames; i++ ) {
|
||||||
CATCH(errctx, get_json_array_index_integer((json_t *)frames, i, &obj->frameids[i]));
|
CATCH(errctx, akgl_get_json_array_index_integer((json_t *)frames, i, (uint32_t *)&obj->frameids[i]));
|
||||||
}
|
}
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
if ( errctx != NULL && errctx->status != 0 ) {
|
if ( errctx != NULL && errctx->status != 0 ) {
|
||||||
IGNORE(heap_release_sprite(obj));
|
IGNORE(akgl_heap_release_sprite(obj));
|
||||||
IGNORE(heap_release_spritesheet(sheet));
|
IGNORE(akgl_heap_release_spritesheet(sheet));
|
||||||
}
|
}
|
||||||
IGNORE(heap_release_string(spritename));
|
IGNORE(akgl_heap_release_string(spritename));
|
||||||
//IGNORE(heap_release_string(tmpstr));
|
//IGNORE(akgl_heap_release_string(tmpstr));
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *sprite_initialize(sprite *spr, char *name, spritesheet *sheet)
|
akerr_ErrorContext *akgl_sprite_initialize(akgl_Sprite *spr, char *name, akgl_SpriteSheet *sheet)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, spr, ERR_NULLPOINTER, "Null sprite reference");
|
FAIL_ZERO_RETURN(errctx, spr, AKERR_NULLPOINTER, "Null sprite reference");
|
||||||
FAIL_ZERO_RETURN(errctx, name, ERR_NULLPOINTER, "Empty sprite name");
|
FAIL_ZERO_RETURN(errctx, name, AKERR_NULLPOINTER, "Empty sprite name");
|
||||||
FAIL_ZERO_RETURN(errctx, sheet, ERR_NULLPOINTER, "Null spritesheet reference");
|
FAIL_ZERO_RETURN(errctx, sheet, AKERR_NULLPOINTER, "Null spritesheet reference");
|
||||||
|
|
||||||
memset(spr, 0x00, sizeof(sprite));
|
memset(spr, 0x00, sizeof(akgl_Sprite));
|
||||||
memcpy(spr->name, name, SPRITE_MAX_NAME_LENGTH);
|
memcpy(spr->name, name, AKGL_SPRITE_MAX_NAME_LENGTH);
|
||||||
spr->sheet = sheet;
|
spr->sheet = sheet;
|
||||||
FAIL_ZERO_RETURN(
|
FAIL_ZERO_RETURN(
|
||||||
errctx,
|
errctx,
|
||||||
SDL_SetPointerProperty(REGISTRY_SPRITE, (char *)&spr->name, (void *)spr),
|
SDL_SetPointerProperty(AKGL_REGISTRY_SPRITE, (char *)&spr->name, (void *)spr),
|
||||||
ERR_KEY,
|
AKERR_KEY,
|
||||||
"Unable to add sprite to registry");
|
"Unable to add sprite to registry");
|
||||||
spr->refcount += 1;
|
spr->refcount += 1;
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *spritesheet_initialize(spritesheet *sheet, int sprite_w, int sprite_h, char *filename)
|
akerr_ErrorContext *akgl_spritesheet_initialize(akgl_SpriteSheet *sheet, int sprite_w, int sprite_h, char *filename)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
//string *tmpstr = NULL;
|
//akgl_String *tmpstr = NULL;
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
FAIL_ZERO_BREAK(errctx, sheet, ERR_NULLPOINTER, "Null spritesheet pointer");
|
FAIL_ZERO_BREAK(errctx, sheet, AKERR_NULLPOINTER, "Null spritesheet pointer");
|
||||||
FAIL_ZERO_BREAK(errctx, filename, ERR_NULLPOINTER, "Null filename pointer");
|
FAIL_ZERO_BREAK(errctx, filename, AKERR_NULLPOINTER, "Null filename pointer");
|
||||||
|
|
||||||
memset(sheet, 0x00, sizeof(spritesheet));
|
memset(sheet, 0x00, sizeof(akgl_SpriteSheet));
|
||||||
|
|
||||||
//CATCH(errctx, heap_next_string(&tmpstr));
|
//CATCH(errctx, akgl_heap_next_string(&tmpstr));
|
||||||
|
|
||||||
//CATCH(errctx, string_initialize(tmpstr, NULL));
|
//CATCH(errctx, akgl_string_initialize(tmpstr, NULL));
|
||||||
strncpy((char *)&sheet->name, filename, SPRITE_SHEET_MAX_FILENAME_LENGTH);
|
strncpy((char *)&sheet->name, filename, AKGL_SPRITE_SHEET_MAX_FILENAME_LENGTH);
|
||||||
|
|
||||||
//snprintf((char *)&tmpstr->data, MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), filename);
|
//snprintf((char *)&tmpstr->data, AKGL_MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), filename);
|
||||||
sheet->texture = IMG_LoadTexture(renderer, filename);
|
sheet->texture = IMG_LoadTexture(renderer, filename);
|
||||||
FAIL_ZERO_BREAK(errctx, sheet->texture, ERR_SDL, "Failed loading asset %s : %s", filename, SDL_GetError());
|
FAIL_ZERO_BREAK(errctx, sheet->texture, AKGL_ERR_SDL, "Failed loading asset %s : %s", filename, SDL_GetError());
|
||||||
|
|
||||||
FAIL_ZERO_BREAK(
|
FAIL_ZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
SDL_SetPointerProperty(REGISTRY_SPRITESHEET, (char *)sheet->name, (void *)sheet),
|
SDL_SetPointerProperty(AKGL_REGISTRY_SPRITESHEET, (char *)sheet->name, (void *)sheet),
|
||||||
ERR_KEY,
|
AKERR_KEY,
|
||||||
"Unable to add spritesheet to registry: %s",
|
"Unable to add spritesheet to registry: %s",
|
||||||
SDL_GetError());
|
SDL_GetError());
|
||||||
sheet->refcount += 1;
|
sheet->refcount += 1;
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
//IGNORE(heap_release_string(tmpstr));
|
//IGNORE(akgl_heap_release_string(tmpstr));
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
#include <sdlerror.h>
|
#include <akerror.h>
|
||||||
#include <sdl3game/staticstring.h>
|
#include <akgl/staticstring.h>
|
||||||
|
|
||||||
ErrorContext *string_initialize(string *obj, char *init)
|
akerr_ErrorContext *akgl_string_initialize(akgl_String *obj, char *init)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, obj, ERR_NULLPOINTER, "Attempted to initialize NULL string reference");
|
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "Attempted to initialize NULL string reference");
|
||||||
if ( init != NULL ) {
|
if ( init != NULL ) {
|
||||||
strncpy((char *)&obj->data, init, MAX_STRING_LENGTH);
|
strncpy((char *)&obj->data, init, AKGL_MAX_STRING_LENGTH);
|
||||||
} else {
|
} else {
|
||||||
memset(&obj->data, 0x00, sizeof(string));
|
memset(&obj->data, 0x00, sizeof(akgl_String));
|
||||||
}
|
}
|
||||||
obj->refcount = 1;
|
obj->refcount = 1;
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
|
|||||||
61
src/text.c
Normal file
61
src/text.c
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
#include <akerror.h>
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
#include <SDL3_ttf/SDL_ttf.h>
|
||||||
|
#include <akgl/text.h>
|
||||||
|
#include <akgl/registry.h>
|
||||||
|
#include <akgl/game.h>
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_text_loadfont(char *name, char *filepath, int size)
|
||||||
|
{
|
||||||
|
TTF_Font *font = NULL;
|
||||||
|
|
||||||
|
PREPARE_ERROR(errctx);
|
||||||
|
FAIL_ZERO_RETURN(errctx, name, AKERR_NULLPOINTER, "Null font name");
|
||||||
|
FAIL_ZERO_RETURN(errctx, name, AKERR_NULLPOINTER, "Null filepath");
|
||||||
|
font = TTF_OpenFont(filepath, size);
|
||||||
|
FAIL_ZERO_RETURN(errctx, font, AKGL_ERR_SDL, "%s", SDL_GetError());
|
||||||
|
FAIL_ZERO_RETURN(
|
||||||
|
errctx,
|
||||||
|
SDL_SetPointerProperty(AKGL_REGISTRY_FONT, name, (void *)font),
|
||||||
|
AKERR_KEY,
|
||||||
|
"Unable to add font %p to registry as %s : %s",
|
||||||
|
(void *)font,
|
||||||
|
name,
|
||||||
|
SDL_GetError());
|
||||||
|
SUCCEED_RETURN(errctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_text_rendertextat(TTF_Font *font, char *text, SDL_Color color, int wraplength, int x, int y)
|
||||||
|
{
|
||||||
|
SDL_Surface *textsurf = NULL;
|
||||||
|
SDL_Texture *texture = NULL;
|
||||||
|
SDL_FRect dest;
|
||||||
|
|
||||||
|
PREPARE_ERROR(errctx);
|
||||||
|
FAIL_ZERO_RETURN(errctx, font, AKERR_NULLPOINTER, "NULL font");
|
||||||
|
FAIL_ZERO_RETURN(errctx, text, AKERR_NULLPOINTER, "NULL text string");
|
||||||
|
if ( wraplength > 0 ) {
|
||||||
|
textsurf = TTF_RenderText_Blended_Wrapped(
|
||||||
|
font,
|
||||||
|
text,
|
||||||
|
0,
|
||||||
|
color,
|
||||||
|
wraplength);
|
||||||
|
} else {
|
||||||
|
textsurf = TTF_RenderText_Blended(
|
||||||
|
font,
|
||||||
|
text,
|
||||||
|
0,
|
||||||
|
color);
|
||||||
|
}
|
||||||
|
FAIL_ZERO_RETURN(errctx, textsurf, AKERR_NULLPOINTER, "%s", SDL_GetError());
|
||||||
|
texture = SDL_CreateTextureFromSurface(renderer, textsurf);
|
||||||
|
FAIL_ZERO_RETURN(errctx, texture, AKERR_NULLPOINTER, "%s", SDL_GetError());
|
||||||
|
dest.x = x;
|
||||||
|
dest.y = y;
|
||||||
|
SDL_GetTextureSize(texture, &dest.w, &dest.h);
|
||||||
|
FAIL_ZERO_RETURN(errctx, SDL_RenderTexture(renderer, texture, NULL, &dest), AKERR_NULLPOINTER, "%s", SDL_GetError());
|
||||||
|
SDL_DestroyTexture(texture);
|
||||||
|
SDL_DestroySurface(textsurf);
|
||||||
|
SUCCEED_RETURN(errctx);
|
||||||
|
}
|
||||||
420
src/tilemap.c
420
src/tilemap.c
@@ -3,64 +3,64 @@
|
|||||||
#include <SDL3_mixer/SDL_mixer.h>
|
#include <SDL3_mixer/SDL_mixer.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <jansson.h>
|
#include <jansson.h>
|
||||||
#include <sdlerror.h>
|
#include <akerror.h>
|
||||||
|
|
||||||
#include <sdl3game/tilemap.h>
|
#include <akgl/tilemap.h>
|
||||||
#include <sdl3game/actor.h>
|
#include <akgl/actor.h>
|
||||||
#include <sdl3game/json_helpers.h>
|
#include <akgl/json_helpers.h>
|
||||||
#include <sdl3game/heap.h>
|
#include <akgl/heap.h>
|
||||||
#include <sdl3game/registry.h>
|
#include <akgl/registry.h>
|
||||||
#include <sdl3game/staticstring.h>
|
#include <akgl/staticstring.h>
|
||||||
#include <sdl3game/game.h>
|
#include <akgl/game.h>
|
||||||
|
|
||||||
ErrorContext *get_json_tilemap_property(json_t *obj, char *key, char *type, json_t **dest)
|
akerr_ErrorContext *akgl_get_json_tilemap_property(json_t *obj, char *key, char *type, json_t **dest)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
json_t *properties = NULL;
|
json_t *properties = NULL;
|
||||||
json_t *property = NULL;
|
json_t *property = NULL;
|
||||||
string *tmpstr = NULL;
|
akgl_String *tmpstr = NULL;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
// This is not a generic JSON helper. It assumes we are receiving an object with a 'properties' key
|
// 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.
|
// inside of it. That key is an array of objects, and each object has a name, type, and value.
|
||||||
FAIL_ZERO_RETURN(errctx, obj, ERR_NULLPOINTER, "NULL json obj reference");
|
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL json obj reference");
|
||||||
FAIL_ZERO_RETURN(errctx, key, ERR_NULLPOINTER, "NULL key string");
|
FAIL_ZERO_RETURN(errctx, key, AKERR_NULLPOINTER, "NULL key string");
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, get_json_array_value(obj, "properties", &properties));
|
CATCH(errctx, akgl_get_json_array_value(obj, "properties", &properties));
|
||||||
for (i = 0; i < json_array_size(properties); i++) {
|
for (i = 0; i < json_array_size(properties); i++) {
|
||||||
CATCH(errctx, get_json_array_index_object(properties, i, &property));
|
CATCH(errctx, akgl_get_json_array_index_object(properties, i, &property));
|
||||||
CATCH(errctx, get_json_string_value(property, "name", &tmpstr));
|
CATCH(errctx, akgl_get_json_string_value(property, "name", &tmpstr));
|
||||||
if ( strcmp(tmpstr->data, key) != 0 ) {
|
if ( strcmp(tmpstr->data, key) != 0 ) {
|
||||||
CATCH(errctx, heap_release_string(tmpstr));
|
CATCH(errctx, akgl_heap_release_string(tmpstr));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
CATCH(errctx, get_json_string_value(property, "type", &tmpstr));
|
CATCH(errctx, akgl_get_json_string_value(property, "type", &tmpstr));
|
||||||
if ( strcmp(tmpstr->data, type) != 0 ) {
|
if ( strcmp(tmpstr->data, type) != 0 ) {
|
||||||
FAIL_BREAK(errctx, ERR_TYPE, "Character property is present but is incorrect type");
|
FAIL_BREAK(errctx, AKERR_TYPE, "Object property is present but is incorrect type");
|
||||||
}
|
}
|
||||||
*dest = property;
|
*dest = property;
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
if ( tmpstr != NULL ) {
|
if ( tmpstr != NULL ) {
|
||||||
IGNORE(heap_release_string(tmpstr));
|
IGNORE(akgl_heap_release_string(tmpstr));
|
||||||
}
|
}
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
|
|
||||||
FAIL_RETURN(errctx, ERR_KEY, "Property not found in properties map");
|
FAIL_RETURN(errctx, AKERR_KEY, "Property not found in properties map");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ErrorContext *get_json_properties_string(json_t *obj, char *key, string **dest)
|
akerr_ErrorContext *akgl_get_json_properties_string(json_t *obj, char *key, akgl_String **dest)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
json_t *property;
|
json_t *property;
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, get_json_tilemap_property(obj, key, "string", &property));
|
CATCH(errctx, akgl_get_json_tilemap_property(obj, key, "string", &property));
|
||||||
CATCH(errctx, heap_next_string(dest));
|
CATCH(errctx, akgl_heap_next_string(dest));
|
||||||
CATCH(errctx, string_initialize(*dest, NULL));
|
CATCH(errctx, akgl_string_initialize(*dest, NULL));
|
||||||
CATCH(errctx, get_json_string_value(property, "value", dest));
|
CATCH(errctx, akgl_get_json_string_value(property, "value", dest));
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
@@ -68,13 +68,13 @@ ErrorContext *get_json_properties_string(json_t *obj, char *key, string **dest)
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *get_json_properties_integer(json_t *obj, char *key, int *dest)
|
akerr_ErrorContext *akgl_get_json_properties_integer(json_t *obj, char *key, int *dest)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
json_t *property = NULL;
|
json_t *property = NULL;
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, get_json_tilemap_property(obj, key, "int", &property));
|
CATCH(errctx, akgl_get_json_tilemap_property(obj, key, "int", &property));
|
||||||
CATCH(errctx, get_json_integer_value(property, "value", dest));
|
CATCH(errctx, akgl_get_json_integer_value(property, "value", dest));
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
@@ -82,38 +82,52 @@ ErrorContext *get_json_properties_integer(json_t *obj, char *key, int *dest)
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *tilemap_load_tilesets_each(json_t *tileset, tilemap *dest, int tsidx)
|
akerr_ErrorContext *akgl_get_json_properties_number(json_t *obj, char *key, float *dest)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
string *tmpstr = NULL;
|
json_t *property = NULL;
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, get_json_integer_value((json_t *)tileset, "columns", &dest->tilesets[tsidx].columns));
|
CATCH(errctx, akgl_get_json_tilemap_property(obj, key, "number", &property));
|
||||||
CATCH(errctx, get_json_integer_value((json_t *)tileset, "firstgid", &dest->tilesets[tsidx].firstgid));
|
CATCH(errctx, akgl_get_json_number_value(property, "value", dest));
|
||||||
CATCH(errctx, get_json_integer_value((json_t *)tileset, "imageheight", &dest->tilesets[tsidx].imageheight));
|
} CLEANUP {
|
||||||
CATCH(errctx, get_json_integer_value((json_t *)tileset, "imagewidth", &dest->tilesets[tsidx].imagewidth));
|
} PROCESS(errctx) {
|
||||||
CATCH(errctx, get_json_integer_value((json_t *)tileset, "margin", &dest->tilesets[tsidx].margin));
|
} FINISH(errctx, true);
|
||||||
CATCH(errctx, get_json_integer_value((json_t *)tileset, "spacing", &dest->tilesets[tsidx].spacing));
|
|
||||||
CATCH(errctx, get_json_integer_value((json_t *)tileset, "tilecount", &dest->tilesets[tsidx].tilecount));
|
|
||||||
CATCH(errctx, get_json_integer_value((json_t *)tileset, "tileheight", &dest->tilesets[tsidx].tileheight));
|
|
||||||
CATCH(errctx, get_json_integer_value((json_t *)tileset, "tilewidth", &dest->tilesets[tsidx].tilewidth));
|
|
||||||
|
|
||||||
CATCH(errctx, get_json_string_value((json_t *)tileset, "name", &tmpstr));
|
SUCCEED_RETURN(errctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
akerr_ErrorContext *akgl_tilemap_load_tilesets_each(json_t *tileset, akgl_Tilemap *dest, int tsidx)
|
||||||
|
{
|
||||||
|
PREPARE_ERROR(errctx);
|
||||||
|
akgl_String *tmpstr = NULL;
|
||||||
|
ATTEMPT {
|
||||||
|
CATCH(errctx, akgl_get_json_integer_value((json_t *)tileset, "columns", &dest->tilesets[tsidx].columns));
|
||||||
|
CATCH(errctx, akgl_get_json_integer_value((json_t *)tileset, "firstgid", &dest->tilesets[tsidx].firstgid));
|
||||||
|
CATCH(errctx, akgl_get_json_integer_value((json_t *)tileset, "imageheight", &dest->tilesets[tsidx].imageheight));
|
||||||
|
CATCH(errctx, akgl_get_json_integer_value((json_t *)tileset, "imagewidth", &dest->tilesets[tsidx].imagewidth));
|
||||||
|
CATCH(errctx, akgl_get_json_integer_value((json_t *)tileset, "margin", &dest->tilesets[tsidx].margin));
|
||||||
|
CATCH(errctx, akgl_get_json_integer_value((json_t *)tileset, "spacing", &dest->tilesets[tsidx].spacing));
|
||||||
|
CATCH(errctx, akgl_get_json_integer_value((json_t *)tileset, "tilecount", &dest->tilesets[tsidx].tilecount));
|
||||||
|
CATCH(errctx, akgl_get_json_integer_value((json_t *)tileset, "tileheight", &dest->tilesets[tsidx].tileheight));
|
||||||
|
CATCH(errctx, akgl_get_json_integer_value((json_t *)tileset, "tilewidth", &dest->tilesets[tsidx].tilewidth));
|
||||||
|
|
||||||
|
CATCH(errctx, akgl_get_json_string_value((json_t *)tileset, "name", &tmpstr));
|
||||||
strncpy((char *)&dest->tilesets[tsidx].name,
|
strncpy((char *)&dest->tilesets[tsidx].name,
|
||||||
(char *)&tmpstr->data,
|
(char *)&tmpstr->data,
|
||||||
TILEMAP_MAX_TILESET_NAME_SIZE
|
AKGL_TILEMAP_MAX_TILESET_NAME_SIZE
|
||||||
);
|
);
|
||||||
|
|
||||||
CATCH(errctx, get_json_string_value((json_t *)tileset, "image", &tmpstr));
|
CATCH(errctx, akgl_get_json_string_value((json_t *)tileset, "image", &tmpstr));
|
||||||
|
|
||||||
snprintf((char *)&dest->tilesets[tsidx].imagefilename,
|
snprintf((char *)&dest->tilesets[tsidx].imagefilename,
|
||||||
TILEMAP_MAX_TILESET_FILENAME_SIZE,
|
AKGL_TILEMAP_MAX_TILESET_FILENAME_SIZE,
|
||||||
"%s%s",
|
"%s%s",
|
||||||
SDL_GetBasePath(),
|
SDL_GetBasePath(),
|
||||||
tmpstr->data
|
tmpstr->data
|
||||||
);
|
);
|
||||||
|
|
||||||
dest->tilesets[tsidx].texture = IMG_LoadTexture(renderer, (char *)&dest->tilesets[tsidx].imagefilename);
|
dest->tilesets[tsidx].texture = IMG_LoadTexture(renderer, (char *)&dest->tilesets[tsidx].imagefilename);
|
||||||
FAIL_ZERO_BREAK(errctx, dest->tilesets[tsidx].texture, ERR_NULLPOINTER, "Failed loading tileset image");
|
FAIL_ZERO_BREAK(errctx, dest->tilesets[tsidx].texture, AKERR_NULLPOINTER, "Failed loading tileset image : %s", SDL_GetError());
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
@@ -121,7 +135,7 @@ ErrorContext *tilemap_load_tilesets_each(json_t *tileset, tilemap *dest, int tsi
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *tilemap_compute_tileset_offsets(tilemap *dest, int tilesetidx)
|
akerr_ErrorContext *akgl_tilemap_compute_tileset_offsets(akgl_Tilemap *dest, int tilesetidx)
|
||||||
{
|
{
|
||||||
int x_offset = 0;
|
int x_offset = 0;
|
||||||
int y_offset = 0;
|
int y_offset = 0;
|
||||||
@@ -176,11 +190,11 @@ ErrorContext *tilemap_compute_tileset_offsets(tilemap *dest, int tilesetidx)
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *tilemap_load_tilesets(tilemap *dest, json_t *root)
|
akerr_ErrorContext *akgl_tilemap_load_tilesets(akgl_Tilemap *dest, json_t *root)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, dest, ERR_NULLPOINTER, "Received NULL tilemap pointer");
|
FAIL_ZERO_RETURN(errctx, dest, AKERR_NULLPOINTER, "Received NULL tilemap pointer");
|
||||||
FAIL_ZERO_RETURN(errctx, root, ERR_NULLPOINTER, "Received NULL json object pointer");
|
FAIL_ZERO_RETURN(errctx, root, AKERR_NULLPOINTER, "Received NULL json object pointer");
|
||||||
|
|
||||||
json_t *tilesets = NULL;
|
json_t *tilesets = NULL;
|
||||||
json_t *jstileset = NULL;
|
json_t *jstileset = NULL;
|
||||||
@@ -188,11 +202,11 @@ ErrorContext *tilemap_load_tilesets(tilemap *dest, json_t *root)
|
|||||||
|
|
||||||
dest->numtilesets = 0;
|
dest->numtilesets = 0;
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, get_json_array_value(root, "tilesets", &tilesets))
|
CATCH(errctx, akgl_get_json_array_value(root, "tilesets", &tilesets))
|
||||||
for (i = 0; i < json_array_size((json_t *)tilesets); i++) {
|
for (i = 0; i < json_array_size((json_t *)tilesets); i++) {
|
||||||
CATCH(errctx, get_json_array_index_object((json_t *)tilesets, i, &jstileset));
|
CATCH(errctx, akgl_get_json_array_index_object((json_t *)tilesets, i, &jstileset));
|
||||||
CATCH(errctx, tilemap_load_tilesets_each(jstileset, dest, i));
|
CATCH(errctx, akgl_tilemap_load_tilesets_each(jstileset, dest, i));
|
||||||
CATCH(errctx, tilemap_compute_tileset_offsets(dest, i));
|
CATCH(errctx, akgl_tilemap_compute_tileset_offsets(dest, i));
|
||||||
dest->numtilesets += 1;
|
dest->numtilesets += 1;
|
||||||
}
|
}
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
@@ -202,37 +216,37 @@ ErrorContext *tilemap_load_tilesets(tilemap *dest, json_t *root)
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *tilemap_load_layer_object_actor(tilemap_object *curobj, json_t *layerdatavalue, int layerid)
|
akerr_ErrorContext *akgl_tilemap_load_layer_object_actor(akgl_TilemapObject *curobj, json_t *layerdatavalue, int layerid)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
string *tmpstr = NULL;
|
akgl_String *tmpstr = NULL;
|
||||||
actor *actorobj = NULL;
|
akgl_Actor *actorobj = NULL;
|
||||||
|
|
||||||
curobj->type = TILEMAP_OBJECT_TYPE_ACTOR;
|
curobj->type = AKGL_TILEMAP_OBJECT_TYPE_ACTOR;
|
||||||
if ( strlen((char *)&curobj->name) == 0 ) {
|
if ( strlen((char *)&curobj->name) == 0 ) {
|
||||||
FAIL_RETURN(errctx, ERR_KEY, "Actor in tile object layer cannot have empty name");
|
FAIL_RETURN(errctx, AKERR_KEY, "Actor in tile object layer cannot have empty name");
|
||||||
}
|
}
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, heap_next_string(&tmpstr));
|
CATCH(errctx, akgl_heap_next_string(&tmpstr));
|
||||||
actorobj = SDL_GetPointerProperty(REGISTRY_ACTOR, (char *)&curobj->name, NULL);
|
actorobj = SDL_GetPointerProperty(AKGL_REGISTRY_ACTOR, (char *)&curobj->name, NULL);
|
||||||
if ( actorobj == NULL ) {
|
if ( actorobj == NULL ) {
|
||||||
CATCH(errctx, heap_next_actor(&actorobj));
|
CATCH(errctx, akgl_heap_next_actor(&actorobj));
|
||||||
CATCH(errctx, actor_initialize((actor *)actorobj, (char *)&curobj->name));
|
CATCH(errctx, akgl_actor_initialize((akgl_Actor *)actorobj, (char *)&curobj->name));
|
||||||
CATCH(errctx, get_json_properties_string((json_t *)layerdatavalue, "character", &tmpstr));
|
CATCH(errctx, akgl_get_json_properties_string((json_t *)layerdatavalue, "character", &tmpstr));
|
||||||
CATCH(errctx,
|
CATCH(errctx,
|
||||||
actor_set_character(
|
akgl_actor_set_character(
|
||||||
(actor *)actorobj,
|
(akgl_Actor *)actorobj,
|
||||||
(char *)&tmpstr->data
|
(char *)&tmpstr->data
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
actorobj->refcount += 1;
|
actorobj->refcount += 1;
|
||||||
}
|
}
|
||||||
CATCH(errctx, get_json_properties_integer((json_t *)layerdatavalue, "state", &actorobj->state));
|
CATCH(errctx, akgl_get_json_properties_integer((json_t *)layerdatavalue, "state", &actorobj->state));
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
if ( tmpstr != NULL ) {
|
if ( tmpstr != NULL ) {
|
||||||
IGNORE(heap_release_string(tmpstr));
|
IGNORE(akgl_heap_release_string(tmpstr));
|
||||||
}
|
}
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
@@ -241,43 +255,55 @@ ErrorContext *tilemap_load_layer_object_actor(tilemap_object *curobj, json_t *la
|
|||||||
actorobj->x = curobj->x;
|
actorobj->x = curobj->x;
|
||||||
actorobj->y = curobj->y;
|
actorobj->y = curobj->y;
|
||||||
actorobj->visible = curobj->visible;
|
actorobj->visible = curobj->visible;
|
||||||
curobj->actorptr = (actor *)actorobj;
|
curobj->actorptr = (akgl_Actor *)actorobj;
|
||||||
|
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *tilemap_load_layer_objects(tilemap *dest, json_t *root, int layerid)
|
akerr_ErrorContext *akgl_tilemap_load_layer_objects(akgl_Tilemap *dest, json_t *root, int layerid)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
json_t *layerdata = NULL;
|
json_t *layerdata = NULL;
|
||||||
json_t *layerdatavalue = NULL;
|
json_t *layerdatavalue = NULL;
|
||||||
int j;
|
int j;
|
||||||
int len;
|
int len;
|
||||||
tilemap_layer *curlayer = NULL;
|
akgl_TilemapLayer *curlayer = NULL;
|
||||||
tilemap_object *curobj = NULL;
|
akgl_TilemapObject *curobj = NULL;
|
||||||
string *tmpstr = NULL;
|
akgl_String *tmpstr = NULL;
|
||||||
|
|
||||||
FAIL_ZERO_RETURN(errctx, dest, ERR_NULLPOINTER, "NULL destination tilemap reference");
|
FAIL_ZERO_RETURN(errctx, dest, AKERR_NULLPOINTER, "NULL destination tilemap reference");
|
||||||
FAIL_ZERO_RETURN(errctx, root, ERR_NULLPOINTER, "NULL tilemap root reference");
|
FAIL_ZERO_RETURN(errctx, root, AKERR_NULLPOINTER, "NULL tilemap root reference");
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, get_json_array_value(root, "objects", &layerdata));
|
CATCH(errctx, akgl_get_json_array_value(root, "objects", &layerdata));
|
||||||
len = json_array_size((json_t *)layerdata);
|
len = json_array_size((json_t *)layerdata);
|
||||||
curlayer = &dest->layers[layerid];
|
curlayer = &dest->layers[layerid];
|
||||||
for ( j = 0; j < len; j++ ) {
|
for ( j = 0; j < len; j++ ) {
|
||||||
CATCH(errctx, get_json_array_index_object((json_t *)layerdata, j, &layerdatavalue));
|
CATCH(errctx, akgl_get_json_array_index_object((json_t *)layerdata, j, &layerdatavalue));
|
||||||
curobj = &curlayer->objects[j];
|
curobj = &curlayer->objects[j];
|
||||||
CATCH(errctx, get_json_string_value((json_t *)layerdatavalue, "name", &tmpstr));
|
CATCH(errctx, akgl_get_json_string_value((json_t *)layerdatavalue, "name", &tmpstr));
|
||||||
strncpy((char *)curobj->name, tmpstr->data, ACTOR_MAX_NAME_LENGTH);
|
strncpy((char *)curobj->name, tmpstr->data, AKGL_ACTOR_MAX_NAME_LENGTH);
|
||||||
CATCH(errctx, heap_release_string(tmpstr));
|
CATCH(errctx, akgl_heap_release_string(tmpstr));
|
||||||
CATCH(errctx, get_json_number_value((json_t *)layerdatavalue, "x", &curobj->x));
|
CATCH(errctx, akgl_get_json_number_value((json_t *)layerdatavalue, "x", &curobj->x));
|
||||||
CATCH(errctx, get_json_number_value((json_t *)layerdatavalue, "y", &curobj->y));
|
CATCH(errctx, akgl_get_json_number_value((json_t *)layerdatavalue, "y", &curobj->y));
|
||||||
CATCH(errctx, get_json_boolean_value((json_t *)layerdatavalue, "visible", &curobj->visible));
|
CATCH(errctx, akgl_get_json_boolean_value((json_t *)layerdatavalue, "visible", &curobj->visible));
|
||||||
|
|
||||||
CATCH(errctx, get_json_string_value((json_t *)layerdatavalue, "type", &tmpstr));
|
CATCH(errctx, akgl_get_json_string_value((json_t *)layerdatavalue, "type", &tmpstr));
|
||||||
if ( strcmp(tmpstr->data, "actor") == 0 ) {
|
if ( strcmp(tmpstr->data, "actor") == 0 ) {
|
||||||
CATCH(errctx, tilemap_load_layer_object_actor(curobj, layerdatavalue, layerid));
|
CATCH(errctx, akgl_tilemap_load_layer_object_actor(curobj, layerdatavalue, layerid));
|
||||||
|
} else if ( strcmp(tmpstr->data, "perspective") == 0 ) {
|
||||||
|
curobj->visible = false;
|
||||||
|
if ( strcmp((char *)curobj->name, "p_foreground") == 0 ) {
|
||||||
|
dest->p_foreground_y = curobj->y;
|
||||||
|
CATCH(errctx, akgl_get_json_integer_value((json_t *)layerdatavalue, "height", &dest->p_foreground_h));
|
||||||
|
CATCH(errctx, akgl_get_json_properties_number((json_t *)layerdatavalue, "scale", &dest->p_foreground_scale));
|
||||||
|
} else if ( strcmp((char *)curobj->name, "p_vanishing") == 0 ) {
|
||||||
|
dest->p_vanishing_y = curobj->y;
|
||||||
|
CATCH(errctx, akgl_get_json_integer_value((json_t *)layerdatavalue, "height", &dest->p_vanishing_h));
|
||||||
|
CATCH(errctx, akgl_get_json_properties_number((json_t *)layerdatavalue, "scale", &dest->p_vanishing_scale));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
layerdatavalue = NULL;
|
layerdatavalue = NULL;
|
||||||
}
|
}
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
@@ -287,26 +313,26 @@ ErrorContext *tilemap_load_layer_objects(tilemap *dest, json_t *root, int layeri
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *tilemap_load_layer_tile(tilemap *dest, json_t *root, int layerid)
|
akerr_ErrorContext *akgl_tilemap_load_layer_tile(akgl_Tilemap *dest, json_t *root, int layerid)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
json_t *layerdata = NULL;
|
json_t *layerdata = NULL;
|
||||||
int j;
|
int j;
|
||||||
int layerdatalen;
|
int layerdatalen;
|
||||||
|
|
||||||
FAIL_ZERO_RETURN(errctx, dest, ERR_NULLPOINTER, "NULL destination tilemap reference");
|
FAIL_ZERO_RETURN(errctx, dest, AKERR_NULLPOINTER, "NULL destination tilemap reference");
|
||||||
FAIL_ZERO_RETURN(errctx, root, ERR_NULLPOINTER, "NULL tilemap root reference");
|
FAIL_ZERO_RETURN(errctx, root, AKERR_NULLPOINTER, "NULL tilemap root reference");
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, get_json_integer_value(root, "height", &dest->layers[layerid].height));
|
CATCH(errctx, akgl_get_json_integer_value(root, "height", &dest->layers[layerid].height));
|
||||||
CATCH(errctx, get_json_integer_value(root, "width", &dest->layers[layerid].width));
|
CATCH(errctx, akgl_get_json_integer_value(root, "width", &dest->layers[layerid].width));
|
||||||
CATCH(errctx, get_json_array_value(root, "data", &layerdata));
|
CATCH(errctx, akgl_get_json_array_value(root, "data", &layerdata));
|
||||||
layerdatalen = (dest->layers[layerid].width * dest->layers[layerid].height);
|
layerdatalen = (dest->layers[layerid].width * dest->layers[layerid].height);
|
||||||
if ( layerdatalen >= (TILEMAP_MAX_WIDTH * TILEMAP_MAX_HEIGHT) ) {
|
if ( layerdatalen >= (AKGL_TILEMAP_MAX_WIDTH * AKGL_TILEMAP_MAX_HEIGHT) ) {
|
||||||
FAIL_BREAK(errctx, ERR_OUTOFBOUNDS, "Map layer exceeds the maximum size");
|
FAIL_BREAK(errctx, AKERR_OUTOFBOUNDS, "Map layer exceeds the maximum size");
|
||||||
}
|
}
|
||||||
for ( j = 0; j < layerdatalen; j++ ) {
|
for ( j = 0; j < layerdatalen; j++ ) {
|
||||||
CATCH(errctx, get_json_array_index_integer(layerdata, j, &dest->layers[layerid].data[j]));
|
CATCH(errctx, akgl_get_json_array_index_integer(layerdata, j, &dest->layers[layerid].data[j]));
|
||||||
}
|
}
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
@@ -315,47 +341,81 @@ ErrorContext *tilemap_load_layer_tile(tilemap *dest, json_t *root, int layerid)
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *tilemap_load_layers(tilemap *dest, json_t *root)
|
akerr_ErrorContext *akgl_tilemap_load_layer_image(akgl_Tilemap *dest, json_t *root, int layerid)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, dest, ERR_NULLPOINTER, "tilemap_load_layers received NULL tilemap pointer");
|
akgl_String *tmpstr;
|
||||||
FAIL_ZERO_RETURN(errctx, root, ERR_NULLPOINTER, "tilemap_load_layers received NULL json object pointer");
|
akgl_String *fpath;
|
||||||
json_t *layers = NULL;
|
|
||||||
json_t *layer = NULL;
|
FAIL_ZERO_RETURN(errctx, dest, AKERR_NULLPOINTER, "NULL destination tilemap reference");
|
||||||
string *tmpstr = NULL;
|
FAIL_ZERO_RETURN(errctx, root, AKERR_NULLPOINTER, "NULL tilemap root reference");
|
||||||
int i;
|
|
||||||
int tmpint;
|
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, get_json_array_value(root, "layers", &layers));
|
CATCH(errctx, akgl_heap_next_string(&tmpstr));
|
||||||
|
CATCH(errctx, akgl_heap_next_string(&fpath));
|
||||||
|
CATCH(errctx, akgl_get_json_string_value(root, "image", &tmpstr));
|
||||||
|
|
||||||
|
snprintf((char *)&fpath->data,
|
||||||
|
AKGL_TILEMAP_MAX_TILESET_FILENAME_SIZE,
|
||||||
|
"%s%s",
|
||||||
|
SDL_GetBasePath(),
|
||||||
|
tmpstr->data
|
||||||
|
);
|
||||||
|
|
||||||
|
dest->layers[layerid].texture = IMG_LoadTexture(renderer, (char *)fpath->data);
|
||||||
|
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);
|
||||||
|
|
||||||
|
SUCCEED_RETURN(errctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
akerr_ErrorContext *akgl_tilemap_load_layers(akgl_Tilemap *dest, json_t *root)
|
||||||
|
{
|
||||||
|
PREPARE_ERROR(errctx);
|
||||||
|
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");
|
||||||
|
json_t *layers = NULL;
|
||||||
|
json_t *layer = NULL;
|
||||||
|
akgl_String *tmpstr = NULL;
|
||||||
|
int i;
|
||||||
|
int layerid = 0;
|
||||||
|
int tmpint = 0;
|
||||||
|
|
||||||
|
ATTEMPT {
|
||||||
|
CATCH(errctx, akgl_get_json_array_value(root, "layers", &layers));
|
||||||
dest->numlayers = json_array_size((json_t *)layers);
|
dest->numlayers = json_array_size((json_t *)layers);
|
||||||
for ( i = 0; i < dest->numlayers; i++) {
|
for ( i = 0; i < dest->numlayers; i++) {
|
||||||
if ( i >= TILEMAP_MAX_LAYERS ) {
|
if ( i >= AKGL_TILEMAP_MAX_LAYERS ) {
|
||||||
FAIL_BREAK(errctx, ERR_OUTOFBOUNDS, "Map exceeds the maximum number of layers");
|
FAIL_BREAK(errctx, AKERR_OUTOFBOUNDS, "Map exceeds the maximum number of layers");
|
||||||
}
|
|
||||||
CATCH(errctx, get_json_array_index_object((json_t *)layers, i, &layer));
|
|
||||||
CATCH(errctx, get_json_integer_value((json_t *)layer, "id", &tmpint));
|
|
||||||
if ( (tmpint - 1) != i ) {
|
|
||||||
// TileD's map layer IDs start at 1, not 0, and are sequential but not necessarily contiguous. We may have a gap in IDs.
|
|
||||||
layer = NULL;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
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));
|
||||||
|
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));
|
||||||
|
|
||||||
CATCH(errctx, get_json_number_value((json_t *)layer, "opacity", &dest->layers[i].opacity));
|
CATCH(errctx, akgl_get_json_string_value((json_t *)layer, "type", &tmpstr));
|
||||||
CATCH(errctx, get_json_boolean_value((json_t *)layer, "visible", &dest->layers[i].visible));
|
SDL_Log("Layer %d has type %s", layerid, tmpstr->data);
|
||||||
CATCH(errctx, get_json_integer_value((json_t *)layer, "id", &dest->layers[i].id));
|
|
||||||
CATCH(errctx, get_json_integer_value((json_t *)layer, "x", &dest->layers[i].x));
|
|
||||||
CATCH(errctx, get_json_integer_value((json_t *)layer, "y", &dest->layers[i].y));
|
|
||||||
|
|
||||||
CATCH(errctx, get_json_string_value((json_t *)layer, "type", &tmpstr));
|
|
||||||
if ( strncmp((char *)tmpstr->data, "objectgroup", strlen((char *)tmpstr->data)) == 0 ) {
|
if ( strncmp((char *)tmpstr->data, "objectgroup", strlen((char *)tmpstr->data)) == 0 ) {
|
||||||
dest->layers[i].type = TILEMAP_LAYER_TYPE_OBJECTS;
|
dest->layers[layerid].type = AKGL_TILEMAP_LAYER_TYPE_OBJECTS;
|
||||||
CATCH(errctx, tilemap_load_layer_objects((tilemap *)dest, (json_t *)layer, i));
|
CATCH(errctx, akgl_tilemap_load_layer_objects((akgl_Tilemap *)dest, (json_t *)layer, layerid));
|
||||||
} else if ( strncmp((char *)tmpstr->data, "tilelayer", strlen((char *)tmpstr->data)) == 0 ) {
|
} else if ( strncmp((char *)tmpstr->data, "tilelayer", strlen((char *)tmpstr->data)) == 0 ) {
|
||||||
dest->layers[i].type = TILEMAP_LAYER_TYPE_TILES;
|
dest->layers[layerid].type = AKGL_TILEMAP_LAYER_TYPE_TILES;
|
||||||
CATCH(errctx, tilemap_load_layer_tile((tilemap *)dest, (json_t *)layer, i));
|
CATCH(errctx, akgl_tilemap_load_layer_tile((akgl_Tilemap *)dest, (json_t *)layer, layerid));
|
||||||
|
} else if ( strncmp((char *)tmpstr->data, "imagelayer", strlen((char *)tmpstr->data)) == 0 ) {
|
||||||
|
dest->layers[layerid].type = AKGL_TILEMAP_LAYER_TYPE_IMAGE;
|
||||||
|
CATCH(errctx, akgl_tilemap_load_layer_image((akgl_Tilemap *)dest, (json_t *)layer, layerid));
|
||||||
}
|
}
|
||||||
layer = NULL;
|
layer = NULL;
|
||||||
|
layerid += 1;
|
||||||
}
|
}
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
@@ -363,53 +423,68 @@ ErrorContext *tilemap_load_layers(tilemap *dest, json_t *root)
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *tilemap_load(char *fname, tilemap *dest)
|
akerr_ErrorContext *akgl_tilemap_load(char *fname, akgl_Tilemap *dest)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
json_t *json = NULL;
|
json_t *json = NULL;
|
||||||
string *tmpstr = NULL;
|
//akgl_String *tmpstr = NULL;
|
||||||
json_error_t error;
|
json_error_t error;
|
||||||
|
|
||||||
FAIL_ZERO_RETURN(errctx, fname, ERR_NULLPOINTER, "load_tilemap received null filename");
|
FAIL_ZERO_RETURN(errctx, fname, AKERR_NULLPOINTER, "load_tilemap received null filename");
|
||||||
FAIL_ZERO_RETURN(errctx, dest, ERR_NULLPOINTER, "load_tilemap received null tilemap");
|
FAIL_ZERO_RETURN(errctx, dest, AKERR_NULLPOINTER, "load_tilemap received null tilemap");
|
||||||
|
|
||||||
memset(dest, 0x00, sizeof(tilemap));
|
|
||||||
|
|
||||||
|
memset(dest, 0x00, sizeof(akgl_Tilemap));
|
||||||
|
dest->p_foreground_scale = 1.0;
|
||||||
|
dest->p_vanishing_scale = 1.0;
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, heap_next_string(&tmpstr));
|
//CATCH(errctx, akgl_heap_next_string(&tmpstr));
|
||||||
CATCH(errctx, string_initialize(tmpstr, NULL));
|
//CATCH(errctx, akgl_string_initialize(tmpstr, NULL));
|
||||||
SDL_snprintf(tmpstr->data, MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), fname);
|
//SDL_snprintf(tmpstr->data, AKGL_MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), fname);
|
||||||
json = json_load_file(tmpstr->data, 0, &error);
|
json = json_load_file(fname, 0, &error);
|
||||||
FAIL_ZERO_BREAK(
|
FAIL_ZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
json,
|
json,
|
||||||
ERR_NULLPOINTER,
|
AKERR_NULLPOINTER,
|
||||||
"Error while loading tilemap from %s on line %d: %s-",
|
"Error while loading tilemap from %s on line %d: %s-",
|
||||||
tmpstr->data,
|
fname,
|
||||||
error.line,
|
error.line,
|
||||||
error.text
|
error.text
|
||||||
);
|
);
|
||||||
CATCH(errctx, get_json_integer_value((json_t *)json, "tileheight", &dest->tileheight));
|
CATCH(errctx, akgl_get_json_integer_value((json_t *)json, "tileheight", &dest->tileheight));
|
||||||
CATCH(errctx, get_json_integer_value((json_t *)json, "tilewidth", &dest->tilewidth));
|
CATCH(errctx, akgl_get_json_integer_value((json_t *)json, "tilewidth", &dest->tilewidth));
|
||||||
CATCH(errctx, get_json_integer_value((json_t *)json, "height", &dest->height));
|
CATCH(errctx, akgl_get_json_integer_value((json_t *)json, "height", &dest->height));
|
||||||
CATCH(errctx, get_json_integer_value((json_t *)json, "width", &dest->width));
|
CATCH(errctx, akgl_get_json_integer_value((json_t *)json, "width", &dest->width));
|
||||||
|
|
||||||
dest->orientation = 0;
|
dest->orientation = 0;
|
||||||
if ( (dest->width * dest->height) >= (TILEMAP_MAX_WIDTH * TILEMAP_MAX_HEIGHT) ) {
|
if ( (dest->width * dest->height) >= (AKGL_TILEMAP_MAX_WIDTH * AKGL_TILEMAP_MAX_HEIGHT) ) {
|
||||||
FAIL_RETURN(errctx, ERR_OUTOFBOUNDS, "Map exceeds the maximum size");
|
FAIL_RETURN(errctx, AKERR_OUTOFBOUNDS, "Map exceeds the maximum size");
|
||||||
}
|
}
|
||||||
|
|
||||||
CATCH(errctx, tilemap_load_layers((tilemap *)dest, (json_t *)json));
|
CATCH(errctx, akgl_tilemap_load_layers((akgl_Tilemap *)dest, (json_t *)json));
|
||||||
CATCH(errctx, tilemap_load_tilesets((tilemap *)dest, (json_t *)json));
|
CATCH(errctx, akgl_tilemap_load_tilesets((akgl_Tilemap *)dest, (json_t *)json));
|
||||||
|
|
||||||
|
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
|
||||||
|
/* 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
|
||||||
|
// 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
|
||||||
|
// 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));
|
||||||
|
SDL_Log("Map perspective rate is %f", dest->p_rate);
|
||||||
|
}
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
IGNORE(heap_release_string(tmpstr));
|
//IGNORE(akgl_heap_release_string(tmpstr));
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *tilemap_draw(SDL_Renderer *renderer, tilemap *map, SDL_FRect *viewport, int layeridx)
|
akerr_ErrorContext *akgl_tilemap_draw(SDL_Renderer *renderer, akgl_Tilemap *map, SDL_FRect *viewport, int layeridx)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
SDL_FRect dest = {.x = 0, .y = 0, .w = 0, .h = 0};;
|
SDL_FRect dest = {.x = 0, .y = 0, .w = 0, .h = 0};;
|
||||||
@@ -439,8 +514,8 @@ ErrorContext *tilemap_draw(SDL_Renderer *renderer, tilemap *map, SDL_FRect *view
|
|||||||
* 0 and 8 would not be rendered. 1, 9, 6, and E would be partially rendered at their corner.
|
* 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.
|
* 2,3,4,5 and A,B,C,D would be partially rendered with a slice from their center.
|
||||||
*/
|
*/
|
||||||
FAIL_ZERO_RETURN(errctx, map, ERR_NULLPOINTER, "tilemap_draw received NULL pointer to tilemap");
|
FAIL_ZERO_RETURN(errctx, map, AKERR_NULLPOINTER, "akgl_tilemap_draw received NULL pointer to tilemap");
|
||||||
FAIL_ZERO_RETURN(errctx, viewport, ERR_NULLPOINTER, "tilemap_draw received NULL pointer to viewport");
|
FAIL_ZERO_RETURN(errctx, viewport, AKERR_NULLPOINTER, "akgl_tilemap_draw received NULL pointer to viewport");
|
||||||
|
|
||||||
/* Only try to render the stuff that is partially within the viewport */
|
/* Only try to render the stuff that is partially within the viewport */
|
||||||
|
|
||||||
@@ -458,6 +533,17 @@ ErrorContext *tilemap_draw(SDL_Renderer *renderer, tilemap *map, SDL_FRect *view
|
|||||||
/*SDL_Log("Rendering map into viewport from (%d, %d) to (%d, %d)",
|
/*SDL_Log("Rendering map into viewport from (%d, %d) to (%d, %d)",
|
||||||
start_x, start_y, end_x, end_y);*/
|
start_x, start_y, end_x, end_y);*/
|
||||||
|
|
||||||
|
if ( map->layers[layeridx].type == AKGL_TILEMAP_LAYER_TYPE_IMAGE ) {
|
||||||
|
dest.x = 0;
|
||||||
|
dest.y = 0;
|
||||||
|
src.w = map->layers[layeridx].width;
|
||||||
|
src.h = map->layers[layeridx].height;
|
||||||
|
dest.w = map->layers[layeridx].width;
|
||||||
|
dest.h = map->layers[layeridx].height;
|
||||||
|
SDL_RenderTexture(renderer, map->layers[layeridx].texture, &src, &dest);
|
||||||
|
SUCCEED_RETURN(errctx);
|
||||||
|
}
|
||||||
|
|
||||||
dest.x = 0;
|
dest.x = 0;
|
||||||
dest.y = 0;
|
dest.y = 0;
|
||||||
dest.w = map->tilewidth;
|
dest.w = map->tilewidth;
|
||||||
@@ -519,7 +605,7 @@ ErrorContext *tilemap_draw(SDL_Renderer *renderer, tilemap *map, SDL_FRect *view
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *tilemap_draw_tileset(SDL_Renderer *renderer, tilemap *map, int tilesetidx)
|
akerr_ErrorContext *akgl_tilemap_draw_tileset(SDL_Renderer *renderer, akgl_Tilemap *map, int tilesetidx)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
SDL_FRect dest;
|
SDL_FRect dest;
|
||||||
@@ -531,8 +617,8 @@ ErrorContext *tilemap_draw_tileset(SDL_Renderer *renderer, tilemap *map, int til
|
|||||||
* by proving that we can reconstruct the original tileset image)
|
* by proving that we can reconstruct the original tileset image)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
FAIL_ZERO_RETURN(errctx, map, ERR_NULLPOINTER, "tilemap_draw_tileset received NULL pointer to tilemap");
|
FAIL_ZERO_RETURN(errctx, map, AKERR_NULLPOINTER, "akgl_tilemap_draw_tileset received NULL pointer to tilemap");
|
||||||
FAIL_NONZERO_RETURN(errctx, (tilesetidx >= map->numtilesets), ERR_OUTOFBOUNDS, "tilemap_draw_tileset received a tileset index out of bounds");
|
FAIL_NONZERO_RETURN(errctx, (tilesetidx >= map->numtilesets), AKERR_OUTOFBOUNDS, "akgl_tilemap_draw_tileset received a tileset index out of bounds");
|
||||||
|
|
||||||
for ( tilenum = 0; tilenum < map->tilesets[tilesetidx].tilecount; tilenum++) {
|
for ( tilenum = 0; tilenum < map->tilesets[tilesetidx].tilecount; tilenum++) {
|
||||||
// Render this tile to the correct screen position
|
// Render this tile to the correct screen position
|
||||||
@@ -568,3 +654,41 @@ ErrorContext *tilemap_draw_tileset(SDL_Renderer *renderer, tilemap *map, int til
|
|||||||
}
|
}
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 ) {
|
||||||
|
actor->scale = map->p_vanishing_scale;
|
||||||
|
} else if ( actor->y >= map->p_foreground_y ) {
|
||||||
|
actor->scale = map->p_foreground_scale;
|
||||||
|
} else {
|
||||||
|
actor->scale = map->p_foreground_scale - (map->p_rate * (map->p_foreground_y - actor->y));
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|||||||
86
src/util.c
86
src/util.c
@@ -3,18 +3,18 @@
|
|||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <SDL3_image/SDL_image.h>
|
#include <SDL3_image/SDL_image.h>
|
||||||
#include <sdlerror.h>
|
#include <akerror.h>
|
||||||
|
|
||||||
#include <sdl3game/util.h>
|
#include <akgl/util.h>
|
||||||
#include <sdl3game/heap.h>
|
#include <akgl/heap.h>
|
||||||
#include <sdl3game/registry.h>
|
#include <akgl/registry.h>
|
||||||
#include <sdl3game/game.h>
|
#include <akgl/game.h>
|
||||||
|
|
||||||
ErrorContext *rectangle_points(RectanglePoints *dest, SDL_FRect *rect)
|
akerr_ErrorContext *akgl_rectangle_points(RectanglePoints *dest, SDL_FRect *rect)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, dest, ERR_NULLPOINTER, "NULL RectanglePoints reference");
|
FAIL_ZERO_RETURN(errctx, dest, AKERR_NULLPOINTER, "NULL RectanglePoints reference");
|
||||||
FAIL_ZERO_RETURN(errctx, rect, ERR_NULLPOINTER, "NULL Rectangle reference");
|
FAIL_ZERO_RETURN(errctx, rect, AKERR_NULLPOINTER, "NULL Rectangle reference");
|
||||||
dest->topleft.x = rect->x;
|
dest->topleft.x = rect->x;
|
||||||
dest->topleft.y = rect->y;
|
dest->topleft.y = rect->y;
|
||||||
dest->bottomleft.x = rect->x;
|
dest->bottomleft.x = rect->x;
|
||||||
@@ -26,12 +26,12 @@ ErrorContext *rectangle_points(RectanglePoints *dest, SDL_FRect *rect)
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *collide_point_rectangle(point *p, RectanglePoints *rp, bool *collide)
|
akerr_ErrorContext *akgl_collide_point_rectangle(point *p, RectanglePoints *rp, bool *collide)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, p, ERR_NULLPOINTER, "NULL Point reference");
|
FAIL_ZERO_RETURN(errctx, p, AKERR_NULLPOINTER, "NULL Point reference");
|
||||||
FAIL_ZERO_RETURN(errctx, rp, ERR_NULLPOINTER, "NULL RectanglePoints reference");
|
FAIL_ZERO_RETURN(errctx, rp, AKERR_NULLPOINTER, "NULL RectanglePoints reference");
|
||||||
FAIL_ZERO_RETURN(errctx, collide, ERR_NULLPOINTER, "NULL boolean reference");
|
FAIL_ZERO_RETURN(errctx, collide, AKERR_NULLPOINTER, "NULL boolean reference");
|
||||||
if ( (p->x >= rp->topleft.x) && (p->y >= rp->topleft.y) &&
|
if ( (p->x >= rp->topleft.x) && (p->y >= rp->topleft.y) &&
|
||||||
(p->x <= rp->bottomright.x) && (p->y <= rp->bottomright.y) ) {
|
(p->x <= rp->bottomright.x) && (p->y <= rp->bottomright.y) ) {
|
||||||
*collide = true;
|
*collide = true;
|
||||||
@@ -41,49 +41,49 @@ ErrorContext *collide_point_rectangle(point *p, RectanglePoints *rp, bool *colli
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *collide_rectangles(SDL_FRect *r1, SDL_FRect *r2, bool *collide)
|
akerr_ErrorContext *akgl_collide_rectangles(SDL_FRect *r1, SDL_FRect *r2, bool *collide)
|
||||||
{
|
{
|
||||||
RectanglePoints r1p;
|
RectanglePoints r1p;
|
||||||
RectanglePoints r2p;
|
RectanglePoints r2p;
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, r1, ERR_NULLPOINTER, "NULL rectangle reference");
|
FAIL_ZERO_RETURN(errctx, r1, AKERR_NULLPOINTER, "NULL rectangle reference");
|
||||||
FAIL_ZERO_RETURN(errctx, r2, ERR_NULLPOINTER, "NULL rectangle reference");
|
FAIL_ZERO_RETURN(errctx, r2, AKERR_NULLPOINTER, "NULL rectangle reference");
|
||||||
FAIL_ZERO_RETURN(errctx, collide, ERR_NULLPOINTER, "NULL collision flag reference");
|
FAIL_ZERO_RETURN(errctx, collide, AKERR_NULLPOINTER, "NULL collision flag reference");
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, rectangle_points(&r1p, r1));
|
CATCH(errctx, akgl_rectangle_points(&r1p, r1));
|
||||||
CATCH(errctx, rectangle_points(&r2p, r2));
|
CATCH(errctx, akgl_rectangle_points(&r2p, r2));
|
||||||
|
|
||||||
// is the upper left corner of r1 contacting r2?
|
// is the upper left corner of r1 contacting r2?
|
||||||
CATCH(errctx, collide_point_rectangle(&r1p.topleft, &r2p, collide));
|
CATCH(errctx, akgl_collide_point_rectangle(&r1p.topleft, &r2p, collide));
|
||||||
if ( *collide == true ) { SUCCEED_RETURN(errctx); }
|
if ( *collide == true ) { SUCCEED_RETURN(errctx); }
|
||||||
|
|
||||||
// is the upper left corner of r2 contacting r1?
|
// is the upper left corner of r2 contacting r1?
|
||||||
CATCH(errctx, collide_point_rectangle(&r2p.topleft, &r1p, collide));
|
CATCH(errctx, akgl_collide_point_rectangle(&r2p.topleft, &r1p, collide));
|
||||||
if ( *collide == true ) { SUCCEED_RETURN(errctx); }
|
if ( *collide == true ) { SUCCEED_RETURN(errctx); }
|
||||||
|
|
||||||
// is the top right corner of r1 contacting r2?
|
// is the top right corner of r1 contacting r2?
|
||||||
CATCH(errctx, collide_point_rectangle(&r1p.topright, &r2p, collide));
|
CATCH(errctx, akgl_collide_point_rectangle(&r1p.topright, &r2p, collide));
|
||||||
if ( *collide == true ) { SUCCEED_RETURN(errctx); }
|
if ( *collide == true ) { SUCCEED_RETURN(errctx); }
|
||||||
|
|
||||||
// is the top right corner of r2 contacting r1?
|
// is the top right corner of r2 contacting r1?
|
||||||
CATCH(errctx, collide_point_rectangle(&r2p.topright, &r1p, collide));
|
CATCH(errctx, akgl_collide_point_rectangle(&r2p.topright, &r1p, collide));
|
||||||
if ( *collide == true ) { SUCCEED_RETURN(errctx); }
|
if ( *collide == true ) { SUCCEED_RETURN(errctx); }
|
||||||
|
|
||||||
// is the bottom left corner of r1 contacting r2?
|
// is the bottom left corner of r1 contacting r2?
|
||||||
CATCH(errctx, collide_point_rectangle(&r1p.bottomleft, &r2p, collide));
|
CATCH(errctx, akgl_collide_point_rectangle(&r1p.bottomleft, &r2p, collide));
|
||||||
if ( *collide == true ) { SUCCEED_RETURN(errctx); }
|
if ( *collide == true ) { SUCCEED_RETURN(errctx); }
|
||||||
|
|
||||||
// is the bottom left corner of r2 contacting r1?
|
// is the bottom left corner of r2 contacting r1?
|
||||||
CATCH(errctx, collide_point_rectangle(&r2p.bottomleft, &r1p, collide));
|
CATCH(errctx, akgl_collide_point_rectangle(&r2p.bottomleft, &r1p, collide));
|
||||||
if ( *collide == true ) { SUCCEED_RETURN(errctx); }
|
if ( *collide == true ) { SUCCEED_RETURN(errctx); }
|
||||||
|
|
||||||
// is the bottom right corner of r1 contacting r2?
|
// is the bottom right corner of r1 contacting r2?
|
||||||
CATCH(errctx, collide_point_rectangle(&r1p.bottomright, &r2p, collide));
|
CATCH(errctx, akgl_collide_point_rectangle(&r1p.bottomright, &r2p, collide));
|
||||||
if ( *collide == true ) { SUCCEED_RETURN(errctx); }
|
if ( *collide == true ) { SUCCEED_RETURN(errctx); }
|
||||||
|
|
||||||
// is the bottom right corner of r2 contacting r1?
|
// is the bottom right corner of r2 contacting r1?
|
||||||
CATCH(errctx, collide_point_rectangle(&r2p.bottomright, &r1p, collide));
|
CATCH(errctx, akgl_collide_point_rectangle(&r2p.bottomright, &r1p, collide));
|
||||||
if ( *collide == true ) { SUCCEED_RETURN(errctx); }
|
if ( *collide == true ) { SUCCEED_RETURN(errctx); }
|
||||||
|
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
@@ -95,30 +95,30 @@ ErrorContext *collide_rectangles(SDL_FRect *r1, SDL_FRect *r2, bool *collide)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ErrorContext *compare_sdl_surfaces(SDL_Surface *s1, SDL_Surface *s2)
|
akerr_ErrorContext *akgl_compare_sdl_surfaces(SDL_Surface *s1, SDL_Surface *s2)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, s1, ERR_NULLPOINTER, "NULL Surface pointer");
|
FAIL_ZERO_RETURN(errctx, s1, AKERR_NULLPOINTER, "NULL Surface pointer");
|
||||||
FAIL_ZERO_RETURN(errctx, s2, ERR_NULLPOINTER, "NULL Surface pointer");
|
FAIL_ZERO_RETURN(errctx, s2, AKERR_NULLPOINTER, "NULL Surface pointer");
|
||||||
FAIL_NONZERO_RETURN(errctx, memcmp(s1->pixels, s2->pixels, (s1->pitch * s1->h)), ERR_VALUE, "Comparison surfaces are not equal");
|
FAIL_NONZERO_RETURN(errctx, memcmp(s1->pixels, s2->pixels, (s1->pitch * s1->h)), AKERR_VALUE, "Comparison surfaces are not equal");
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *render_and_compare(SDL_Texture *t1, SDL_Texture *t2, int x, int y, int w, int h, char *writeout)
|
akerr_ErrorContext *akgl_render_and_compare(SDL_Texture *t1, SDL_Texture *t2, int x, int y, int w, int h, char *writeout)
|
||||||
{
|
{
|
||||||
SDL_Surface *s1 = NULL;
|
SDL_Surface *s1 = NULL;
|
||||||
SDL_Surface *s2 = NULL;
|
SDL_Surface *s2 = NULL;
|
||||||
SDL_FRect src = {.x = x, .y = y, .w = w, .h = h};
|
SDL_FRect src = {.x = x, .y = y, .w = w, .h = h};
|
||||||
SDL_FRect dest = {.x = x, .y = y, .w = w, .h = h};
|
SDL_FRect dest = {.x = x, .y = y, .w = w, .h = h};
|
||||||
SDL_Rect read = {.x = x, .y = y, .w = w, .h = h};
|
SDL_Rect read = {.x = x, .y = y, .w = w, .h = h};
|
||||||
string *tmpstring = NULL;
|
akgl_String *tmpstring = NULL;
|
||||||
|
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
FAIL_ZERO_BREAK(errctx, t1, ERR_NULLPOINTER, "NULL texture");
|
FAIL_ZERO_BREAK(errctx, t1, AKERR_NULLPOINTER, "NULL texture");
|
||||||
FAIL_ZERO_BREAK(errctx, t2, ERR_NULLPOINTER, "NULL texture");
|
FAIL_ZERO_BREAK(errctx, t2, AKERR_NULLPOINTER, "NULL texture");
|
||||||
|
|
||||||
CATCH(errctx, heap_next_string(&tmpstring));
|
CATCH(errctx, akgl_heap_next_string(&tmpstring));
|
||||||
SDL_RenderClear(renderer);
|
SDL_RenderClear(renderer);
|
||||||
FAIL_ZERO_BREAK(
|
FAIL_ZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
@@ -127,17 +127,17 @@ ErrorContext *render_and_compare(SDL_Texture *t1, SDL_Texture *t2, int x, int y,
|
|||||||
t1,
|
t1,
|
||||||
&src,
|
&src,
|
||||||
&dest),
|
&dest),
|
||||||
ERR_SDL,
|
AKGL_ERR_SDL,
|
||||||
"Failed to render test texture");
|
"Failed to render test texture");
|
||||||
s1 = SDL_RenderReadPixels(renderer, &read);
|
s1 = SDL_RenderReadPixels(renderer, &read);
|
||||||
FAIL_ZERO_BREAK(errctx, s1, ERR_SDL, "Failed to read pixels from renderer");
|
FAIL_ZERO_BREAK(errctx, s1, AKGL_ERR_SDL, "Failed to read pixels from renderer");
|
||||||
|
|
||||||
if ( writeout != NULL ) {
|
if ( writeout != NULL ) {
|
||||||
snprintf((char *)&tmpstring->data, MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), writeout);
|
snprintf((char *)&tmpstring->data, AKGL_MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), writeout);
|
||||||
FAIL_ZERO_BREAK(
|
FAIL_ZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
IMG_SavePNG(s1, (char *)&tmpstring->data),
|
IMG_SavePNG(s1, (char *)&tmpstring->data),
|
||||||
ERR_IO,
|
AKERR_IO,
|
||||||
"Unable to save %s: %s",
|
"Unable to save %s: %s",
|
||||||
(char *)&tmpstring->data,
|
(char *)&tmpstring->data,
|
||||||
SDL_GetError());
|
SDL_GetError());
|
||||||
@@ -152,18 +152,18 @@ ErrorContext *render_and_compare(SDL_Texture *t1, SDL_Texture *t2, int x, int y,
|
|||||||
t2,
|
t2,
|
||||||
&src,
|
&src,
|
||||||
&dest),
|
&dest),
|
||||||
ERR_SDL,
|
AKGL_ERR_SDL,
|
||||||
"Failed to render test texture");
|
"Failed to render test texture");
|
||||||
s2 = SDL_RenderReadPixels(renderer, &read);
|
s2 = SDL_RenderReadPixels(renderer, &read);
|
||||||
FAIL_ZERO_BREAK(errctx, s2, ERR_SDL, "Failed to read pixels from renderer");
|
FAIL_ZERO_BREAK(errctx, s2, AKGL_ERR_SDL, "Failed to read pixels from renderer");
|
||||||
|
|
||||||
CATCH(errctx, compare_sdl_surfaces(s1, s2));
|
CATCH(errctx, akgl_compare_sdl_surfaces(s1, s2));
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
if ( s1 != NULL )
|
if ( s1 != NULL )
|
||||||
SDL_DestroySurface(s1);
|
SDL_DestroySurface(s1);
|
||||||
if ( s2 != NULL )
|
if ( s2 != NULL )
|
||||||
SDL_DestroySurface(s2);
|
SDL_DestroySurface(s2);
|
||||||
IGNORE(heap_release_string(tmpstring));
|
IGNORE(akgl_heap_release_string(tmpstring));
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
|
|||||||
229
tests/actor.c
229
tests/actor.c
@@ -1,7 +1,7 @@
|
|||||||
#define UNHANDLED_ERROR_TERMINATION_BEHAVIOR \
|
#define UNHANDLED_ERROR_TERMINATION_BEHAVIOR \
|
||||||
handle_unhandled_error(errctx);
|
handle_unhandled_error(errctx);
|
||||||
|
|
||||||
#include <sdlerror.h>
|
#include <akerror.h>
|
||||||
|
|
||||||
#define UNHANDLED_ERROR_EXIT 0
|
#define UNHANDLED_ERROR_EXIT 0
|
||||||
#define UNHANDLED_ERROR_SET 1
|
#define UNHANDLED_ERROR_SET 1
|
||||||
@@ -9,15 +9,15 @@
|
|||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <sdl3game/iterator.h>
|
#include <akgl/iterator.h>
|
||||||
#include <sdl3game/registry.h>
|
#include <akgl/registry.h>
|
||||||
#include <sdl3game/actor.h>
|
#include <akgl/actor.h>
|
||||||
#include <sdl3game/heap.h>
|
#include <akgl/heap.h>
|
||||||
|
|
||||||
int UNHANDLED_ERROR_BEHAVIOR;
|
int UNHANDLED_ERROR_BEHAVIOR;
|
||||||
ErrorContext *unhandled_error_context;
|
akerr_ErrorContext *unhandled_error_context;
|
||||||
|
|
||||||
void handle_unhandled_error_noexit(ErrorContext *errctx)
|
void handle_unhandled_error_noexit(akerr_ErrorContext *errctx)
|
||||||
{
|
{
|
||||||
if ( errctx == NULL ) {
|
if ( errctx == NULL ) {
|
||||||
return;
|
return;
|
||||||
@@ -32,203 +32,200 @@ void handle_unhandled_error_noexit(ErrorContext *errctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int actor_updated;
|
int akgl_actor_updated;
|
||||||
ErrorContext *actor_update_noop(actor *obj)
|
akerr_ErrorContext *akgl_actor_update_noop(akgl_Actor *obj)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
actor_updated = 1;
|
akgl_actor_updated = 1;
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Currently the renderer assumes there is a global variable named `renderer`
|
// Currently the renderer assumes there is a global variable named `renderer`
|
||||||
int actor_rendered;
|
int akgl_actor_rendered;
|
||||||
ErrorContext *actor_render_noop(actor *obj, SDL_Renderer *r)
|
akerr_ErrorContext *akgl_actor_render_noop(akgl_Actor *obj, SDL_Renderer *r)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
actor_rendered = 1;
|
akgl_actor_rendered = 1;
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *test_registry_actor_iterator_nullpointers(void)
|
akerr_ErrorContext *test_registry_actor_iterator_nullpointers(void)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
|
|
||||||
ErrorUnhandledErrorHandler defaulthandler = error_handler_unhandled_error;
|
akerr_ErrorUnhandledErrorHandler defaulthandler = akerr_handler_unhandled_error;
|
||||||
|
|
||||||
error_handler_unhandled_error = handle_unhandled_error_noexit;
|
akerr_handler_unhandled_error = handle_unhandled_error_noexit;
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
UNHANDLED_ERROR_BEHAVIOR = UNHANDLED_ERROR_SET;
|
UNHANDLED_ERROR_BEHAVIOR = UNHANDLED_ERROR_SET;
|
||||||
DETECT(unhandled_error_context, registry_iterate_actor(NULL, REGISTRY_ACTOR, ""));
|
DETECT(unhandled_error_context, akgl_registry_iterate_actor(NULL, AKGL_REGISTRY_ACTOR, ""));
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
UNHANDLED_ERROR_BEHAVIOR = UNHANDLED_ERROR_EXIT;
|
UNHANDLED_ERROR_BEHAVIOR = UNHANDLED_ERROR_EXIT;
|
||||||
} PROCESS(unhandled_error_context) {
|
} PROCESS(unhandled_error_context) {
|
||||||
} HANDLE(unhandled_error_context, ERR_NULLPOINTER) {
|
} HANDLE(unhandled_error_context, AKERR_NULLPOINTER) {
|
||||||
printf("Handled\n");
|
printf("Handled\n");
|
||||||
} FINISH(unhandled_error_context, true);
|
} FINISH(unhandled_error_context, true);
|
||||||
IGNORE(heap_release_error(unhandled_error_context));
|
akerr_handler_unhandled_error = defaulthandler;
|
||||||
error_handler_unhandled_error = defaulthandler;
|
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *test_registry_actor_iterator_missingactor(void)
|
akerr_ErrorContext *test_registry_actor_iterator_missingactor(void)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
ErrorUnhandledErrorHandler defaulthandler = error_handler_unhandled_error;
|
akerr_ErrorUnhandledErrorHandler defaulthandler = akerr_handler_unhandled_error;
|
||||||
|
|
||||||
iterator iter = {
|
akgl_Iterator iter = {
|
||||||
.layerid = 0,
|
.layerid = 0,
|
||||||
.flags = 0
|
.flags = 0
|
||||||
};
|
};
|
||||||
error_handler_unhandled_error = handle_unhandled_error_noexit;
|
akerr_handler_unhandled_error = handle_unhandled_error_noexit;
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
UNHANDLED_ERROR_BEHAVIOR = UNHANDLED_ERROR_SET;
|
UNHANDLED_ERROR_BEHAVIOR = UNHANDLED_ERROR_SET;
|
||||||
DETECT(
|
DETECT(
|
||||||
unhandled_error_context,
|
unhandled_error_context,
|
||||||
registry_iterate_actor(
|
akgl_registry_iterate_actor(
|
||||||
&iter,
|
&iter,
|
||||||
REGISTRY_ACTOR,
|
AKGL_REGISTRY_ACTOR,
|
||||||
"Actor who doesn't exist")
|
"Actor who doesn't exist")
|
||||||
);
|
);
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
UNHANDLED_ERROR_BEHAVIOR = UNHANDLED_ERROR_EXIT;
|
UNHANDLED_ERROR_BEHAVIOR = UNHANDLED_ERROR_EXIT;
|
||||||
} PROCESS(unhandled_error_context) {
|
} PROCESS(unhandled_error_context) {
|
||||||
} HANDLE(unhandled_error_context, ERR_KEY) {
|
} HANDLE(unhandled_error_context, AKERR_KEY) {
|
||||||
printf("Handled\n");
|
printf("Handled\n");
|
||||||
} FINISH(unhandled_error_context, true);
|
} FINISH(unhandled_error_context, true);
|
||||||
IGNORE(heap_release_error(unhandled_error_context));
|
akerr_handler_unhandled_error = defaulthandler;
|
||||||
error_handler_unhandled_error = defaulthandler;
|
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *test_registry_actor_iterator_updaterender(void)
|
akerr_ErrorContext *test_registry_actor_iterator_updaterender(void)
|
||||||
{
|
{
|
||||||
actor *testactor;
|
akgl_Actor *testactor;
|
||||||
iterator iter = {
|
akgl_Iterator iter = {
|
||||||
.layerid = 0,
|
.layerid = 0,
|
||||||
.flags = ITERATOR_OP_UPDATE | ITERATOR_OP_RENDER
|
.flags = AKGL_ITERATOR_OP_UPDATE | AKGL_ITERATOR_OP_RENDER
|
||||||
};
|
};
|
||||||
ErrorUnhandledErrorHandler defaulthandler = error_handler_unhandled_error;
|
akerr_ErrorUnhandledErrorHandler defaulthandler = akerr_handler_unhandled_error;
|
||||||
|
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
error_handler_unhandled_error = handle_unhandled_error_noexit;
|
akerr_handler_unhandled_error = handle_unhandled_error_noexit;
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
UNHANDLED_ERROR_BEHAVIOR = UNHANDLED_ERROR_SET;
|
UNHANDLED_ERROR_BEHAVIOR = UNHANDLED_ERROR_SET;
|
||||||
CATCH(unhandled_error_context, heap_next_actor(&testactor));
|
CATCH(unhandled_error_context, akgl_heap_next_actor(&testactor));
|
||||||
CATCH(unhandled_error_context, actor_initialize(testactor, "test"));
|
CATCH(unhandled_error_context, akgl_actor_initialize(testactor, "test"));
|
||||||
|
|
||||||
testactor->layer = 0;
|
testactor->layer = 0;
|
||||||
testactor->updatefunc = &actor_update_noop;
|
testactor->updatefunc = &akgl_actor_update_noop;
|
||||||
testactor->renderfunc = &actor_render_noop;
|
testactor->renderfunc = &akgl_actor_render_noop;
|
||||||
|
|
||||||
DETECT(
|
DETECT(
|
||||||
unhandled_error_context,
|
unhandled_error_context,
|
||||||
registry_iterate_actor(
|
akgl_registry_iterate_actor(
|
||||||
&iter,
|
&iter,
|
||||||
REGISTRY_ACTOR,
|
AKGL_REGISTRY_ACTOR,
|
||||||
"test")
|
"test")
|
||||||
);
|
);
|
||||||
|
|
||||||
FAIL_ZERO_BREAK(
|
FAIL_ZERO_BREAK(
|
||||||
unhandled_error_context,
|
unhandled_error_context,
|
||||||
actor_updated,
|
akgl_actor_updated,
|
||||||
ERR_BEHAVIOR,
|
AKERR_BEHAVIOR,
|
||||||
"actor->updatefunc not called by the iterator"
|
"actor->updatefunc not called by the iterator"
|
||||||
);
|
);
|
||||||
FAIL_ZERO_BREAK(
|
FAIL_ZERO_BREAK(
|
||||||
unhandled_error_context,
|
unhandled_error_context,
|
||||||
actor_rendered,
|
akgl_actor_rendered,
|
||||||
ERR_BEHAVIOR,
|
AKERR_BEHAVIOR,
|
||||||
"actor->renderfunc not called by the iterator"
|
"actor->renderfunc not called by the iterator"
|
||||||
);
|
);
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
UNHANDLED_ERROR_BEHAVIOR = UNHANDLED_ERROR_EXIT;
|
UNHANDLED_ERROR_BEHAVIOR = UNHANDLED_ERROR_EXIT;
|
||||||
IGNORE(heap_release_actor(testactor));
|
IGNORE(akgl_heap_release_actor(testactor));
|
||||||
} PROCESS(unhandled_error_context) {
|
} PROCESS(unhandled_error_context) {
|
||||||
} FINISH(unhandled_error_context, true);
|
} FINISH(unhandled_error_context, true);
|
||||||
|
|
||||||
IGNORE(heap_release_error(unhandled_error_context));
|
akerr_handler_unhandled_error = defaulthandler;
|
||||||
error_handler_unhandled_error = defaulthandler;
|
|
||||||
|
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *test_actor_set_character(void)
|
akerr_ErrorContext *test_akgl_actor_set_character(void)
|
||||||
{
|
{
|
||||||
actor *testactor = NULL;
|
akgl_Actor *testactor = NULL;
|
||||||
character *testchar = NULL;
|
akgl_Character *testchar = NULL;
|
||||||
|
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, actor_set_character(NULL, "test"));
|
CATCH(errctx, akgl_actor_set_character(NULL, "test"));
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} HANDLE(errctx, ERR_NULLPOINTER) {
|
} HANDLE(errctx, AKERR_NULLPOINTER) {
|
||||||
printf("Handled\n");
|
printf("Handled\n");
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
|
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, heap_next_actor(&testactor));
|
CATCH(errctx, akgl_heap_next_actor(&testactor));
|
||||||
|
|
||||||
CATCH(errctx, actor_initialize(testactor, "test"));
|
CATCH(errctx, akgl_actor_initialize(testactor, "test"));
|
||||||
testactor->layer = 0;
|
testactor->layer = 0;
|
||||||
testactor->updatefunc = &actor_update_noop;
|
testactor->updatefunc = &akgl_actor_update_noop;
|
||||||
testactor->renderfunc = &actor_render_noop;
|
testactor->renderfunc = &akgl_actor_render_noop;
|
||||||
|
|
||||||
CATCH(errctx, actor_set_character(testactor, "test"));
|
CATCH(errctx, akgl_actor_set_character(testactor, "test"));
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
IGNORE(heap_release_actor(testactor));
|
IGNORE(akgl_heap_release_actor(testactor));
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} HANDLE(errctx, ERR_NULLPOINTER) {
|
} HANDLE(errctx, AKERR_NULLPOINTER) {
|
||||||
printf("Handled\n");
|
printf("Handled\n");
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, heap_next_actor(&testactor));
|
CATCH(errctx, akgl_heap_next_actor(&testactor));
|
||||||
CATCH(errctx, heap_next_character(&testchar));
|
CATCH(errctx, akgl_heap_next_character(&testchar));
|
||||||
|
|
||||||
CATCH(errctx, actor_initialize(testactor, "test"));
|
CATCH(errctx, akgl_actor_initialize(testactor, "test"));
|
||||||
testactor->layer = 0;
|
testactor->layer = 0;
|
||||||
testactor->updatefunc = &actor_update_noop;
|
testactor->updatefunc = &akgl_actor_update_noop;
|
||||||
testactor->renderfunc = &actor_render_noop;
|
testactor->renderfunc = &akgl_actor_render_noop;
|
||||||
|
|
||||||
CATCH(errctx, character_initialize(testchar, "test"));
|
CATCH(errctx, akgl_character_initialize(testchar, "test"));
|
||||||
|
|
||||||
CATCH(errctx, actor_set_character(testactor, "test"));
|
CATCH(errctx, akgl_actor_set_character(testactor, "test"));
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
IGNORE(heap_release_actor(testactor));
|
IGNORE(akgl_heap_release_actor(testactor));
|
||||||
IGNORE(heap_release_character(testchar));
|
IGNORE(akgl_heap_release_character(testchar));
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
|
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *test_actor_manage_children(void)
|
akerr_ErrorContext *test_actor_manage_children(void)
|
||||||
{
|
{
|
||||||
actor *parent = NULL;
|
akgl_Actor *parent = NULL;
|
||||||
actor *child = NULL;
|
akgl_Actor *child = NULL;
|
||||||
string *tmpstring = NULL;
|
akgl_String *tmpstring = NULL;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int j = 0;
|
int j = 0;
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, heap_init());
|
CATCH(errctx, akgl_heap_init());
|
||||||
CATCH(errctx, heap_next_string(&tmpstring));
|
CATCH(errctx, akgl_heap_next_string(&tmpstring));
|
||||||
CATCH(errctx, heap_next_actor(&parent));
|
CATCH(errctx, akgl_heap_next_actor(&parent));
|
||||||
CATCH(errctx, actor_initialize(parent, "parent"));
|
CATCH(errctx, akgl_actor_initialize(parent, "parent"));
|
||||||
for ( i = 0 ; i < ACTOR_MAX_CHILDREN; i++ ) {
|
for ( i = 0 ; i < AKGL_ACTOR_MAX_CHILDREN; i++ ) {
|
||||||
sprintf((char *)&tmpstring->data, "child %d", i);
|
sprintf((char *)&tmpstring->data, "child %d", i);
|
||||||
CATCH(errctx, heap_next_actor(&child));
|
CATCH(errctx, akgl_heap_next_actor(&child));
|
||||||
CATCH(errctx, actor_initialize(child, (char *)&tmpstring->data));
|
CATCH(errctx, akgl_actor_initialize(child, (char *)&tmpstring->data));
|
||||||
CATCH(errctx, parent->addchild(parent, child));
|
CATCH(errctx, parent->addchild(parent, child));
|
||||||
// Release our claim on the actor so the parent can own the child and kill it
|
// Release our claim on the actor so the parent can own the child and kill it
|
||||||
CATCH(errctx, heap_release_actor(child));
|
CATCH(errctx, akgl_heap_release_actor(child));
|
||||||
}
|
}
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
IGNORE(heap_release_string(tmpstring));
|
IGNORE(akgl_heap_release_string(tmpstring));
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
|
|
||||||
@@ -238,46 +235,46 @@ ErrorContext *test_actor_manage_children(void)
|
|||||||
CATCH(errctx, parent->addchild(parent, child));
|
CATCH(errctx, parent->addchild(parent, child));
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
if ( errctx == NULL ) {
|
if ( errctx == NULL ) {
|
||||||
FAIL(errctx, ERR_BEHAVIOR, "addchild does not throw ERR_RELATIONSHIP when child already has a parent");
|
FAIL(errctx, AKERR_BEHAVIOR, "addchild does not throw AKERR_RELATIONSHIP when child already has a parent");
|
||||||
}
|
}
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} HANDLE(errctx, ERR_RELATIONSHIP) {
|
} HANDLE(errctx, AKERR_RELATIONSHIP) {
|
||||||
// Expected behavior
|
// Expected behavior
|
||||||
SDL_Log("addchild throws ERR_RELATIONSHIP when child already has a parent");
|
SDL_Log("addchild throws AKERR_RELATIONSHIP when child already has a parent");
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, heap_next_actor(&child));
|
CATCH(errctx, akgl_heap_next_actor(&child));
|
||||||
CATCH(errctx, parent->addchild(parent, child));
|
CATCH(errctx, parent->addchild(parent, child));
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
if ( errctx == NULL ) {
|
if ( errctx == NULL ) {
|
||||||
FAIL(errctx, ERR_BEHAVIOR, "addchild does not throw ERR_OUTOFBOUNDS when all children already set");
|
FAIL(errctx, AKERR_BEHAVIOR, "addchild does not throw AKERR_OUTOFBOUNDS when all children already set");
|
||||||
}
|
}
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} HANDLE(errctx, ERR_OUTOFBOUNDS) {
|
} HANDLE(errctx, AKERR_OUTOFBOUNDS) {
|
||||||
// Expected behavior
|
// Expected behavior
|
||||||
SDL_Log("addchild throws ERR_OUTOFBOUNDS when all children already set");
|
SDL_Log("addchild throws AKERR_OUTOFBOUNDS when all children already set");
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, heap_release_actor(parent));
|
CATCH(errctx, akgl_heap_release_actor(parent));
|
||||||
// All actor objects on the heap should be empty now
|
// All actor objects on the heap should be empty now
|
||||||
for ( i = 0; i < MAX_HEAP_ACTOR; i++) {
|
for ( i = 0; i < AKGL_MAX_HEAP_ACTOR; i++) {
|
||||||
FAIL_NONZERO_BREAK(errctx, HEAP_ACTOR[i].refcount, ERR_VALUE, "Actor not properly cleared");
|
FAIL_NONZERO_BREAK(errctx, HEAP_ACTOR[i].refcount, AKERR_VALUE, "Actor not properly cleared");
|
||||||
FAIL_NONZERO_BREAK(errctx, HEAP_ACTOR[i].parent, ERR_VALUE, "Actor not properly cleared");
|
FAIL_NONZERO_BREAK(errctx, HEAP_ACTOR[i].parent, AKERR_VALUE, "Actor not properly cleared");
|
||||||
for ( j = 0 ; j < ACTOR_MAX_CHILDREN; j++) {
|
for ( j = 0 ; j < AKGL_ACTOR_MAX_CHILDREN; j++) {
|
||||||
if ( HEAP_ACTOR[i].children[j] != NULL ) {
|
if ( HEAP_ACTOR[i].children[j] != NULL ) {
|
||||||
FAIL(errctx, ERR_VALUE, "Actor not properly cleared");
|
FAIL(errctx, AKERR_VALUE, "Actor not properly cleared");
|
||||||
goto _test_actor_addchild_heaprelease_cleanup;
|
goto _test_actor_addchild_heaprelease_cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for ( j = 0; j < ACTOR_MAX_CHILDREN; j++) {
|
for ( j = 0; j < AKGL_ACTOR_MAX_CHILDREN; j++) {
|
||||||
sprintf((char *)&tmpstring->data, "child %d", i);
|
sprintf((char *)&tmpstring->data, "child %d", i);
|
||||||
FAIL_NONZERO_BREAK(
|
FAIL_NONZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
SDL_GetPointerProperty(REGISTRY_ACTOR, (char *)&tmpstring->data, NULL),
|
SDL_GetPointerProperty(AKGL_REGISTRY_ACTOR, (char *)&tmpstring->data, NULL),
|
||||||
ERR_KEY,
|
AKERR_KEY,
|
||||||
"Child %s was not removed from the registry",
|
"Child %s was not removed from the registry",
|
||||||
(char *)&tmpstring->data);
|
(char *)&tmpstring->data);
|
||||||
}
|
}
|
||||||
@@ -287,22 +284,22 @@ _test_actor_addchild_heaprelease_cleanup:
|
|||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, heap_next_actor(&parent));
|
CATCH(errctx, akgl_heap_next_actor(&parent));
|
||||||
CATCH(errctx, actor_initialize(parent, "parent"));
|
CATCH(errctx, akgl_actor_initialize(parent, "parent"));
|
||||||
CATCH(errctx, heap_next_actor(&child));
|
CATCH(errctx, akgl_heap_next_actor(&child));
|
||||||
CATCH(errctx, actor_initialize(child, "child"));
|
CATCH(errctx, akgl_actor_initialize(child, "child"));
|
||||||
// Don't release our claim on the child. The child should not be reclaimed.
|
// Don't release our claim on the child. The child should not be reclaimed.
|
||||||
CATCH(errctx, heap_release_actor(parent));
|
CATCH(errctx, akgl_heap_release_actor(parent));
|
||||||
FAIL_NONZERO_BREAK(errctx, child->parent, ERR_VALUE, "Child still references released parent");
|
FAIL_NONZERO_BREAK(errctx, child->parent, AKERR_VALUE, "Child still references released parent");
|
||||||
FAIL_ZERO_BREAK(errctx, child->refcount, ERR_VALUE, "Child prematurely released");
|
FAIL_ZERO_BREAK(errctx, child->refcount, AKERR_VALUE, "Child prematurely released");
|
||||||
FAIL_NONZERO_BREAK(errctx, strcmp(child->name, "child"), ERR_VALUE, "Child had identity erased");
|
FAIL_NONZERO_BREAK(errctx, strcmp(child->name, "child"), AKERR_VALUE, "Child had identity erased");
|
||||||
FAIL_ZERO_BREAK(
|
FAIL_ZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
(child == SDL_GetPointerProperty(REGISTRY_ACTOR, child->name, NULL)),
|
(child == SDL_GetPointerProperty(AKGL_REGISTRY_ACTOR, child->name, NULL)),
|
||||||
ERR_KEY,
|
AKERR_KEY,
|
||||||
"Child prematurely removed from the registry");
|
"Child prematurely removed from the registry");
|
||||||
// Now we can release the child
|
// Now we can release the child
|
||||||
CATCH(errctx, heap_release_actor(child));
|
CATCH(errctx, akgl_heap_release_actor(child));
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
@@ -312,20 +309,20 @@ _test_actor_addchild_heaprelease_cleanup:
|
|||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
actor_updated = 0;
|
akgl_actor_updated = 0;
|
||||||
actor_rendered = 0;
|
akgl_actor_rendered = 0;
|
||||||
UNHANDLED_ERROR_BEHAVIOR = UNHANDLED_ERROR_EXIT;
|
UNHANDLED_ERROR_BEHAVIOR = UNHANDLED_ERROR_EXIT;
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, registry_init_actor());
|
CATCH(errctx, akgl_registry_init_actor());
|
||||||
CATCH(errctx, registry_init_sprite());
|
CATCH(errctx, akgl_registry_init_sprite());
|
||||||
CATCH(errctx, registry_init_spritesheet());
|
CATCH(errctx, akgl_registry_init_spritesheet());
|
||||||
CATCH(errctx, registry_init_character());
|
CATCH(errctx, akgl_registry_init_character());
|
||||||
|
|
||||||
CATCH(errctx, test_registry_actor_iterator_nullpointers());
|
CATCH(errctx, test_registry_actor_iterator_nullpointers());
|
||||||
CATCH(errctx, test_registry_actor_iterator_missingactor());
|
CATCH(errctx, test_registry_actor_iterator_missingactor());
|
||||||
CATCH(errctx, test_registry_actor_iterator_updaterender());
|
CATCH(errctx, test_registry_actor_iterator_updaterender());
|
||||||
CATCH(errctx, test_actor_set_character());
|
CATCH(errctx, test_akgl_actor_set_character());
|
||||||
CATCH(errctx, test_actor_manage_children());
|
CATCH(errctx, test_actor_manage_children());
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
"sprite_mappings": [
|
"sprite_mappings": [
|
||||||
{
|
{
|
||||||
"state": [
|
"state": [
|
||||||
"ACTOR_STATE_ALIVE",
|
"AKGL_ACTOR_STATE_ALIVE",
|
||||||
"ACTOR_STATE_FACE_LEFT"
|
"AKGL_ACTOR_STATE_FACE_LEFT"
|
||||||
],
|
],
|
||||||
"sprite": "testsprite"
|
"sprite": "testsprite"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,31 +1,31 @@
|
|||||||
#include <sdl3game/game.h>
|
#include <akgl/game.h>
|
||||||
#include <sdl3game/actor.h>
|
#include <akgl/actor.h>
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
int mask = 0;
|
int mask = 0;
|
||||||
BITMASK_ADD(mask, ACTOR_STATE_ALIVE);
|
AKGL_BITMASK_ADD(mask, AKGL_ACTOR_STATE_ALIVE);
|
||||||
if ( mask != ACTOR_STATE_ALIVE )
|
if ( mask != AKGL_ACTOR_STATE_ALIVE )
|
||||||
return 1;
|
return 1;
|
||||||
BITMASK_ADD(mask, ACTOR_STATE_FACE_LEFT);
|
AKGL_BITMASK_ADD(mask, AKGL_ACTOR_STATE_FACE_LEFT);
|
||||||
if ( mask != (ACTOR_STATE_ALIVE | ACTOR_STATE_FACE_LEFT) )
|
if ( mask != (AKGL_ACTOR_STATE_ALIVE | AKGL_ACTOR_STATE_FACE_LEFT) )
|
||||||
return 1;
|
return 1;
|
||||||
BITMASK_DEL(mask, ACTOR_STATE_ALIVE);
|
AKGL_BITMASK_DEL(mask, AKGL_ACTOR_STATE_ALIVE);
|
||||||
if ( mask != (ACTOR_STATE_FACE_LEFT) )
|
if ( mask != (AKGL_ACTOR_STATE_FACE_LEFT) )
|
||||||
return 1;
|
return 1;
|
||||||
BITMASK_CLEAR(mask);
|
AKGL_BITMASK_CLEAR(mask);
|
||||||
if ( mask != 0 )
|
if ( mask != 0 )
|
||||||
return 1;
|
return 1;
|
||||||
BITMASK_ADD(mask, ACTOR_STATE_FACE_LEFT);
|
AKGL_BITMASK_ADD(mask, AKGL_ACTOR_STATE_FACE_LEFT);
|
||||||
if ( !(BITMASK_HAS(mask, ACTOR_STATE_FACE_LEFT)) )
|
if ( !(AKGL_BITMASK_HAS(mask, AKGL_ACTOR_STATE_FACE_LEFT)) )
|
||||||
return 1;
|
return 1;
|
||||||
mask = ACTOR_STATE_ALIVE | ACTOR_STATE_FACE_UP;
|
mask = AKGL_ACTOR_STATE_ALIVE | AKGL_ACTOR_STATE_FACE_UP;
|
||||||
BITMASK_DEL(mask, ACTOR_STATE_FACE_ALL);
|
AKGL_BITMASK_DEL(mask, AKGL_ACTOR_STATE_FACE_ALL);
|
||||||
if ( mask != ACTOR_STATE_ALIVE )
|
if ( mask != AKGL_ACTOR_STATE_ALIVE )
|
||||||
return 1;
|
return 1;
|
||||||
BITMASK_ADD(mask, ACTOR_STATE_MOVING_DOWN);
|
AKGL_BITMASK_ADD(mask, AKGL_ACTOR_STATE_MOVING_DOWN);
|
||||||
BITMASK_ADD(mask, ACTOR_STATE_FACE_DOWN);
|
AKGL_BITMASK_ADD(mask, AKGL_ACTOR_STATE_FACE_DOWN);
|
||||||
if ( mask != (ACTOR_STATE_ALIVE | ACTOR_STATE_MOVING_DOWN | ACTOR_STATE_FACE_DOWN) )
|
if ( mask != (AKGL_ACTOR_STATE_ALIVE | AKGL_ACTOR_STATE_MOVING_DOWN | AKGL_ACTOR_STATE_FACE_DOWN) )
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,186 +1,187 @@
|
|||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <sdlerror.h>
|
#include <akerror.h>
|
||||||
|
|
||||||
#include <sdl3game/character.h>
|
#include <akgl/character.h>
|
||||||
#include <sdl3game/actor.h>
|
#include <akgl/actor.h>
|
||||||
#include <sdl3game/heap.h>
|
#include <akgl/error.h>
|
||||||
#include <sdl3game/registry.h>
|
#include <akgl/heap.h>
|
||||||
#include <sdl3game/iterator.h>
|
#include <akgl/registry.h>
|
||||||
|
#include <akgl/iterator.h>
|
||||||
|
|
||||||
SDL_Window *window;
|
SDL_Window *window;
|
||||||
SDL_Renderer *renderer;
|
SDL_Renderer *renderer;
|
||||||
|
|
||||||
ErrorContext *test_character_initialize()
|
akerr_ErrorContext *test_akgl_character_initialize()
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
character *testchar = NULL;
|
akgl_Character *testchar = NULL;
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, heap_next_character(&testchar));
|
CATCH(errctx, akgl_heap_next_character(&testchar));
|
||||||
CATCH(errctx, character_initialize(testchar, "testchar"));
|
CATCH(errctx, akgl_character_initialize(testchar, "testchar"));
|
||||||
FAIL_ZERO_BREAK(
|
FAIL_ZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
SDL_GetPointerProperty(REGISTRY_CHARACTER, "testchar", NULL),
|
SDL_GetPointerProperty(AKGL_REGISTRY_CHARACTER, "testchar", NULL),
|
||||||
ERR_KEY,
|
AKERR_KEY,
|
||||||
"Character was not placed in the registry");
|
"Character was not placed in the registry");
|
||||||
FAIL_NONZERO_BREAK(
|
FAIL_NONZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
strcmp((char *)&testchar->name, "testchar"),
|
strcmp((char *)&testchar->name, "testchar"),
|
||||||
ERR_VALUE,
|
AKERR_VALUE,
|
||||||
"Character was not named properly ('testchar' vs '%s')",
|
"Character was not named properly ('testchar' vs '%s')",
|
||||||
(char *)&testchar->name);
|
(char *)&testchar->name);
|
||||||
FAIL_ZERO_BREAK(
|
FAIL_ZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
testchar->state_sprites,
|
testchar->state_sprites,
|
||||||
ERR_NULLPOINTER,
|
AKERR_NULLPOINTER,
|
||||||
"Character state sprites map was not initialized");
|
"Character state sprites map was not initialized");
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
IGNORE(heap_release_character(testchar));
|
IGNORE(akgl_heap_release_character(testchar));
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *test_character_sprite_mgmt()
|
akerr_ErrorContext *test_character_sprite_mgmt()
|
||||||
{
|
{
|
||||||
character *testchar = NULL;
|
akgl_Character *testchar = NULL;
|
||||||
sprite *testsprite = NULL;
|
akgl_Sprite *testsprite = NULL;
|
||||||
sprite *testsprite2 = NULL;
|
akgl_Sprite *testsprite2 = NULL;
|
||||||
sprite *comparesprite = NULL;
|
akgl_Sprite *comparesprite = NULL;
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, heap_next_character(&testchar));
|
CATCH(errctx, akgl_heap_next_character(&testchar));
|
||||||
CATCH(errctx, sprite_load_json("assets/testsprite.json"));
|
CATCH(errctx, akgl_sprite_load_json("assets/testsprite.json"));
|
||||||
testsprite = SDL_GetPointerProperty(REGISTRY_SPRITE, "testsprite", NULL);
|
testsprite = SDL_GetPointerProperty(AKGL_REGISTRY_SPRITE, "testsprite", NULL);
|
||||||
FAIL_ZERO_BREAK(
|
FAIL_ZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
testsprite,
|
testsprite,
|
||||||
ERR_KEY,
|
AKERR_KEY,
|
||||||
"Sprite loaded from json but not in registry");
|
"Sprite loaded from json but not in registry");
|
||||||
CATCH(errctx, sprite_load_json("assets/testsprite2.json"));
|
CATCH(errctx, akgl_sprite_load_json("assets/testsprite2.json"));
|
||||||
testsprite2 = SDL_GetPointerProperty(REGISTRY_SPRITE, "testsprite2", NULL);
|
testsprite2 = SDL_GetPointerProperty(AKGL_REGISTRY_SPRITE, "testsprite2", NULL);
|
||||||
FAIL_ZERO_BREAK(
|
FAIL_ZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
testsprite2,
|
testsprite2,
|
||||||
ERR_KEY,
|
AKERR_KEY,
|
||||||
"Sprite 2 loaded from json but not in registry");
|
"Sprite 2 loaded from json but not in registry");
|
||||||
CATCH(errctx, testchar->sprite_add(testchar, testsprite, ACTOR_STATE_ALIVE));
|
CATCH(errctx, testchar->sprite_add(testchar, testsprite, AKGL_ACTOR_STATE_ALIVE));
|
||||||
CATCH(errctx, testchar->sprite_add(testchar, testsprite2, ACTOR_STATE_DEAD));
|
CATCH(errctx, testchar->sprite_add(testchar, testsprite2, AKGL_ACTOR_STATE_DEAD));
|
||||||
CATCH(errctx, testchar->sprite_get(testchar, (ACTOR_STATE_ALIVE), &comparesprite));
|
CATCH(errctx, testchar->sprite_get(testchar, (AKGL_ACTOR_STATE_ALIVE), &comparesprite));
|
||||||
FAIL_ZERO_BREAK(errctx, (comparesprite == testsprite), ERR_VALUE, "Wrong sprite for state ACTOR_STATE_ALIVE | ACTOR_STATE_FACE_LEFT");
|
FAIL_ZERO_BREAK(errctx, (comparesprite == testsprite), AKERR_VALUE, "Wrong sprite for state AKGL_ACTOR_STATE_ALIVE | AKGL_ACTOR_STATE_FACE_LEFT");
|
||||||
CATCH(errctx, testchar->sprite_get(testchar, ACTOR_STATE_DEAD, &comparesprite));
|
CATCH(errctx, testchar->sprite_get(testchar, AKGL_ACTOR_STATE_DEAD, &comparesprite));
|
||||||
FAIL_ZERO_BREAK(errctx, (comparesprite == testsprite2), ERR_VALUE, "Wrong sprite for state ACTOR_STATE_DEAD");
|
FAIL_ZERO_BREAK(errctx, (comparesprite == testsprite2), AKERR_VALUE, "Wrong sprite for state AKGL_ACTOR_STATE_DEAD");
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
IGNORE(heap_release_sprite(testsprite));
|
IGNORE(akgl_heap_release_sprite(testsprite));
|
||||||
IGNORE(heap_release_sprite(testsprite2));
|
IGNORE(akgl_heap_release_sprite(testsprite2));
|
||||||
IGNORE(heap_release_character(testchar));
|
IGNORE(akgl_heap_release_character(testchar));
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *test_character_iterate_state_sprites()
|
akerr_ErrorContext *test_character_iterate_state_sprites()
|
||||||
{
|
{
|
||||||
character *testchar = NULL;
|
akgl_Character *testchar = NULL;
|
||||||
sprite *testsprite = NULL;
|
akgl_Sprite *testsprite = NULL;
|
||||||
sprite *testsprite2 = NULL;
|
akgl_Sprite *testsprite2 = NULL;
|
||||||
iterator opflags = {.flags = ITERATOR_OP_RELEASE, .layerid = 0};
|
akgl_Iterator opflags = {.flags = AKGL_ITERATOR_OP_RELEASE, .layerid = 0};
|
||||||
|
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, heap_next_character(&testchar));
|
CATCH(errctx, akgl_heap_next_character(&testchar));
|
||||||
CATCH(errctx, sprite_load_json("assets/testsprite.json"));
|
CATCH(errctx, akgl_sprite_load_json("assets/testsprite.json"));
|
||||||
testsprite = SDL_GetPointerProperty(REGISTRY_SPRITE, "testsprite", NULL);
|
testsprite = SDL_GetPointerProperty(AKGL_REGISTRY_SPRITE, "testsprite", NULL);
|
||||||
FAIL_ZERO_BREAK(
|
FAIL_ZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
testsprite,
|
testsprite,
|
||||||
ERR_KEY,
|
AKERR_KEY,
|
||||||
"Sprite loaded from json but not in registry");
|
"Sprite loaded from json but not in registry");
|
||||||
CATCH(errctx, sprite_load_json("assets/testsprite2.json"));
|
CATCH(errctx, akgl_sprite_load_json("assets/testsprite2.json"));
|
||||||
testsprite2 = SDL_GetPointerProperty(REGISTRY_SPRITE, "testsprite2", NULL);
|
testsprite2 = SDL_GetPointerProperty(AKGL_REGISTRY_SPRITE, "testsprite2", NULL);
|
||||||
FAIL_ZERO_BREAK(
|
FAIL_ZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
testsprite2,
|
testsprite2,
|
||||||
ERR_KEY,
|
AKERR_KEY,
|
||||||
"Sprite 2 loaded from json but not in registry");
|
"Sprite 2 loaded from json but not in registry");
|
||||||
CATCH(errctx, testchar->sprite_add(testchar, testsprite, ACTOR_STATE_ALIVE));
|
CATCH(errctx, testchar->sprite_add(testchar, testsprite, AKGL_ACTOR_STATE_ALIVE));
|
||||||
CATCH(errctx, testchar->sprite_add(testchar, testsprite2, ACTOR_STATE_DEAD));
|
CATCH(errctx, testchar->sprite_add(testchar, testsprite2, AKGL_ACTOR_STATE_DEAD));
|
||||||
|
|
||||||
SDL_EnumerateProperties(testchar->state_sprites, &character_state_sprites_iterate, &opflags);
|
SDL_EnumerateProperties(testchar->state_sprites, &akgl_character_state_sprites_iterate, &opflags);
|
||||||
|
|
||||||
// This is called by heap_release_character so we should assume that our property map is being
|
// This is called by akgl_heap_release_character so we should assume that our property map is being
|
||||||
// deleted soon after this. So we don't care if the sprites have been deleted from the sprite_states.
|
// deleted soon after this. So we don't care if the sprites have been deleted from the sprite_states.
|
||||||
// We just want to know they've been released.
|
// We just want to know they've been released.
|
||||||
FAIL_NONZERO_BREAK(
|
FAIL_NONZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
(testsprite->refcount > 1),
|
(testsprite->refcount > 1),
|
||||||
ERR_VALUE,
|
AKERR_VALUE,
|
||||||
"heap_release_sprite not called for testsprite from iterator");
|
"akgl_heap_release_sprite not called for testsprite from iterator");
|
||||||
FAIL_NONZERO_BREAK(
|
FAIL_NONZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
(testsprite2->refcount > 1),
|
(testsprite2->refcount > 1),
|
||||||
ERR_VALUE,
|
AKERR_VALUE,
|
||||||
"heap_release_sprite not called for testsprite from iterator");
|
"akgl_heap_release_sprite not called for testsprite from iterator");
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
IGNORE(heap_release_sprite(testsprite));
|
IGNORE(akgl_heap_release_sprite(testsprite));
|
||||||
IGNORE(heap_release_sprite(testsprite2));
|
IGNORE(akgl_heap_release_sprite(testsprite2));
|
||||||
IGNORE(heap_release_character(testchar));
|
IGNORE(akgl_heap_release_character(testchar));
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *test_character_load_json()
|
akerr_ErrorContext *test_akgl_character_load_json()
|
||||||
{
|
{
|
||||||
character *testcharacter = NULL;
|
akgl_Character *testcharacter = NULL;
|
||||||
sprite *testsprite = NULL;
|
akgl_Sprite *testsprite = NULL;
|
||||||
sprite *testsprite2 = NULL;
|
akgl_Sprite *testsprite2 = NULL;
|
||||||
sprite *comparesprite = NULL;
|
akgl_Sprite *comparesprite = NULL;
|
||||||
int tsrc = 0;
|
int tsrc = 0;
|
||||||
int tsrc2 = 0;
|
int tsrc2 = 0;
|
||||||
|
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, heap_next_character(&testcharacter));
|
CATCH(errctx, akgl_heap_next_character(&testcharacter));
|
||||||
CATCH(errctx, sprite_load_json("assets/testsprite.json"));
|
CATCH(errctx, akgl_sprite_load_json("assets/testsprite.json"));
|
||||||
testsprite = SDL_GetPointerProperty(REGISTRY_SPRITE, "testsprite", NULL);
|
testsprite = SDL_GetPointerProperty(AKGL_REGISTRY_SPRITE, "testsprite", NULL);
|
||||||
FAIL_ZERO_BREAK(
|
FAIL_ZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
testsprite,
|
testsprite,
|
||||||
ERR_KEY,
|
AKERR_KEY,
|
||||||
"Sprite loaded from json but not in registry");
|
"Sprite loaded from json but not in registry");
|
||||||
CATCH(errctx, sprite_load_json("assets/testsprite2.json"));
|
CATCH(errctx, akgl_sprite_load_json("assets/testsprite2.json"));
|
||||||
testsprite2 = SDL_GetPointerProperty(REGISTRY_SPRITE, "testsprite2", NULL);
|
testsprite2 = SDL_GetPointerProperty(AKGL_REGISTRY_SPRITE, "testsprite2", NULL);
|
||||||
FAIL_ZERO_BREAK(
|
FAIL_ZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
testsprite2,
|
testsprite2,
|
||||||
ERR_KEY,
|
AKERR_KEY,
|
||||||
"Sprite 2 loaded from json but not in registry");
|
"Sprite 2 loaded from json but not in registry");
|
||||||
|
|
||||||
CATCH(errctx, character_load_json("assets/testcharacter.json"));
|
CATCH(errctx, akgl_character_load_json("assets/testcharacter.json"));
|
||||||
testcharacter = SDL_GetPointerProperty(REGISTRY_CHARACTER, "testcharacter", NULL);
|
testcharacter = SDL_GetPointerProperty(AKGL_REGISTRY_CHARACTER, "testcharacter", NULL);
|
||||||
FAIL_ZERO_BREAK(
|
FAIL_ZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
testcharacter,
|
testcharacter,
|
||||||
ERR_KEY,
|
AKERR_KEY,
|
||||||
"Character loaded from json but not in registry");
|
"Character loaded from json but not in registry");
|
||||||
CATCH(errctx, testcharacter->sprite_get(testcharacter, (ACTOR_STATE_ALIVE | ACTOR_STATE_FACE_LEFT), &comparesprite));
|
CATCH(errctx, testcharacter->sprite_get(testcharacter, (AKGL_ACTOR_STATE_ALIVE | AKGL_ACTOR_STATE_FACE_LEFT), &comparesprite));
|
||||||
FAIL_ZERO_BREAK(errctx, (comparesprite == testsprite), ERR_VALUE, "Wrong sprite for state ACTOR_STATE_ALIVE");
|
FAIL_ZERO_BREAK(errctx, (comparesprite == testsprite), AKERR_VALUE, "Wrong sprite for state AKGL_ACTOR_STATE_ALIVE");
|
||||||
CATCH(errctx, testcharacter->sprite_get(testcharacter, ACTOR_STATE_DEAD, &comparesprite));
|
CATCH(errctx, testcharacter->sprite_get(testcharacter, AKGL_ACTOR_STATE_DEAD, &comparesprite));
|
||||||
FAIL_ZERO_BREAK(errctx, (comparesprite == testsprite2), ERR_VALUE, "Wrong sprite for state ACTOR_STATE_DEAD");
|
FAIL_ZERO_BREAK(errctx, (comparesprite == testsprite2), AKERR_VALUE, "Wrong sprite for state AKGL_ACTOR_STATE_DEAD");
|
||||||
|
|
||||||
FAIL_ZERO_BREAK(errctx, (testcharacter->vx != 0.200000003), ERR_VALUE, "Wrong X velocity for test character");
|
FAIL_ZERO_BREAK(errctx, (testcharacter->vx != 0.200000003), AKERR_VALUE, "Wrong X velocity for test character");
|
||||||
FAIL_ZERO_BREAK(errctx, (testcharacter->vy != 0.200000003), ERR_VALUE, "Wrong Y velocity for test character");
|
FAIL_ZERO_BREAK(errctx, (testcharacter->vy != 0.200000003), AKERR_VALUE, "Wrong Y velocity for test character");
|
||||||
|
|
||||||
// Release our handles on the sprites so the character's heap_release can reduce them to 0
|
// Release our handles on the sprites so the character's heap_release can reduce them to 0
|
||||||
CATCH(errctx, heap_release_sprite(testsprite));
|
CATCH(errctx, akgl_heap_release_sprite(testsprite));
|
||||||
CATCH(errctx, heap_release_sprite(testsprite2));
|
CATCH(errctx, akgl_heap_release_sprite(testsprite2));
|
||||||
tsrc = testsprite->refcount;
|
tsrc = testsprite->refcount;
|
||||||
tsrc2 = testsprite2->refcount;
|
tsrc2 = testsprite2->refcount;
|
||||||
CATCH(errctx, heap_release_character(testcharacter));
|
CATCH(errctx, akgl_heap_release_character(testcharacter));
|
||||||
FAIL_ZERO_BREAK(
|
FAIL_ZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
((testsprite->refcount < tsrc) || (testsprite2->refcount < tsrc2)),
|
((testsprite->refcount < tsrc) || (testsprite2->refcount < tsrc2)),
|
||||||
ERR_VALUE,
|
AKERR_VALUE,
|
||||||
"character did not reduce reference count of its child sprites when released");
|
"character did not reduce reference count of its child sprites when released");
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
@@ -195,19 +196,19 @@ int main(void)
|
|||||||
SDL_SetAppMetadata("SDL3-GameTest", "0.1", "net.aklabs.sdl3-gametest");
|
SDL_SetAppMetadata("SDL3-GameTest", "0.1", "net.aklabs.sdl3-gametest");
|
||||||
|
|
||||||
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO )) {
|
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO )) {
|
||||||
FAIL_BREAK(errctx, ERR_SDL, "Couldn't initialize SDL: %s", SDL_GetError());
|
FAIL_BREAK(errctx, AKGL_ERR_SDL, "Couldn't initialize SDL: %s", SDL_GetError());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SDL_CreateWindowAndRenderer("net/aklabs/libsdl3game/test_character", 640, 480, SDL_WINDOW_HIDDEN, &window, &renderer)) {
|
if (!SDL_CreateWindowAndRenderer("net/aklabs/libakgl/test_character", 640, 480, SDL_WINDOW_HIDDEN, &window, &renderer)) {
|
||||||
FAIL_BREAK(errctx, ERR_SDL, "Couldn't create window/renderer: %s", SDL_GetError());
|
FAIL_BREAK(errctx, AKGL_ERR_SDL, "Couldn't create window/renderer: %s", SDL_GetError());
|
||||||
}
|
}
|
||||||
|
|
||||||
CATCH(errctx, heap_init());
|
CATCH(errctx, akgl_heap_init());
|
||||||
CATCH(errctx, registry_init());
|
CATCH(errctx, akgl_registry_init());
|
||||||
CATCH(errctx, test_character_initialize());
|
CATCH(errctx, test_akgl_character_initialize());
|
||||||
CATCH(errctx, test_character_sprite_mgmt());
|
CATCH(errctx, test_character_sprite_mgmt());
|
||||||
CATCH(errctx, test_character_iterate_state_sprites());
|
CATCH(errctx, test_character_iterate_state_sprites());
|
||||||
CATCH(errctx, test_character_load_json());
|
CATCH(errctx, test_akgl_character_load_json());
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH_NORETURN(errctx);
|
} FINISH_NORETURN(errctx);
|
||||||
|
|||||||
125
tests/charviewer.c
Normal file
125
tests/charviewer.c
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
#include <SDL3/SDL.h>
|
||||||
|
#include <SDL3/SDL_main.h>
|
||||||
|
#include <SDL3/SDL_properties.h>
|
||||||
|
#include <SDL3_image/SDL_image.h>
|
||||||
|
#include <SDL3_mixer/SDL_mixer.h>
|
||||||
|
|
||||||
|
#include <akerror.h>
|
||||||
|
#include <akgl/assets.h>
|
||||||
|
#include <akgl/iterator.h>
|
||||||
|
#include <akgl/tilemap.h>
|
||||||
|
#include <akgl/heap.h>
|
||||||
|
#include <akgl/game.h>
|
||||||
|
#include <akgl/controller.h>
|
||||||
|
#include <akgl/draw.h>
|
||||||
|
#include <akgl/sprite.h>
|
||||||
|
#include <akgl/actor.h>
|
||||||
|
#include <akgl/registry.h>
|
||||||
|
#include <akgl/error.h>
|
||||||
|
|
||||||
|
int numsprites = 8;
|
||||||
|
char *spritepaths[] = {
|
||||||
|
"assets/sprites/little_guy_walking_left.json",
|
||||||
|
"assets/sprites/little_guy_walking_right.json",
|
||||||
|
"assets/sprites/little_guy_walking_up.json",
|
||||||
|
"assets/sprites/little_guy_walking_down.json",
|
||||||
|
"assets/sprites/little_guy_facing_left.json",
|
||||||
|
"assets/sprites/little_guy_facing_right.json",
|
||||||
|
"assets/sprites/little_guy_facing_up.json",
|
||||||
|
"assets/sprites/little_guy_facing_down.json"
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
PREPARE_ERROR(errctx);
|
||||||
|
SDL3GControlMap *controlmap;
|
||||||
|
actor *actorptr = NULL;
|
||||||
|
|
||||||
|
ATTEMPT {
|
||||||
|
|
||||||
|
SDL_SetAppMetadata("SDL3-GameTest", "0.1", "net.aklabs.sdl3-gametest");
|
||||||
|
|
||||||
|
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO )) {
|
||||||
|
FAIL_BREAK(errctx, AKGL_ERR_SDL, "Couldn't initialize SDL: %s", SDL_GetError());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SDL_CreateWindowAndRenderer("net/aklabs/libakgl/test_sprite", 640, 480, 0, &window, &renderer)) {
|
||||||
|
FAIL_BREAK(errctx, AKGL_ERR_SDL, "Couldn't create window/renderer: %s", SDL_GetError());
|
||||||
|
}
|
||||||
|
|
||||||
|
CATCH(errctx, akgl_heap_init());
|
||||||
|
CATCH(errctx, akgl_registry_init());
|
||||||
|
|
||||||
|
strcpy((char *)&game.name, "charviewer");
|
||||||
|
strcpy((char *)&game.version, "0.0.1");
|
||||||
|
strcpy((char *)&game.uri, "net.aklabs.libakgl.charviewer");
|
||||||
|
game.screenwidth = 640;
|
||||||
|
game.screenheight = 480;
|
||||||
|
|
||||||
|
CATCH(errctx, akgl_GAME_init());
|
||||||
|
|
||||||
|
for ( int i = 0; i < numsprites ; i++) {
|
||||||
|
CATCH(errctx, akgl_sprite_load_json(spritepaths[i]));
|
||||||
|
}
|
||||||
|
CATCH(errctx, akgl_character_load_json("assets/characters/littleguy.json"));
|
||||||
|
CATCH(errctx, akgl_heap_next_actor(&actorptr));
|
||||||
|
CATCH(errctx, akgl_actor_initialize((actor *)actorptr, "player"));
|
||||||
|
actorptr->basechar = SDL_GetPointerProperty(
|
||||||
|
AKGL_REGISTRY_CHARACTER,
|
||||||
|
"little guy",
|
||||||
|
NULL);
|
||||||
|
FAIL_ZERO_BREAK(errctx, actorptr->basechar, AKERR_REGISTRY, "Can't load character 'little guy' from the registry");
|
||||||
|
actorptr->movement_controls_face = false;
|
||||||
|
actorptr->state = (AKGL_ACTOR_STATE_ALIVE | AKGL_ACTOR_STATE_FACE_LEFT);
|
||||||
|
actorptr->x = 320;
|
||||||
|
actorptr->y = 240;
|
||||||
|
actorptr->visible = true;
|
||||||
|
|
||||||
|
// set up the control map
|
||||||
|
controlmap = &GAME_ControlMaps[0];
|
||||||
|
controlmap->kbid = 0;
|
||||||
|
controlmap->target = SDL_GetPointerProperty(AKGL_REGISTRY_ACTOR, "player", NULL);
|
||||||
|
// Move down
|
||||||
|
controlmap->controls[0].key = SDLK_DOWN;
|
||||||
|
//controlmap->controls[0].target_state_gate = AKGL_ACTOR_STATE_MOVING_DOWN;
|
||||||
|
controlmap->controls[0].target_add_state_on = AKGL_ACTOR_STATE_MOVING_DOWN | AKGL_ACTOR_STATE_FACE_DOWN;
|
||||||
|
controlmap->controls[0].target_del_state_on = AKGL_ACTOR_STATE_MOVING_UP | AKGL_ACTOR_STATE_FACE_ALL;
|
||||||
|
controlmap->controls[0].target_del_state_off = AKGL_ACTOR_STATE_MOVING_DOWN;
|
||||||
|
controlmap->controls[0].event_on = SDL_EVENT_KEY_DOWN;
|
||||||
|
controlmap->controls[0].event_off = SDL_EVENT_KEY_UP;
|
||||||
|
|
||||||
|
// Move up
|
||||||
|
controlmap->controls[1].key = SDLK_UP;
|
||||||
|
//controlmap->controls[1].target_state_gate = AKGL_ACTOR_STATE_MOVING_UP;
|
||||||
|
controlmap->controls[1].target_add_state_on = AKGL_ACTOR_STATE_MOVING_UP | AKGL_ACTOR_STATE_FACE_UP;
|
||||||
|
controlmap->controls[1].target_del_state_on = AKGL_ACTOR_STATE_MOVING_DOWN | AKGL_ACTOR_STATE_FACE_ALL;
|
||||||
|
controlmap->controls[1].target_del_state_off = AKGL_ACTOR_STATE_MOVING_UP;
|
||||||
|
controlmap->controls[1].event_on = SDL_EVENT_KEY_DOWN;
|
||||||
|
controlmap->controls[1].event_off = SDL_EVENT_KEY_UP;
|
||||||
|
|
||||||
|
// Move left
|
||||||
|
controlmap->controls[2].key = SDLK_LEFT;
|
||||||
|
//controlmap->controls[2].target_state_gate = AKGL_ACTOR_STATE_MOVING_LEFT;
|
||||||
|
controlmap->controls[2].target_add_state_on = AKGL_ACTOR_STATE_MOVING_LEFT | AKGL_ACTOR_STATE_FACE_LEFT;
|
||||||
|
controlmap->controls[2].target_del_state_on = AKGL_ACTOR_STATE_MOVING_RIGHT | AKGL_ACTOR_STATE_FACE_ALL;
|
||||||
|
controlmap->controls[2].target_del_state_off = AKGL_ACTOR_STATE_MOVING_LEFT;
|
||||||
|
controlmap->controls[2].event_on = SDL_EVENT_KEY_DOWN;
|
||||||
|
controlmap->controls[2].event_off = SDL_EVENT_KEY_UP;
|
||||||
|
|
||||||
|
// Move right
|
||||||
|
controlmap->controls[3].key = SDLK_RIGHT;
|
||||||
|
//controlmap->controls[3].target_state_gate = AKGL_ACTOR_STATE_MOVING_RIGHT;
|
||||||
|
controlmap->controls[3].target_add_state_on = AKGL_ACTOR_STATE_MOVING_RIGHT | AKGL_ACTOR_STATE_FACE_RIGHT;
|
||||||
|
controlmap->controls[3].target_del_state_on = AKGL_ACTOR_STATE_MOVING_LEFT | AKGL_ACTOR_STATE_FACE_ALL;
|
||||||
|
controlmap->controls[3].target_del_state_off = AKGL_ACTOR_STATE_MOVING_RIGHT;
|
||||||
|
controlmap->controls[3].event_on = SDL_EVENT_KEY_DOWN;
|
||||||
|
controlmap->controls[3].event_off = SDL_EVENT_KEY_UP;
|
||||||
|
} CLEANUP {
|
||||||
|
} PROCESS(errctx) {
|
||||||
|
} HANDLE_DEFAULT(errctx) {
|
||||||
|
LOG_ERROR(errctx);
|
||||||
|
return 1;
|
||||||
|
} FINISH_NORETURN(errctx);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sdlerror.h>
|
#include <akerror.h>
|
||||||
#include <sdl3game/registry.h>
|
#include <akgl/registry.h>
|
||||||
|
|
||||||
typedef ErrorContext *(*RegistryFuncPtr)(void);
|
typedef akerr_ErrorContext *(*RegistryFuncPtr)(void);
|
||||||
|
|
||||||
void *sdl_calloc_always_fails(size_t a, size_t b)
|
void *sdl_calloc_always_fails(size_t a, size_t b)
|
||||||
{
|
{
|
||||||
@@ -11,7 +11,7 @@ void *sdl_calloc_always_fails(size_t a, size_t b)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *test_registry_init(RegistryFuncPtr funcptr)
|
akerr_ErrorContext *test_akgl_registry_init(RegistryFuncPtr funcptr)
|
||||||
{
|
{
|
||||||
SDL_malloc_func malloc_func;
|
SDL_malloc_func malloc_func;
|
||||||
SDL_calloc_func calloc_func;
|
SDL_calloc_func calloc_func;
|
||||||
@@ -43,41 +43,41 @@ ErrorContext *test_registry_init(RegistryFuncPtr funcptr)
|
|||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
|
|
||||||
FAIL_RETURN(errctx, ERR_BEHAVIOR, "SDL memory allocator fails but registry reports successful property creation");
|
FAIL_RETURN(errctx, AKERR_BEHAVIOR, "SDL memory allocator fails but registry reports successful property creation");
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *test_registry_init_creation_failures(void)
|
akerr_ErrorContext *test_akgl_registry_init_creation_failures(void)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, test_registry_init(®istry_init_actor));
|
CATCH(errctx, test_akgl_registry_init(&akgl_registry_init_actor));
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} HANDLE(errctx, ERR_NULLPOINTER) {
|
} HANDLE(errctx, AKERR_NULLPOINTER) {
|
||||||
printf("Sucess\n");
|
printf("Sucess\n");
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, test_registry_init(®istry_init_sprite));
|
CATCH(errctx, test_akgl_registry_init(&akgl_registry_init_sprite));
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} HANDLE(errctx, ERR_NULLPOINTER) {
|
} HANDLE(errctx, AKERR_NULLPOINTER) {
|
||||||
printf("Sucess\n");
|
printf("Sucess\n");
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, test_registry_init(®istry_init_spritesheet));
|
CATCH(errctx, test_akgl_registry_init(&akgl_registry_init_spritesheet));
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} HANDLE(errctx, ERR_NULLPOINTER) {
|
} HANDLE(errctx, AKERR_NULLPOINTER) {
|
||||||
printf("Sucess\n");
|
printf("Sucess\n");
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, test_registry_init(®istry_init_character));
|
CATCH(errctx, test_akgl_registry_init(&akgl_registry_init_character));
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} HANDLE(errctx, ERR_NULLPOINTER) {
|
} HANDLE(errctx, AKERR_NULLPOINTER) {
|
||||||
printf("Sucess\n");
|
printf("Sucess\n");
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
@@ -87,7 +87,7 @@ int main(void)
|
|||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, test_registry_init_creation_failures());
|
CATCH(errctx, test_akgl_registry_init_creation_failures());
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH_NORETURN(errctx);
|
} FINISH_NORETURN(errctx);
|
||||||
|
|||||||
155
tests/sprite.c
155
tests/sprite.c
@@ -3,45 +3,46 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sdlerror.h>
|
#include <akerror.h>
|
||||||
|
|
||||||
#include <sdl3game/registry.h>
|
#include <akgl/registry.h>
|
||||||
#include <sdl3game/sprite.h>
|
#include <akgl/sprite.h>
|
||||||
#include <sdl3game/heap.h>
|
#include <akgl/heap.h>
|
||||||
#include <sdl3game/util.h>
|
#include <akgl/util.h>
|
||||||
|
#include <akgl/error.h>
|
||||||
|
|
||||||
SDL_Window *window;
|
SDL_Window *window;
|
||||||
SDL_Renderer *renderer;
|
SDL_Renderer *renderer;
|
||||||
|
|
||||||
ErrorContext *test_spritesheet_initialize(void)
|
akerr_ErrorContext *test_akgl_spritesheet_initialize(void)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
spritesheet *sheet = NULL;
|
akgl_SpriteSheet *sheet = NULL;
|
||||||
SDL_Texture *image = NULL;
|
SDL_Texture *image = NULL;
|
||||||
string *tmpstr = NULL;
|
akgl_String *tmpstr = NULL;
|
||||||
// Does the image file get loaded?
|
// Does the image file get loaded?
|
||||||
// Is the image file loaded correctly? (Surface comparison)
|
// Is the image file loaded correctly? (Surface comparison)
|
||||||
// Is the spritesheet in the registry?
|
// Is the spritesheet in the registry?
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, heap_next_spritesheet(&sheet));
|
CATCH(errctx, akgl_heap_next_spritesheet(&sheet));
|
||||||
CATCH(errctx, heap_next_string(&tmpstr));
|
CATCH(errctx, akgl_heap_next_string(&tmpstr));
|
||||||
|
|
||||||
snprintf((char *)&tmpstr->data, MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), "assets/spritesheet.png");
|
snprintf((char *)&tmpstr->data, AKGL_MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), "assets/spritesheet.png");
|
||||||
CATCH(errctx, spritesheet_initialize(sheet, 48, 48, "assets/spritesheet.png"));
|
CATCH(errctx, akgl_spritesheet_initialize(sheet, 48, 48, "assets/spritesheet.png"));
|
||||||
FAIL_ZERO_BREAK(errctx, sheet->texture, ERR_VALUE, "spritesheet_initialize failed to load the sprite texture");
|
FAIL_ZERO_BREAK(errctx, sheet->texture, AKERR_VALUE, "akgl_spritesheet_initialize failed to load the sprite texture");
|
||||||
FAIL_NONZERO_BREAK(
|
FAIL_NONZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
((sheet->texture->w != 576) || (sheet->texture->h != 384)),
|
((sheet->texture->w != 576) || (sheet->texture->h != 384)),
|
||||||
ERR_VALUE,
|
AKERR_VALUE,
|
||||||
"Loaded texture was not the correct size");
|
"Loaded texture was not the correct size");
|
||||||
|
|
||||||
snprintf((char *)&tmpstr->data, MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), "assets/spritesheet.png");
|
snprintf((char *)&tmpstr->data, AKGL_MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), "assets/spritesheet.png");
|
||||||
image = IMG_LoadTexture(renderer, (char *)&tmpstr->data);
|
image = IMG_LoadTexture(renderer, (char *)&tmpstr->data);
|
||||||
FAIL_ZERO_BREAK(errctx, image, ERR_SDL, "Failed to load comparison image");
|
FAIL_ZERO_BREAK(errctx, image, AKGL_ERR_SDL, "Failed to load comparison image");
|
||||||
|
|
||||||
CATCH(
|
CATCH(
|
||||||
errctx,
|
errctx,
|
||||||
render_and_compare(
|
akgl_render_and_compare(
|
||||||
sheet->texture,
|
sheet->texture,
|
||||||
image,
|
image,
|
||||||
0, 0, 576, 384,
|
0, 0, 576, 384,
|
||||||
@@ -50,13 +51,13 @@ ErrorContext *test_spritesheet_initialize(void)
|
|||||||
|
|
||||||
FAIL_ZERO_BREAK(
|
FAIL_ZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
SDL_GetPointerProperty(REGISTRY_SPRITESHEET, "assets/spritesheet.png", NULL),
|
SDL_GetPointerProperty(AKGL_REGISTRY_SPRITESHEET, "assets/spritesheet.png", NULL),
|
||||||
ERR_KEY,
|
AKERR_KEY,
|
||||||
"Spritesheet was not placed in the registry");
|
"Spritesheet was not placed in the registry");
|
||||||
|
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
IGNORE(heap_release_string(tmpstr));
|
IGNORE(akgl_heap_release_string(tmpstr));
|
||||||
IGNORE(heap_release_spritesheet(sheet));
|
IGNORE(akgl_heap_release_spritesheet(sheet));
|
||||||
if ( image != NULL )
|
if ( image != NULL )
|
||||||
SDL_DestroyTexture(image);
|
SDL_DestroyTexture(image);
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
@@ -64,48 +65,48 @@ ErrorContext *test_spritesheet_initialize(void)
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *test_sprite_initialize(void)
|
akerr_ErrorContext *test_akgl_sprite_initialize(void)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
spritesheet *testsheet = NULL;
|
akgl_SpriteSheet *testsheet = NULL;
|
||||||
sprite *testsprite = NULL;
|
akgl_Sprite *testsprite = NULL;
|
||||||
string *tmpstr = NULL;
|
akgl_String *tmpstr = NULL;
|
||||||
|
|
||||||
// Does the sprite get loaded?
|
// Does the sprite get loaded?
|
||||||
// Do all frames of the sprite get loaded?
|
// Do all frames of the sprite get loaded?
|
||||||
// Are all the frames of the sprite what we expect? (Surface comparison)
|
// Are all the frames of the sprite what we expect? (Surface comparison)
|
||||||
// Is the sprite added to the registry?
|
// Is the sprite added to the registry?
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, heap_next_spritesheet(&testsheet));
|
CATCH(errctx, akgl_heap_next_spritesheet(&testsheet));
|
||||||
CATCH(errctx, heap_next_sprite(&testsprite));
|
CATCH(errctx, akgl_heap_next_sprite(&testsprite));
|
||||||
CATCH(errctx, heap_next_string(&tmpstr));
|
CATCH(errctx, akgl_heap_next_string(&tmpstr));
|
||||||
|
|
||||||
snprintf((char *)&tmpstr->data, MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), "assets/spritesheet.png");
|
snprintf((char *)&tmpstr->data, AKGL_MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), "assets/spritesheet.png");
|
||||||
CATCH(errctx, spritesheet_initialize(testsheet, 48, 48, "assets/spritesheet.png"));
|
CATCH(errctx, akgl_spritesheet_initialize(testsheet, 48, 48, "assets/spritesheet.png"));
|
||||||
FAIL_ZERO_BREAK(errctx, testsheet, ERR_VALUE, "spritesheet_initialize failed");
|
FAIL_ZERO_BREAK(errctx, testsheet, AKERR_VALUE, "akgl_spritesheet_initialize failed");
|
||||||
|
|
||||||
CATCH(errctx, sprite_initialize(testsprite, "test", testsheet));
|
CATCH(errctx, akgl_sprite_initialize(testsprite, "test", testsheet));
|
||||||
FAIL_NONZERO_BREAK(errctx, (testsprite->sheet != testsheet), ERR_VALUE, "Initialized sprite uses wrong sheet");
|
FAIL_NONZERO_BREAK(errctx, (testsprite->sheet != testsheet), AKERR_VALUE, "Initialized sprite uses wrong sheet");
|
||||||
FAIL_ZERO_BREAK(
|
FAIL_ZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
SDL_GetPointerProperty(REGISTRY_SPRITE, "test", NULL),
|
SDL_GetPointerProperty(AKGL_REGISTRY_SPRITE, "test", NULL),
|
||||||
ERR_KEY,
|
AKERR_KEY,
|
||||||
"Sprite was not placed in the registry");
|
"Sprite was not placed in the registry");
|
||||||
|
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
IGNORE(heap_release_sprite(testsprite));
|
IGNORE(akgl_heap_release_sprite(testsprite));
|
||||||
IGNORE(heap_release_string(tmpstr));
|
IGNORE(akgl_heap_release_string(tmpstr));
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *test_sprite_load_json(void)
|
akerr_ErrorContext *test_akgl_sprite_load_json(void)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
sprite *testsprite = NULL;
|
akgl_Sprite *testsprite = NULL;
|
||||||
sprite *testsprite2 = NULL;
|
akgl_Sprite *testsprite2 = NULL;
|
||||||
string *tmpstr = NULL;
|
akgl_String *tmpstr = NULL;
|
||||||
SDL_Texture *image = NULL;
|
SDL_Texture *image = NULL;
|
||||||
|
|
||||||
// Does the sprite get loaded?
|
// Does the sprite get loaded?
|
||||||
@@ -113,36 +114,36 @@ ErrorContext *test_sprite_load_json(void)
|
|||||||
// Are all the frames of the sprite what we expect? (Surface comparison)
|
// Are all the frames of the sprite what we expect? (Surface comparison)
|
||||||
// Is the sprite added to the registry?
|
// Is the sprite added to the registry?
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, heap_next_string(&tmpstr));
|
CATCH(errctx, akgl_heap_next_string(&tmpstr));
|
||||||
|
|
||||||
CATCH(errctx, sprite_load_json("assets/testsprite.json"));
|
CATCH(errctx, akgl_sprite_load_json("assets/testsprite.json"));
|
||||||
testsprite = SDL_GetPointerProperty(REGISTRY_SPRITE, "testsprite", NULL);
|
testsprite = SDL_GetPointerProperty(AKGL_REGISTRY_SPRITE, "testsprite", NULL);
|
||||||
FAIL_ZERO_BREAK(
|
FAIL_ZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
testsprite,
|
testsprite,
|
||||||
ERR_KEY,
|
AKERR_KEY,
|
||||||
"sprite_load_json succeeds but sprite is not placed in the registry");
|
"akgl_sprite_load_json succeeds but sprite is not placed in the registry");
|
||||||
|
|
||||||
FAIL_ZERO_BREAK(errctx, (testsprite->width == 48), ERR_VALUE, "width incorrect (48 : %d)", testsprite->width);
|
FAIL_ZERO_BREAK(errctx, (testsprite->width == 48), AKERR_VALUE, "width incorrect (48 : %d)", testsprite->width);
|
||||||
FAIL_ZERO_BREAK(errctx, (testsprite->height == 48), ERR_VALUE, "height incorrect (48 : %d)", testsprite->height);
|
FAIL_ZERO_BREAK(errctx, (testsprite->height == 48), AKERR_VALUE, "height incorrect (48 : %d)", testsprite->height);
|
||||||
FAIL_ZERO_BREAK(errctx, (testsprite->speed == 100), ERR_VALUE, "speed incorrect (100 : %d)", testsprite->speed);
|
FAIL_ZERO_BREAK(errctx, (testsprite->speed == 100000000), AKERR_VALUE, "speed incorrect (100 : %d)", testsprite->speed);
|
||||||
FAIL_ZERO_BREAK(errctx, (testsprite->loop == true), ERR_VALUE, "loop incorrect (1 : %d)", testsprite->loop);
|
FAIL_ZERO_BREAK(errctx, (testsprite->loop == true), AKERR_VALUE, "loop incorrect (1 : %d)", testsprite->loop);
|
||||||
FAIL_ZERO_BREAK(errctx, (testsprite->loopReverse == true), ERR_VALUE, "loopReverse incorrect (1 : %d)", testsprite->loopReverse);
|
FAIL_ZERO_BREAK(errctx, (testsprite->loopReverse == true), AKERR_VALUE, "loopReverse incorrect (1 : %d)", testsprite->loopReverse);
|
||||||
FAIL_ZERO_BREAK(errctx, (testsprite->frames == 3), ERR_VALUE, "frame count incorrect (3 : %d)", testsprite->frames);
|
FAIL_ZERO_BREAK(errctx, (testsprite->frames == 3), AKERR_VALUE, "frame count incorrect (3 : %d)", testsprite->frames);
|
||||||
FAIL_ZERO_BREAK(errctx, (testsprite->frameids[0] == 12), ERR_VALUE, "frameids[0] incorrect (12 : %d)", testsprite->frameids[0]);
|
FAIL_ZERO_BREAK(errctx, (testsprite->frameids[0] == 12), AKERR_VALUE, "frameids[0] incorrect (12 : %d)", testsprite->frameids[0]);
|
||||||
FAIL_ZERO_BREAK(errctx, (testsprite->frameids[1] == 13), ERR_VALUE, "frameids[1] incorrect (13 : %d)", testsprite->frameids[1]);
|
FAIL_ZERO_BREAK(errctx, (testsprite->frameids[1] == 13), AKERR_VALUE, "frameids[1] incorrect (13 : %d)", testsprite->frameids[1]);
|
||||||
FAIL_ZERO_BREAK(errctx, (testsprite->frameids[2] == 14), ERR_VALUE, "frameids[2] incorrect (14 : %d)", testsprite->frameids[2]);
|
FAIL_ZERO_BREAK(errctx, (testsprite->frameids[2] == 14), AKERR_VALUE, "frameids[2] incorrect (14 : %d)", testsprite->frameids[2]);
|
||||||
FAIL_NONZERO_BREAK(errctx, strcmp(testsprite->name, "testsprite"), ERR_VALUE, "name incorrect (testsprite : %s)", (char *)testsprite->name);
|
FAIL_NONZERO_BREAK(errctx, strcmp(testsprite->name, "testsprite"), AKERR_VALUE, "name incorrect (testsprite : %s)", (char *)testsprite->name);
|
||||||
|
|
||||||
// Is it using the right spritesheet?
|
// Is it using the right spritesheet?
|
||||||
|
|
||||||
snprintf((char *)&tmpstr->data, MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), "assets/spritesheet.png");
|
snprintf((char *)&tmpstr->data, AKGL_MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), "assets/spritesheet.png");
|
||||||
image = IMG_LoadTexture(renderer, (char *)&tmpstr->data);
|
image = IMG_LoadTexture(renderer, (char *)&tmpstr->data);
|
||||||
FAIL_ZERO_BREAK(errctx, image, ERR_SDL, "Failed to load comparison image");
|
FAIL_ZERO_BREAK(errctx, image, AKGL_ERR_SDL, "Failed to load comparison image");
|
||||||
|
|
||||||
CATCH(
|
CATCH(
|
||||||
errctx,
|
errctx,
|
||||||
render_and_compare(
|
akgl_render_and_compare(
|
||||||
testsprite->sheet->texture,
|
testsprite->sheet->texture,
|
||||||
image,
|
image,
|
||||||
0, 0, 576, 384,
|
0, 0, 576, 384,
|
||||||
@@ -151,29 +152,29 @@ ErrorContext *test_sprite_load_json(void)
|
|||||||
);
|
);
|
||||||
|
|
||||||
// If we load a second sprite using the same sheet name, do they use the same sheet in memory?
|
// If we load a second sprite using the same sheet name, do they use the same sheet in memory?
|
||||||
snprintf((char *)&tmpstr->data, MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), "assets/testsprite2.json");
|
snprintf((char *)&tmpstr->data, AKGL_MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), "assets/testsprite2.json");
|
||||||
CATCH(errctx, sprite_load_json("assets/testsprite2.json"));
|
CATCH(errctx, akgl_sprite_load_json("assets/testsprite2.json"));
|
||||||
testsprite2 = SDL_GetPointerProperty(REGISTRY_SPRITE, "testsprite2", NULL);
|
testsprite2 = SDL_GetPointerProperty(AKGL_REGISTRY_SPRITE, "testsprite2", NULL);
|
||||||
FAIL_ZERO_BREAK(
|
FAIL_ZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
testsprite,
|
testsprite,
|
||||||
ERR_KEY,
|
AKERR_KEY,
|
||||||
"sprite_load_json succeeds but second sprite is not placed in the registry");
|
"akgl_sprite_load_json succeeds but second sprite is not placed in the registry");
|
||||||
|
|
||||||
FAIL_ZERO_BREAK(
|
FAIL_ZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
(testsprite->sheet == testsprite2->sheet),
|
(testsprite->sheet == testsprite2->sheet),
|
||||||
ERR_VALUE,
|
AKERR_VALUE,
|
||||||
"Previously loaded spritesheets are not reused");
|
"Previously loaded spritesheets are not reused");
|
||||||
|
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
if ( testsprite != NULL ) {
|
if ( testsprite != NULL ) {
|
||||||
IGNORE(heap_release_sprite(testsprite));
|
IGNORE(akgl_heap_release_sprite(testsprite));
|
||||||
}
|
}
|
||||||
if ( testsprite2 != NULL ) {
|
if ( testsprite2 != NULL ) {
|
||||||
IGNORE(heap_release_sprite(testsprite2));
|
IGNORE(akgl_heap_release_sprite(testsprite2));
|
||||||
}
|
}
|
||||||
IGNORE(heap_release_string(tmpstr));
|
IGNORE(akgl_heap_release_string(tmpstr));
|
||||||
if ( image != NULL )
|
if ( image != NULL )
|
||||||
SDL_DestroyTexture(image);
|
SDL_DestroyTexture(image);
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
@@ -190,20 +191,20 @@ int main(void)
|
|||||||
SDL_SetAppMetadata("SDL3-GameTest", "0.1", "net.aklabs.sdl3-gametest");
|
SDL_SetAppMetadata("SDL3-GameTest", "0.1", "net.aklabs.sdl3-gametest");
|
||||||
|
|
||||||
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO )) {
|
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO )) {
|
||||||
FAIL_BREAK(errctx, ERR_SDL, "Couldn't initialize SDL: %s", SDL_GetError());
|
FAIL_BREAK(errctx, AKGL_ERR_SDL, "Couldn't initialize SDL: %s", SDL_GetError());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SDL_CreateWindowAndRenderer("net/aklabs/libsdl3game/test_sprite", 640, 480, 0, &window, &renderer)) {
|
if (!SDL_CreateWindowAndRenderer("net/aklabs/libakgl/test_sprite", 640, 480, 0, &window, &renderer)) {
|
||||||
FAIL_BREAK(errctx, ERR_SDL, "Couldn't create window/renderer: %s", SDL_GetError());
|
FAIL_BREAK(errctx, AKGL_ERR_SDL, "Couldn't create window/renderer: %s", SDL_GetError());
|
||||||
}
|
}
|
||||||
|
|
||||||
CATCH(errctx, heap_init());
|
CATCH(errctx, akgl_heap_init());
|
||||||
CATCH(errctx, registry_init_sprite());
|
CATCH(errctx, akgl_registry_init_sprite());
|
||||||
CATCH(errctx, registry_init_spritesheet());
|
CATCH(errctx, akgl_registry_init_spritesheet());
|
||||||
|
|
||||||
CATCH(errctx, test_spritesheet_initialize());
|
CATCH(errctx, test_akgl_spritesheet_initialize());
|
||||||
CATCH(errctx, test_sprite_initialize());
|
CATCH(errctx, test_akgl_sprite_initialize());
|
||||||
CATCH(errctx, test_sprite_load_json());
|
CATCH(errctx, test_akgl_sprite_load_json());
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH_NORETURN(errctx);
|
} FINISH_NORETURN(errctx);
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sdlerror.h>
|
#include <akerror.h>
|
||||||
#include <sdl3game/heap.h>
|
#include <akgl/heap.h>
|
||||||
#include <sdl3game/staticstring.h>
|
#include <akgl/staticstring.h>
|
||||||
|
|
||||||
void reset_string_heap(void);
|
void reset_string_heap(void);
|
||||||
|
|
||||||
ErrorContext *test_fresh_heap_gives_strings(void)
|
akerr_ErrorContext *test_fresh_heap_gives_strings(void)
|
||||||
{
|
{
|
||||||
string *ptr = NULL;
|
akgl_String *ptr = NULL;
|
||||||
|
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
for ( int i = 0; i < MAX_HEAP_STRING - 1; i++ ) {
|
for ( int i = 0; i < AKGL_MAX_HEAP_STRING - 1; i++ ) {
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, heap_next_string(&ptr));
|
CATCH(errctx, akgl_heap_next_string(&ptr));
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
reset_string_heap();
|
reset_string_heap();
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
@@ -22,73 +22,73 @@ ErrorContext *test_fresh_heap_gives_strings(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *test_string_heap_error_when_no_strings_left(void)
|
akerr_ErrorContext *test_string_heap_error_when_no_strings_left(void)
|
||||||
{
|
{
|
||||||
string *ptr;
|
akgl_String *ptr;
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
for ( int i = 0; i < MAX_HEAP_STRING; i++ ) {
|
for ( int i = 0; i < AKGL_MAX_HEAP_STRING; i++ ) {
|
||||||
HEAP_STRING[i].refcount = 1;
|
HEAP_STRING[i].refcount = 1;
|
||||||
}
|
}
|
||||||
for ( int i = 0; i < MAX_HEAP_STRING - 1; i++ ) {
|
for ( int i = 0; i < AKGL_MAX_HEAP_STRING - 1; i++ ) {
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, heap_next_string(&ptr));
|
CATCH(errctx, akgl_heap_next_string(&ptr));
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} HANDLE(errctx, ERR_NULLPOINTER) {
|
} HANDLE(errctx, AKERR_NULLPOINTER) {
|
||||||
return 0;
|
return 0;
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
}
|
}
|
||||||
FAIL_RETURN(errctx, ERR_OUTOFBOUNDS, "Expected ERR_NULLPOINTER when accessing beyond string heap bounds");
|
FAIL_RETURN(errctx, AKERR_OUTOFBOUNDS, "Expected AKERR_NULLPOINTER when accessing beyond string heap bounds");
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *test_string_heap_honors_refcount(void)
|
akerr_ErrorContext *test_string_heap_honors_refcount(void)
|
||||||
{
|
{
|
||||||
string *firstptr = &HEAP_STRING[0];
|
akgl_String *firstptr = &HEAP_STRING[0];
|
||||||
string *secondptr = &HEAP_STRING[1];
|
akgl_String *secondptr = &HEAP_STRING[1];
|
||||||
string *testptr = NULL;
|
akgl_String *testptr = NULL;
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, heap_next_string(&testptr));
|
CATCH(errctx, akgl_heap_next_string(&testptr));
|
||||||
if ( testptr != firstptr ) {
|
if ( testptr != firstptr ) {
|
||||||
FAIL_RETURN(
|
FAIL_RETURN(
|
||||||
errctx,
|
errctx,
|
||||||
ERR_VALUE,
|
AKERR_VALUE,
|
||||||
"Expected testptr to equal (HEAP_STRING[0] = %p) but got %p",
|
"Expected testptr to equal (HEAP_STRING[0] = %p) but got %p",
|
||||||
firstptr,
|
firstptr,
|
||||||
testptr
|
testptr
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
CATCH(errctx, string_initialize(testptr, NULL));
|
CATCH(errctx, akgl_string_initialize(testptr, NULL));
|
||||||
if ( testptr->refcount == 0 ) {
|
if ( testptr->refcount == 0 ) {
|
||||||
FAIL_RETURN(errctx, ERR_VALUE, "Expected string reference count to be nonzero but got 0");
|
FAIL_RETURN(errctx, AKERR_VALUE, "Expected string reference count to be nonzero but got 0");
|
||||||
}
|
}
|
||||||
if ( testptr != firstptr ) {
|
if ( testptr != firstptr ) {
|
||||||
FAIL_RETURN(
|
FAIL_RETURN(
|
||||||
errctx,
|
errctx,
|
||||||
ERR_VALUE,
|
AKERR_VALUE,
|
||||||
"Expected testptr to equal (HEAP_STRING[1] = %p) but got %p",
|
"Expected testptr to equal (HEAP_STRING[1] = %p) but got %p",
|
||||||
secondptr,
|
secondptr,
|
||||||
testptr
|
testptr
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
CATCH(errctx, heap_next_string(&testptr));
|
CATCH(errctx, akgl_heap_next_string(&testptr));
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *test_strcpy_to_all_strings_no_segfault(void)
|
akerr_ErrorContext *test_strcpy_to_all_strings_no_segfault(void)
|
||||||
{
|
{
|
||||||
char copybuf[MAX_STRING_LENGTH];
|
char copybuf[AKGL_MAX_STRING_LENGTH];
|
||||||
string *ptr;
|
akgl_String *ptr;
|
||||||
memset((void *)©buf, 'a', MAX_STRING_LENGTH);
|
memset((void *)©buf, 'a', AKGL_MAX_STRING_LENGTH);
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
for ( int i = 0; i < MAX_HEAP_STRING - 1; i++ ) {
|
for ( int i = 0; i < AKGL_MAX_HEAP_STRING - 1; i++ ) {
|
||||||
CATCH(errctx, heap_next_string(&ptr));
|
CATCH(errctx, akgl_heap_next_string(&ptr));
|
||||||
strncpy(ptr->data, (char *)©buf, MAX_STRING_LENGTH);
|
strncpy(ptr->data, (char *)©buf, AKGL_MAX_STRING_LENGTH);
|
||||||
}
|
}
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
@@ -96,22 +96,22 @@ ErrorContext *test_strcpy_to_all_strings_no_segfault(void)
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *test_string_initialize(void)
|
akerr_ErrorContext *test_akgl_string_initialize(void)
|
||||||
{
|
{
|
||||||
string *ptr;
|
akgl_String *ptr;
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, heap_next_string(&ptr));
|
CATCH(errctx, akgl_heap_next_string(&ptr));
|
||||||
CATCH(errctx, string_initialize(ptr, NULL));
|
CATCH(errctx, akgl_string_initialize(ptr, NULL));
|
||||||
FAIL_NONZERO_BREAK(errctx, ptr->data[0], ERR_VALUE, "Expected empty zero length string data");
|
FAIL_NONZERO_BREAK(errctx, ptr->data[0], AKERR_VALUE, "Expected empty zero length string data");
|
||||||
|
|
||||||
CATCH(errctx, heap_release_string(ptr));
|
CATCH(errctx, akgl_heap_release_string(ptr));
|
||||||
CATCH(errctx, heap_next_string(&ptr));
|
CATCH(errctx, akgl_heap_next_string(&ptr));
|
||||||
CATCH(errctx, string_initialize(ptr, "Test value"));
|
CATCH(errctx, akgl_string_initialize(ptr, "Test value"));
|
||||||
FAIL_NONZERO_BREAK(errctx, strcmp((char *)&ptr->data, "Test value"), ERR_VALUE, "Expected 'Test value', got %s", (char *)&ptr->data);
|
FAIL_NONZERO_BREAK(errctx, strcmp((char *)&ptr->data, "Test value"), AKERR_VALUE, "Expected 'Test value', got %s", (char *)&ptr->data);
|
||||||
|
|
||||||
CATCH(errctx, heap_release_string(NULL));
|
CATCH(errctx, akgl_heap_release_string(NULL));
|
||||||
FAIL_BREAK(errctx, ERR_BEHAVIOR, "Failure to properly handle NULL pointer");
|
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Failure to properly handle NULL pointer");
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
@@ -122,8 +122,8 @@ ErrorContext *test_string_initialize(void)
|
|||||||
|
|
||||||
void reset_string_heap(void)
|
void reset_string_heap(void)
|
||||||
{
|
{
|
||||||
for ( int i = 0; i < MAX_HEAP_STRING; i++ ) {
|
for ( int i = 0; i < AKGL_MAX_HEAP_STRING; i++ ) {
|
||||||
memset(&HEAP_STRING[i], 0x00, sizeof(string));
|
memset(&HEAP_STRING[i], 0x00, sizeof(akgl_String));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,8 +144,8 @@ int main(void)
|
|||||||
printf("test_strcpy_to_all_strings_no_segfault ...\n");
|
printf("test_strcpy_to_all_strings_no_segfault ...\n");
|
||||||
test_strcpy_to_all_strings_no_segfault();
|
test_strcpy_to_all_strings_no_segfault();
|
||||||
reset_string_heap();
|
reset_string_heap();
|
||||||
printf("test_string_initialize....\n");
|
printf("test_akgl_string_initialize....\n");
|
||||||
test_string_initialize();
|
test_akgl_string_initialize();
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH_NORETURN(errctx);
|
} FINISH_NORETURN(errctx);
|
||||||
|
|||||||
216
tests/tilemap.c
216
tests/tilemap.c
@@ -2,37 +2,37 @@
|
|||||||
#include <SDL3_image/SDL_image.h>
|
#include <SDL3_image/SDL_image.h>
|
||||||
#include <jansson.h>
|
#include <jansson.h>
|
||||||
|
|
||||||
#include <sdlerror.h>
|
#include <akerror.h>
|
||||||
#include <sdl3game/util.h>
|
#include <akgl/util.h>
|
||||||
#include <sdl3game/heap.h>
|
#include <akgl/heap.h>
|
||||||
#include <sdl3game/registry.h>
|
#include <akgl/registry.h>
|
||||||
#include <sdl3game/tilemap.h>
|
#include <akgl/tilemap.h>
|
||||||
#include <sdl3game/actor.h>
|
#include <akgl/actor.h>
|
||||||
#include <sdl3game/game.h>
|
#include <akgl/game.h>
|
||||||
#include <sdl3game/json_helpers.h>
|
#include <akgl/json_helpers.h>
|
||||||
|
|
||||||
ErrorContext *test_tilemap_get_json_tilemap_property(void)
|
akerr_ErrorContext *test_tilemap_akgl_get_json_tilemap_property(void)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
json_t *jsondoc = NULL;
|
json_t *jsondoc = NULL;
|
||||||
json_error_t jsonerr;
|
json_error_t jsonerr;
|
||||||
string *tmpstr = NULL;
|
akgl_String *tmpstr = NULL;
|
||||||
int propnum;
|
int propnum;
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, heap_next_string(&tmpstr));
|
CATCH(errctx, akgl_heap_next_string(&tmpstr));
|
||||||
snprintf(
|
snprintf(
|
||||||
(char *)&tmpstr->data,
|
(char *)&tmpstr->data,
|
||||||
MAX_STRING_LENGTH,
|
AKGL_MAX_STRING_LENGTH,
|
||||||
"%s%s",
|
"%s%s",
|
||||||
SDL_GetBasePath(),
|
SDL_GetBasePath(),
|
||||||
"assets/snippets/test_tilemap_get_json_tilemap_property.json"
|
"assets/snippets/test_tilemap_akgl_get_json_tilemap_property.json"
|
||||||
);
|
);
|
||||||
jsondoc = json_load_file((char *)&tmpstr->data, 0, (json_error_t *)&jsonerr);
|
jsondoc = json_load_file((char *)&tmpstr->data, 0, (json_error_t *)&jsonerr);
|
||||||
FAIL_ZERO_BREAK(errctx, jsondoc, ERR_NULLPOINTER, "Failure loading json fixture: %s", (char *)jsonerr.text);
|
FAIL_ZERO_BREAK(errctx, jsondoc, AKERR_NULLPOINTER, "Failure loading json fixture: %s", (char *)jsonerr.text);
|
||||||
CATCH(
|
CATCH(
|
||||||
errctx,
|
errctx,
|
||||||
get_json_properties_string(
|
akgl_get_json_properties_string(
|
||||||
jsondoc,
|
jsondoc,
|
||||||
"character",
|
"character",
|
||||||
&tmpstr
|
&tmpstr
|
||||||
@@ -41,13 +41,13 @@ ErrorContext *test_tilemap_get_json_tilemap_property(void)
|
|||||||
FAIL_NONZERO_BREAK(
|
FAIL_NONZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
strcmp((char *)&tmpstr->data, "testcharacter"),
|
strcmp((char *)&tmpstr->data, "testcharacter"),
|
||||||
ERR_VALUE,
|
AKERR_VALUE,
|
||||||
"Incorrect value loaded from property `character` (`testcharacter` vs `%s`)",
|
"Incorrect value loaded from property `character` (`testcharacter` vs `%s`)",
|
||||||
(char *)&tmpstr->data
|
(char *)&tmpstr->data
|
||||||
);
|
);
|
||||||
CATCH(
|
CATCH(
|
||||||
errctx,
|
errctx,
|
||||||
get_json_properties_integer(
|
akgl_get_json_properties_integer(
|
||||||
jsondoc,
|
jsondoc,
|
||||||
"state",
|
"state",
|
||||||
&propnum
|
&propnum
|
||||||
@@ -56,13 +56,13 @@ ErrorContext *test_tilemap_get_json_tilemap_property(void)
|
|||||||
FAIL_NONZERO_BREAK(
|
FAIL_NONZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
(propnum != 6),
|
(propnum != 6),
|
||||||
ERR_VALUE,
|
AKERR_VALUE,
|
||||||
"Incorrect value loaded from property `state` (6 vs %d)",
|
"Incorrect value loaded from property `state` (6 vs %d)",
|
||||||
propnum
|
propnum
|
||||||
);
|
);
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
if ( tmpstr != NULL ) {
|
if ( tmpstr != NULL ) {
|
||||||
IGNORE(heap_release_string(tmpstr));
|
IGNORE(akgl_heap_release_string(tmpstr));
|
||||||
}
|
}
|
||||||
if ( jsondoc != NULL ) {
|
if ( jsondoc != NULL ) {
|
||||||
json_decref(jsondoc);
|
json_decref(jsondoc);
|
||||||
@@ -72,7 +72,7 @@ ErrorContext *test_tilemap_get_json_tilemap_property(void)
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *test_tilemap_compute_tileset_offsets(void)
|
akerr_ErrorContext *test_akgl_tilemap_compute_tileset_offsets(void)
|
||||||
{
|
{
|
||||||
int comparison_values[8] = {
|
int comparison_values[8] = {
|
||||||
0, // Tile 0 X
|
0, // Tile 0 X
|
||||||
@@ -96,7 +96,7 @@ ErrorContext *test_tilemap_compute_tileset_offsets(void)
|
|||||||
};
|
};
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
memset((void *)&gamemap, 0x00, sizeof(tilemap));
|
memset((void *)&gamemap, 0x00, sizeof(akgl_Tilemap));
|
||||||
gamemap.tilesets[0].tilecount = 4;
|
gamemap.tilesets[0].tilecount = 4;
|
||||||
gamemap.tilesets[0].columns = 2;
|
gamemap.tilesets[0].columns = 2;
|
||||||
gamemap.tilesets[0].firstgid = 1;
|
gamemap.tilesets[0].firstgid = 1;
|
||||||
@@ -110,13 +110,13 @@ ErrorContext *test_tilemap_compute_tileset_offsets(void)
|
|||||||
|
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, tilemap_compute_tileset_offsets(&gamemap, 0));
|
CATCH(errctx, akgl_tilemap_compute_tileset_offsets(&gamemap, 0));
|
||||||
// Tile 0 X offset
|
// Tile 0 X offset
|
||||||
for ( i = 0; i < 8; i++ ) {
|
for ( i = 0; i < 8; i++ ) {
|
||||||
FAIL_NONZERO_BREAK(
|
FAIL_NONZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
(*comparison_ptrs[i] != comparison_values[i]),
|
(*comparison_ptrs[i] != comparison_values[i]),
|
||||||
ERR_VALUE,
|
AKERR_VALUE,
|
||||||
"Tile offset incorrectly calculated for index %d (%d vs %d)",
|
"Tile offset incorrectly calculated for index %d (%d vs %d)",
|
||||||
i,
|
i,
|
||||||
*comparison_ptrs[i],
|
*comparison_ptrs[i],
|
||||||
@@ -129,44 +129,44 @@ ErrorContext *test_tilemap_compute_tileset_offsets(void)
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *test_tilemap_load_layer_objects(void)
|
akerr_ErrorContext *test_akgl_tilemap_load_layer_objects(void)
|
||||||
{
|
{
|
||||||
string *pathstr;
|
akgl_String *pathstr;
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
json_t *doc = NULL;
|
json_t *doc = NULL;
|
||||||
json_t *layers = NULL;
|
json_t *layers = NULL;
|
||||||
json_t *objectlayer = NULL;
|
json_t *objectlayer = NULL;
|
||||||
json_error_t errdata;
|
json_error_t errdata;
|
||||||
actor *testactor;
|
akgl_Actor *testactor;
|
||||||
|
|
||||||
memset((void *)&gamemap, 0x00, sizeof(tilemap));
|
memset((void *)&gamemap, 0x00, sizeof(akgl_Tilemap));
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, heap_next_string(&pathstr));
|
CATCH(errctx, akgl_heap_next_string(&pathstr));
|
||||||
snprintf((char *)&pathstr->data, MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), "assets/testmap.tmj");
|
snprintf((char *)&pathstr->data, AKGL_MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), "assets/testmap.tmj");
|
||||||
doc = json_load_file((char *)&pathstr->data, 0, &errdata);
|
doc = json_load_file((char *)&pathstr->data, 0, &errdata);
|
||||||
FAIL_ZERO_BREAK(errctx, doc, ERR_NULLPOINTER, "Failed to load testmap: %s", (char *)&errdata.text);
|
FAIL_ZERO_BREAK(errctx, doc, AKERR_NULLPOINTER, "Failed to load testmap: %s", (char *)&errdata.text);
|
||||||
CATCH(errctx, get_json_array_value(doc, "layers", &layers));
|
CATCH(errctx, akgl_get_json_array_value(doc, "layers", &layers));
|
||||||
CATCH(errctx, get_json_array_index_object(layers, 1, &objectlayer));
|
CATCH(errctx, akgl_get_json_array_index_object(layers, 1, &objectlayer));
|
||||||
CATCH(errctx, tilemap_load_layer_objects(&gamemap, objectlayer, 1));
|
CATCH(errctx, akgl_tilemap_load_layer_objects(&gamemap, objectlayer, 1));
|
||||||
|
|
||||||
testactor = SDL_GetPointerProperty(REGISTRY_ACTOR, "testactor", NULL);
|
testactor = SDL_GetPointerProperty(AKGL_REGISTRY_ACTOR, "testactor", NULL);
|
||||||
FAIL_ZERO_BREAK(
|
FAIL_ZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
testactor,
|
testactor,
|
||||||
ERR_NULLPOINTER,
|
AKERR_NULLPOINTER,
|
||||||
"Test Actor was not loaded from the test map"
|
"Test Actor was not loaded from the test map"
|
||||||
);
|
);
|
||||||
if ( (testactor->basechar != SDL_GetPointerProperty(REGISTRY_CHARACTER, "testcharacter", NULL)) ||
|
if ( (testactor->basechar != SDL_GetPointerProperty(AKGL_REGISTRY_CHARACTER, "testcharacter", NULL)) ||
|
||||||
(testactor->layer != 1) ||
|
(testactor->layer != 1) ||
|
||||||
(testactor->state != 6) ||
|
(testactor->state != 6) ||
|
||||||
(testactor->visible != true) ||
|
(testactor->visible != true) ||
|
||||||
(testactor->x != 16) ||
|
(testactor->x != 16) ||
|
||||||
(testactor->y != 16) ) {
|
(testactor->y != 16) ) {
|
||||||
FAIL_BREAK(errctx, ERR_VALUE, "Test actor was loaded with incorrect values (check gdb)");
|
FAIL_BREAK(errctx, AKERR_VALUE, "Test actor was loaded with incorrect values (check gdb)");
|
||||||
}
|
}
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
if ( pathstr != NULL ) {
|
if ( pathstr != NULL ) {
|
||||||
IGNORE(heap_release_string(pathstr));
|
IGNORE(akgl_heap_release_string(pathstr));
|
||||||
}
|
}
|
||||||
if ( doc != NULL ) {
|
if ( doc != NULL ) {
|
||||||
json_decref(doc);
|
json_decref(doc);
|
||||||
@@ -176,9 +176,9 @@ ErrorContext *test_tilemap_load_layer_objects(void)
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *test_tilemap_load_layer_tile(void)
|
akerr_ErrorContext *test_akgl_tilemap_load_layer_tile(void)
|
||||||
{
|
{
|
||||||
string *pathstr;
|
akgl_String *pathstr;
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
json_t *doc = NULL;
|
json_t *doc = NULL;
|
||||||
json_t *layers = NULL;
|
json_t *layers = NULL;
|
||||||
@@ -186,26 +186,26 @@ ErrorContext *test_tilemap_load_layer_tile(void)
|
|||||||
json_t *tiledata = NULL;
|
json_t *tiledata = NULL;
|
||||||
json_error_t errdata;
|
json_error_t errdata;
|
||||||
|
|
||||||
memset((void *)&gamemap, 0x00, sizeof(tilemap));
|
memset((void *)&gamemap, 0x00, sizeof(akgl_Tilemap));
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, heap_next_string(&pathstr));
|
CATCH(errctx, akgl_heap_next_string(&pathstr));
|
||||||
snprintf((char *)&pathstr->data, MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), "assets/testmap.tmj");
|
snprintf((char *)&pathstr->data, AKGL_MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), "assets/testmap.tmj");
|
||||||
doc = json_load_file((char *)&pathstr->data, 0, &errdata);
|
doc = json_load_file((char *)&pathstr->data, 0, &errdata);
|
||||||
FAIL_ZERO_BREAK(errctx, doc, ERR_NULLPOINTER, "Failed to load testmap: %s", (char *)&errdata.text);
|
FAIL_ZERO_BREAK(errctx, doc, AKERR_NULLPOINTER, "Failed to load testmap: %s", (char *)&errdata.text);
|
||||||
CATCH(errctx, get_json_array_value(doc, "layers", &layers));
|
CATCH(errctx, akgl_get_json_array_value(doc, "layers", &layers));
|
||||||
CATCH(errctx, get_json_array_index_object(layers, 0, &tilelayer));
|
CATCH(errctx, akgl_get_json_array_index_object(layers, 0, &tilelayer));
|
||||||
CATCH(errctx, get_json_array_value(tilelayer, "data", &tiledata));
|
CATCH(errctx, akgl_get_json_array_value(tilelayer, "data", &tiledata));
|
||||||
CATCH(errctx, tilemap_load_layer_tile(&gamemap, tilelayer, 0));
|
CATCH(errctx, akgl_tilemap_load_layer_tile(&gamemap, tilelayer, 0));
|
||||||
if ( (gamemap.layers[0].data[0] != 1) ||
|
if ( (gamemap.layers[0].data[0] != 1) ||
|
||||||
(gamemap.layers[0].data[1] != 2) ||
|
(gamemap.layers[0].data[1] != 2) ||
|
||||||
(gamemap.layers[0].data[2] != 3) ||
|
(gamemap.layers[0].data[2] != 3) ||
|
||||||
(gamemap.layers[0].data[3] != 4) ) {
|
(gamemap.layers[0].data[3] != 4) ) {
|
||||||
FAIL_BREAK(errctx, ERR_VALUE, "Test tilemap layer 0 tiles loaded with incorrect values (check gdb)");
|
FAIL_BREAK(errctx, AKERR_VALUE, "Test tilemap layer 0 tiles loaded with incorrect values (check gdb)");
|
||||||
}
|
}
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
if ( pathstr != NULL ) {
|
if ( pathstr != NULL ) {
|
||||||
IGNORE(heap_release_string(pathstr));
|
IGNORE(akgl_heap_release_string(pathstr));
|
||||||
}
|
}
|
||||||
if ( doc != NULL ) {
|
if ( doc != NULL ) {
|
||||||
json_decref(doc);
|
json_decref(doc);
|
||||||
@@ -215,26 +215,26 @@ ErrorContext *test_tilemap_load_layer_tile(void)
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *test_tilemap_load_layers(void)
|
akerr_ErrorContext *test_akgl_tilemap_load_layers(void)
|
||||||
{
|
{
|
||||||
string *pathstr;
|
akgl_String *pathstr;
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
json_t *doc = NULL;
|
json_t *doc = NULL;
|
||||||
json_error_t errdata;
|
json_error_t errdata;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
memset((void *)&gamemap, 0x00, sizeof(tilemap));
|
memset((void *)&gamemap, 0x00, sizeof(akgl_Tilemap));
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, heap_next_string(&pathstr));
|
CATCH(errctx, akgl_heap_next_string(&pathstr));
|
||||||
snprintf((char *)&pathstr->data, MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), "assets/testmap.tmj");
|
snprintf((char *)&pathstr->data, AKGL_MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), "assets/testmap.tmj");
|
||||||
doc = json_load_file((char *)&pathstr->data, 0, &errdata);
|
doc = json_load_file((char *)&pathstr->data, 0, &errdata);
|
||||||
FAIL_ZERO_BREAK(errctx, doc, ERR_NULLPOINTER, "Failed to load testmap: %s", (char *)&errdata.text);
|
FAIL_ZERO_BREAK(errctx, doc, AKERR_NULLPOINTER, "Failed to load testmap: %s", (char *)&errdata.text);
|
||||||
CATCH(errctx, tilemap_load_layers(&gamemap, doc));
|
CATCH(errctx, akgl_tilemap_load_layers(&gamemap, doc));
|
||||||
FAIL_NONZERO_BREAK(
|
FAIL_NONZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
(gamemap.numlayers != 3),
|
(gamemap.numlayers != 3),
|
||||||
ERR_VALUE,
|
AKERR_VALUE,
|
||||||
"Map layer count incorrect"
|
"Map layer count incorrect"
|
||||||
);
|
);
|
||||||
for ( i = 0; i < gamemap.numlayers; i++ ) {
|
for ( i = 0; i < gamemap.numlayers; i++ ) {
|
||||||
@@ -243,27 +243,27 @@ ErrorContext *test_tilemap_load_layers(void)
|
|||||||
(gamemap.layers[i].id != (i + 1)) ||
|
(gamemap.layers[i].id != (i + 1)) ||
|
||||||
(gamemap.layers[i].x != 0) ||
|
(gamemap.layers[i].x != 0) ||
|
||||||
(gamemap.layers[i].y != 0) ) {
|
(gamemap.layers[i].y != 0) ) {
|
||||||
FAIL(errctx, ERR_VALUE, "Map layer data loaded incorrectly (see gdb)");
|
FAIL(errctx, AKERR_VALUE, "Map layer data loaded incorrectly (see gdb)");
|
||||||
goto _test_tilemap_load_layers_cleanup;
|
goto _test_akgl_tilemap_load_layers_cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Layer 2 should have 1 object loaded
|
// Layer 2 should have 1 object loaded
|
||||||
if ( (gamemap.layers[1].objects[0].actorptr != SDL_GetPointerProperty(REGISTRY_ACTOR, "testactor", NULL)) ||
|
if ( (gamemap.layers[1].objects[0].actorptr != SDL_GetPointerProperty(AKGL_REGISTRY_ACTOR, "testactor", NULL)) ||
|
||||||
(gamemap.layers[1].objects[1].name[0] != '\0' ) ||
|
(gamemap.layers[1].objects[1].name[0] != '\0' ) ||
|
||||||
(gamemap.layers[1].objects[1].id != 0) ) {
|
(gamemap.layers[1].objects[1].id != 0) ) {
|
||||||
FAIL_BREAK(errctx, ERR_VALUE, "Map layer 2 should have 1 loaded object (testactor) and nothing else (see gdb)");
|
FAIL_BREAK(errctx, AKERR_VALUE, "Map layer 2 should have 1 loaded object (testactor) and nothing else (see gdb)");
|
||||||
}
|
}
|
||||||
// Layer 1 and 3 should have no objects
|
// Layer 1 and 3 should have no objects
|
||||||
for ( i = 0; i < TILEMAP_MAX_OBJECTS_PER_LAYER ; i++ ) {
|
for ( i = 0; i < AKGL_TILEMAP_MAX_OBJECTS_PER_LAYER ; i++ ) {
|
||||||
if ( gamemap.layers[0].objects[i].id != 0 ) {
|
if ( gamemap.layers[0].objects[i].id != 0 ) {
|
||||||
FAIL(errctx, ERR_VALUE, "Map layers 1 and 3 should have no objects loaded but found objects");
|
FAIL(errctx, AKERR_VALUE, "Map layers 1 and 3 should have no objects loaded but found objects");
|
||||||
goto _test_tilemap_load_layers_cleanup;
|
goto _test_akgl_tilemap_load_layers_cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for ( i = 0; i < TILEMAP_MAX_OBJECTS_PER_LAYER ; i++ ) {
|
for ( i = 0; i < AKGL_TILEMAP_MAX_OBJECTS_PER_LAYER ; i++ ) {
|
||||||
if ( gamemap.layers[2].objects[i].id != 0 ) {
|
if ( gamemap.layers[2].objects[i].id != 0 ) {
|
||||||
FAIL(errctx, ERR_VALUE, "Map layers 1 and 3 should have no objects loaded but found objects");
|
FAIL(errctx, AKERR_VALUE, "Map layers 1 and 3 should have no objects loaded but found objects");
|
||||||
goto _test_tilemap_load_layers_cleanup;
|
goto _test_akgl_tilemap_load_layers_cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Layers 1 and 3 should have tile data
|
// Layers 1 and 3 should have tile data
|
||||||
@@ -276,12 +276,12 @@ ErrorContext *test_tilemap_load_layers(void)
|
|||||||
(gamemap.layers[2].data[2] != 0) ||
|
(gamemap.layers[2].data[2] != 0) ||
|
||||||
(gamemap.layers[2].data[3] != 6)
|
(gamemap.layers[2].data[3] != 6)
|
||||||
) {
|
) {
|
||||||
FAIL_BREAK(errctx, ERR_VALUE, "Map layers 1 and 3 should have tile data but it is incorrect");
|
FAIL_BREAK(errctx, AKERR_VALUE, "Map layers 1 and 3 should have tile data but it is incorrect");
|
||||||
}
|
}
|
||||||
_test_tilemap_load_layers_cleanup:
|
_test_akgl_tilemap_load_layers_cleanup:
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
if ( pathstr != NULL ) {
|
if ( pathstr != NULL ) {
|
||||||
IGNORE(heap_release_string(pathstr));
|
IGNORE(akgl_heap_release_string(pathstr));
|
||||||
}
|
}
|
||||||
if ( doc != NULL ) {
|
if ( doc != NULL ) {
|
||||||
json_decref(doc);
|
json_decref(doc);
|
||||||
@@ -291,23 +291,23 @@ _test_tilemap_load_layers_cleanup:
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *test_tilemap_load_tilesets(void)
|
akerr_ErrorContext *test_akgl_tilemap_load_tilesets(void)
|
||||||
{
|
{
|
||||||
string *pathstr = NULL;
|
akgl_String *pathstr = NULL;
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
json_t *doc = NULL;
|
json_t *doc = NULL;
|
||||||
json_error_t errdata;
|
json_error_t errdata;
|
||||||
SDL_Texture *image = NULL;
|
SDL_Texture *image = NULL;
|
||||||
|
|
||||||
memset((void *)&gamemap, 0x00, sizeof(tilemap));
|
memset((void *)&gamemap, 0x00, sizeof(akgl_Tilemap));
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, heap_next_string(&pathstr));
|
CATCH(errctx, akgl_heap_next_string(&pathstr));
|
||||||
snprintf((char *)&pathstr->data, MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), "assets/testmap.tmj");
|
snprintf((char *)&pathstr->data, AKGL_MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), "assets/testmap.tmj");
|
||||||
doc = json_load_file((char *)&pathstr->data, 0, &errdata);
|
doc = json_load_file((char *)&pathstr->data, 0, &errdata);
|
||||||
FAIL_ZERO_BREAK(errctx, doc, ERR_NULLPOINTER, "Failed to load testmap: %s", (char *)&errdata.text);
|
FAIL_ZERO_BREAK(errctx, doc, AKERR_NULLPOINTER, "Failed to load testmap: %s", (char *)&errdata.text);
|
||||||
CATCH(errctx, tilemap_load_tilesets(&gamemap, doc));
|
CATCH(errctx, akgl_tilemap_load_tilesets(&gamemap, doc));
|
||||||
FAIL_NONZERO_BREAK(errctx, (gamemap.numtilesets != 1), ERR_VALUE, "Incorrect number of tilesets loaded for map");
|
FAIL_NONZERO_BREAK(errctx, (gamemap.numtilesets != 1), AKERR_VALUE, "Incorrect number of tilesets loaded for map");
|
||||||
if ( (gamemap.tilesets[0].columns != 48 ) ||
|
if ( (gamemap.tilesets[0].columns != 48 ) ||
|
||||||
(gamemap.tilesets[0].firstgid != 1) ||
|
(gamemap.tilesets[0].firstgid != 1) ||
|
||||||
(gamemap.tilesets[0].imageheight != 576) ||
|
(gamemap.tilesets[0].imageheight != 576) ||
|
||||||
@@ -317,30 +317,30 @@ ErrorContext *test_tilemap_load_tilesets(void)
|
|||||||
(gamemap.tilesets[0].tilecount != 1728) ||
|
(gamemap.tilesets[0].tilecount != 1728) ||
|
||||||
(gamemap.tilesets[0].tileheight != 16) ||
|
(gamemap.tilesets[0].tileheight != 16) ||
|
||||||
(gamemap.tilesets[0].tilewidth != 16) ) {
|
(gamemap.tilesets[0].tilewidth != 16) ) {
|
||||||
FAIL_BREAK(errctx, ERR_VALUE, "Tileset loaded with incorrect values");
|
FAIL_BREAK(errctx, AKERR_VALUE, "Tileset loaded with incorrect values");
|
||||||
}
|
}
|
||||||
FAIL_NONZERO_BREAK(
|
FAIL_NONZERO_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
strcmp((char *)&gamemap.tilesets[0].name, "World_A1"),
|
strcmp((char *)&gamemap.tilesets[0].name, "World_A1"),
|
||||||
ERR_VALUE,
|
AKERR_VALUE,
|
||||||
"Tileset loaded with incorrect name");
|
"Tileset loaded with incorrect name");
|
||||||
|
|
||||||
snprintf((char *)&pathstr->data, MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), "assets/World_A1.png");
|
snprintf((char *)&pathstr->data, AKGL_MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), "assets/World_A1.png");
|
||||||
image = IMG_LoadTexture(renderer, (char *)&pathstr->data);
|
image = IMG_LoadTexture(renderer, (char *)&pathstr->data);
|
||||||
FAIL_ZERO_BREAK(errctx, image, ERR_SDL, "Failed to load comparison image");
|
FAIL_ZERO_BREAK(errctx, image, AKGL_ERR_SDL, "Failed to load comparison image");
|
||||||
|
|
||||||
CATCH(
|
CATCH(
|
||||||
errctx,
|
errctx,
|
||||||
render_and_compare(
|
akgl_render_and_compare(
|
||||||
gamemap.tilesets[0].texture,
|
gamemap.tilesets[0].texture,
|
||||||
image,
|
image,
|
||||||
0, 0, 768, 576,
|
0, 0, 768, 576,
|
||||||
"test_tilemap_loaded_tileset.png")
|
"test_akgl_tilemap_loaded_tileset.png")
|
||||||
);
|
);
|
||||||
|
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
if ( pathstr != NULL ) {
|
if ( pathstr != NULL ) {
|
||||||
IGNORE(heap_release_string(pathstr));
|
IGNORE(akgl_heap_release_string(pathstr));
|
||||||
}
|
}
|
||||||
if ( doc != NULL ) {
|
if ( doc != NULL ) {
|
||||||
json_decref(doc);
|
json_decref(doc);
|
||||||
@@ -350,21 +350,21 @@ ErrorContext *test_tilemap_load_tilesets(void)
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *test_tilemap_load(void)
|
akerr_ErrorContext *test_akgl_tilemap_load(void)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
|
|
||||||
memset((void *)&gamemap, 0x00, sizeof(tilemap));
|
memset((void *)&gamemap, 0x00, sizeof(akgl_Tilemap));
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, tilemap_load("assets/testmap.tmj", &gamemap));
|
CATCH(errctx, akgl_tilemap_load("assets/testmap.tmj", &gamemap));
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *test_tilemap_draw(void)
|
akerr_ErrorContext *test_akgl_tilemap_draw(void)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
|
|
||||||
@@ -376,7 +376,7 @@ ErrorContext *test_tilemap_draw(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ErrorContext *test_tilemap_draw_tileset(void)
|
akerr_ErrorContext *test_akgl_tilemap_draw_tileset(void)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
|
|
||||||
@@ -395,28 +395,28 @@ int main(void)
|
|||||||
SDL_SetAppMetadata("SDL3-GameTest", "0.1", "net.aklabs.sdl3-gametest");
|
SDL_SetAppMetadata("SDL3-GameTest", "0.1", "net.aklabs.sdl3-gametest");
|
||||||
|
|
||||||
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO )) {
|
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO )) {
|
||||||
FAIL_BREAK(errctx, ERR_SDL, "Couldn't initialize SDL: %s", SDL_GetError());
|
FAIL_BREAK(errctx, AKGL_ERR_SDL, "Couldn't initialize SDL: %s", SDL_GetError());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SDL_CreateWindowAndRenderer("net/aklabs/libsdl3game/test_sprite", 768, 576, 0, &window, &renderer)) {
|
if (!SDL_CreateWindowAndRenderer("net/aklabs/libakgl/test_sprite", 768, 576, 0, &window, &renderer)) {
|
||||||
FAIL_BREAK(errctx, ERR_SDL, "Couldn't create window/renderer: %s", SDL_GetError());
|
FAIL_BREAK(errctx, AKGL_ERR_SDL, "Couldn't create window/renderer: %s", SDL_GetError());
|
||||||
}
|
}
|
||||||
|
|
||||||
CATCH(errctx, registry_init());
|
CATCH(errctx, akgl_registry_init());
|
||||||
CATCH(errctx, heap_init());
|
CATCH(errctx, akgl_heap_init());
|
||||||
CATCH(errctx, sprite_load_json("assets/testsprite.json"));
|
CATCH(errctx, akgl_sprite_load_json("assets/testsprite.json"));
|
||||||
CATCH(errctx, sprite_load_json("assets/testsprite2.json"));
|
CATCH(errctx, akgl_sprite_load_json("assets/testsprite2.json"));
|
||||||
CATCH(errctx, character_load_json("assets/testcharacter.json"));
|
CATCH(errctx, akgl_character_load_json("assets/testcharacter.json"));
|
||||||
|
|
||||||
CATCH(errctx, test_tilemap_get_json_tilemap_property());
|
CATCH(errctx, test_tilemap_akgl_get_json_tilemap_property());
|
||||||
CATCH(errctx, test_tilemap_compute_tileset_offsets());
|
CATCH(errctx, test_akgl_tilemap_compute_tileset_offsets());
|
||||||
CATCH(errctx, test_tilemap_load_layer_objects());
|
CATCH(errctx, test_akgl_tilemap_load_layer_objects());
|
||||||
CATCH(errctx, test_tilemap_load_layer_tile());
|
CATCH(errctx, test_akgl_tilemap_load_layer_tile());
|
||||||
CATCH(errctx, test_tilemap_load_layers());
|
CATCH(errctx, test_akgl_tilemap_load_layers());
|
||||||
CATCH(errctx, test_tilemap_load_tilesets());
|
CATCH(errctx, test_akgl_tilemap_load_tilesets());
|
||||||
//CATCH(errctx, test_tilemap_load());
|
//CATCH(errctx, test_akgl_tilemap_load());
|
||||||
//CATCH(errctx, test_tilemap_draw_tileset());
|
//CATCH(errctx, test_akgl_tilemap_draw_tileset());
|
||||||
//CATCH(errctx, test_tilemap_draw());
|
//CATCH(errctx, test_akgl_tilemap_draw());
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH_NORETURN(errctx);
|
} FINISH_NORETURN(errctx);
|
||||||
|
|||||||
150
tests/util.c
150
tests/util.c
@@ -1,42 +1,42 @@
|
|||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <sdlerror.h>
|
#include <akerror.h>
|
||||||
#include <sdl3game/util.h>
|
#include <akgl/util.h>
|
||||||
|
|
||||||
ErrorContext *test_rectangle_points_nullpointers(void)
|
akerr_ErrorContext *test_akgl_rectangle_points_nullpointers(void)
|
||||||
{
|
{
|
||||||
RectanglePoints points;
|
RectanglePoints points;
|
||||||
SDL_FRect testrect;
|
SDL_FRect testrect;
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, rectangle_points(NULL, NULL));
|
CATCH(errctx, akgl_rectangle_points(NULL, NULL));
|
||||||
FAIL_BREAK(errctx, ERR_BEHAVIOR, "rectangle_points fails to FAIL with all NULL pointers");
|
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_rectangle_points fails to FAIL with all NULL pointers");
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} HANDLE(errctx, ERR_NULLPOINTER) {
|
} HANDLE(errctx, AKERR_NULLPOINTER) {
|
||||||
// noop
|
// noop
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, rectangle_points(NULL, &testrect));
|
CATCH(errctx, akgl_rectangle_points(NULL, &testrect));
|
||||||
FAIL_BREAK(errctx, ERR_BEHAVIOR, "rectangle_points fails to FAIL with NULL SDL_FRect pointer");
|
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_rectangle_points fails to FAIL with NULL SDL_FRect pointer");
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} HANDLE(errctx, ERR_NULLPOINTER) {
|
} HANDLE(errctx, AKERR_NULLPOINTER) {
|
||||||
// noop
|
// noop
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, rectangle_points(&points, NULL));
|
CATCH(errctx, akgl_rectangle_points(&points, NULL));
|
||||||
FAIL_BREAK(errctx, ERR_BEHAVIOR, "rectangle_points fails to FAIL with NULL RectanglePoints pointer");
|
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_rectangle_points fails to FAIL with NULL RectanglePoints pointer");
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} HANDLE(errctx, ERR_NULLPOINTER) {
|
} HANDLE(errctx, AKERR_NULLPOINTER) {
|
||||||
// noop
|
// noop
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, rectangle_points(&points, &testrect));
|
CATCH(errctx, akgl_rectangle_points(&points, &testrect));
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
@@ -44,7 +44,7 @@ ErrorContext *test_rectangle_points_nullpointers(void)
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *test_rectangle_points_math(void)
|
akerr_ErrorContext *test_akgl_rectangle_points_math(void)
|
||||||
{
|
{
|
||||||
RectanglePoints points;
|
RectanglePoints points;
|
||||||
SDL_FRect testrect = {.x = 0, .y = 0, .w = 32, .h = 32};
|
SDL_FRect testrect = {.x = 0, .y = 0, .w = 32, .h = 32};
|
||||||
@@ -52,7 +52,7 @@ ErrorContext *test_rectangle_points_math(void)
|
|||||||
|
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, rectangle_points(&points, &testrect));
|
CATCH(errctx, akgl_rectangle_points(&points, &testrect));
|
||||||
if ( points.topleft.x != 0 ||
|
if ( points.topleft.x != 0 ||
|
||||||
points.topleft.y != 0 ||
|
points.topleft.y != 0 ||
|
||||||
points.topright.x != 32 ||
|
points.topright.x != 32 ||
|
||||||
@@ -63,8 +63,8 @@ ErrorContext *test_rectangle_points_math(void)
|
|||||||
points.bottomright.y != 32 ) {
|
points.bottomright.y != 32 ) {
|
||||||
FAIL_BREAK(
|
FAIL_BREAK(
|
||||||
errctx,
|
errctx,
|
||||||
ERR_BEHAVIOR,
|
AKERR_BEHAVIOR,
|
||||||
"rectangle_points incorrectly calculated points for {x=0, y=0, w=32, h=32} to {topleft={%d, %d}, topright={%d, %d}, bottomleft={%d, %d}, bottomright={%d, %d}}",
|
"akgl_rectangle_points incorrectly calculated points for {x=0, y=0, w=32, h=32} to {topleft={%d, %d}, topright={%d, %d}, bottomleft={%d, %d}, bottomright={%d, %d}}",
|
||||||
points.topleft.x, points.topleft.y,
|
points.topleft.x, points.topleft.y,
|
||||||
points.topright.x, points.topright.y,
|
points.topright.x, points.topright.y,
|
||||||
points.bottomleft.x, points.bottomleft.y,
|
points.bottomleft.x, points.bottomleft.y,
|
||||||
@@ -77,7 +77,7 @@ ErrorContext *test_rectangle_points_math(void)
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *test_collide_point_rectangle_nullpointers(void)
|
akerr_ErrorContext *test_akgl_collide_point_rectangle_nullpointers(void)
|
||||||
{
|
{
|
||||||
point testpoint;
|
point testpoint;
|
||||||
RectanglePoints testrectpoints;
|
RectanglePoints testrectpoints;
|
||||||
@@ -86,43 +86,43 @@ ErrorContext *test_collide_point_rectangle_nullpointers(void)
|
|||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, collide_point_rectangle(&testpoint, &testrectpoints, NULL));
|
CATCH(errctx, akgl_collide_point_rectangle(&testpoint, &testrectpoints, NULL));
|
||||||
FAIL_BREAK(errctx, ERR_BEHAVIOR, "collide_point_rectangle(*, *, NULL) failed");
|
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_collide_point_rectangle(*, *, NULL) failed");
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} HANDLE(errctx, ERR_NULLPOINTER) {
|
} HANDLE(errctx, AKERR_NULLPOINTER) {
|
||||||
// noop
|
// noop
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, collide_point_rectangle(&testpoint, NULL, &testcollide));
|
CATCH(errctx, akgl_collide_point_rectangle(&testpoint, NULL, &testcollide));
|
||||||
FAIL_BREAK(errctx, ERR_BEHAVIOR, "collide_point_rectangle(*, NULL, *) failed");
|
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_collide_point_rectangle(*, NULL, *) failed");
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} HANDLE(errctx, ERR_NULLPOINTER) {
|
} HANDLE(errctx, AKERR_NULLPOINTER) {
|
||||||
// noop
|
// noop
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, collide_point_rectangle(NULL, &testrectpoints, &testcollide));
|
CATCH(errctx, akgl_collide_point_rectangle(NULL, &testrectpoints, &testcollide));
|
||||||
FAIL_BREAK(errctx, ERR_BEHAVIOR, "collide_point_rectangle(NULL, *, *) failed");
|
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_collide_point_rectangle(NULL, *, *) failed");
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} HANDLE(errctx, ERR_NULLPOINTER) {
|
} HANDLE(errctx, AKERR_NULLPOINTER) {
|
||||||
// noop
|
// noop
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, collide_point_rectangle(NULL, NULL, NULL));
|
CATCH(errctx, akgl_collide_point_rectangle(NULL, NULL, NULL));
|
||||||
FAIL_BREAK(errctx, ERR_BEHAVIOR, "collide_point_rectangle(NULL, NULL, NULL) failed");
|
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_collide_point_rectangle(NULL, NULL, NULL) failed");
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} HANDLE(errctx, ERR_NULLPOINTER) {
|
} HANDLE(errctx, AKERR_NULLPOINTER) {
|
||||||
// noop
|
// noop
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, collide_point_rectangle(&testpoint, &testrectpoints, &testcollide));
|
CATCH(errctx, akgl_collide_point_rectangle(&testpoint, &testrectpoints, &testcollide));
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
@@ -130,7 +130,7 @@ ErrorContext *test_collide_point_rectangle_nullpointers(void)
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *test_collide_point_rectangle_logic(void)
|
akerr_ErrorContext *test_akgl_collide_point_rectangle_logic(void)
|
||||||
{
|
{
|
||||||
point testpoint = {.x = 16, .y = 16};
|
point testpoint = {.x = 16, .y = 16};
|
||||||
SDL_FRect testrect = { .x = 0, .y = 0, .w = 32, .h = 32};
|
SDL_FRect testrect = { .x = 0, .y = 0, .w = 32, .h = 32};
|
||||||
@@ -139,17 +139,17 @@ ErrorContext *test_collide_point_rectangle_logic(void)
|
|||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, rectangle_points(&testrectpoints, &testrect));
|
CATCH(errctx, akgl_rectangle_points(&testrectpoints, &testrect));
|
||||||
CATCH(errctx, collide_point_rectangle(&testpoint, &testrectpoints, &testcollide));
|
CATCH(errctx, akgl_collide_point_rectangle(&testpoint, &testrectpoints, &testcollide));
|
||||||
if ( testcollide == false ) {
|
if ( testcollide == false ) {
|
||||||
FAIL_BREAK(errctx, ERR_BEHAVIOR, "Valid collision missed");
|
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Valid collision missed");
|
||||||
}
|
}
|
||||||
|
|
||||||
testpoint.x = 48;
|
testpoint.x = 48;
|
||||||
testpoint.y = 48;
|
testpoint.y = 48;
|
||||||
CATCH(errctx, collide_point_rectangle(&testpoint, &testrectpoints, &testcollide));
|
CATCH(errctx, akgl_collide_point_rectangle(&testpoint, &testrectpoints, &testcollide));
|
||||||
if ( testcollide == true ) {
|
if ( testcollide == true ) {
|
||||||
FAIL_BREAK(errctx, ERR_BEHAVIOR, "Invalid collision reported");
|
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Invalid collision reported");
|
||||||
}
|
}
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
@@ -157,7 +157,7 @@ ErrorContext *test_collide_point_rectangle_logic(void)
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *test_collide_rectangles_nullpointers(void)
|
akerr_ErrorContext *test_akgl_collide_rectangles_nullpointers(void)
|
||||||
{
|
{
|
||||||
SDL_FRect testrect1;
|
SDL_FRect testrect1;
|
||||||
SDL_FRect testrect2;
|
SDL_FRect testrect2;
|
||||||
@@ -166,43 +166,43 @@ ErrorContext *test_collide_rectangles_nullpointers(void)
|
|||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, collide_rectangles(&testrect1, &testrect2, NULL));
|
CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, NULL));
|
||||||
FAIL_BREAK(errctx, ERR_BEHAVIOR, "collide_rectangles(*, *, NULL) failed");
|
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_collide_rectangles(*, *, NULL) failed");
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} HANDLE(errctx, ERR_NULLPOINTER) {
|
} HANDLE(errctx, AKERR_NULLPOINTER) {
|
||||||
// noop
|
// noop
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, collide_rectangles(&testrect1, NULL, &testcollide));
|
CATCH(errctx, akgl_collide_rectangles(&testrect1, NULL, &testcollide));
|
||||||
FAIL_BREAK(errctx, ERR_BEHAVIOR, "collide_rectangles(*, NULL, *) failed");
|
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_collide_rectangles(*, NULL, *) failed");
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} HANDLE(errctx, ERR_NULLPOINTER) {
|
} HANDLE(errctx, AKERR_NULLPOINTER) {
|
||||||
// noop
|
// noop
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, collide_rectangles(NULL, &testrect2, &testcollide));
|
CATCH(errctx, akgl_collide_rectangles(NULL, &testrect2, &testcollide));
|
||||||
FAIL_BREAK(errctx, ERR_BEHAVIOR, "collide_rectangles(NULL, *, *) failed");
|
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_collide_rectangles(NULL, *, *) failed");
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} HANDLE(errctx, ERR_NULLPOINTER) {
|
} HANDLE(errctx, AKERR_NULLPOINTER) {
|
||||||
// noop
|
// noop
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, collide_rectangles(NULL, NULL, NULL));
|
CATCH(errctx, akgl_collide_rectangles(NULL, NULL, NULL));
|
||||||
FAIL_BREAK(errctx, ERR_BEHAVIOR, "collide_rectangles(NULL, NULL, NULL) failed");
|
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_collide_rectangles(NULL, NULL, NULL) failed");
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} HANDLE(errctx, ERR_NULLPOINTER) {
|
} HANDLE(errctx, AKERR_NULLPOINTER) {
|
||||||
// noop
|
// noop
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, collide_rectangles(&testrect1, &testrect2, &testcollide));
|
CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide));
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
@@ -210,7 +210,7 @@ ErrorContext *test_collide_rectangles_nullpointers(void)
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorContext *test_collide_rectangles_logic(void)
|
akerr_ErrorContext *test_akgl_collide_rectangles_logic(void)
|
||||||
{
|
{
|
||||||
SDL_FRect testrect1 = { .x = 0, .y = 0, .w = 32, .h = 32};
|
SDL_FRect testrect1 = { .x = 0, .y = 0, .w = 32, .h = 32};
|
||||||
SDL_FRect testrect2 = { .x = 30, .y = 30, .w = 40, .h = 40};
|
SDL_FRect testrect2 = { .x = 30, .y = 30, .w = 40, .h = 40};
|
||||||
@@ -220,32 +220,32 @@ ErrorContext *test_collide_rectangles_logic(void)
|
|||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
// Collision overlapping on the top left
|
// Collision overlapping on the top left
|
||||||
CATCH(errctx, collide_rectangles(&testrect1, &testrect2, &testcollide));
|
CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide));
|
||||||
if ( testcollide == false ) {
|
if ( testcollide == false ) {
|
||||||
FAIL_BREAK(errctx, ERR_BEHAVIOR, "Valid collision missed");
|
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Valid collision missed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collision overlapping on the top right
|
// Collision overlapping on the top right
|
||||||
testrect1.x = 64;
|
testrect1.x = 64;
|
||||||
CATCH(errctx, collide_rectangles(&testrect1, &testrect2, &testcollide));
|
CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide));
|
||||||
if ( testcollide == false ) {
|
if ( testcollide == false ) {
|
||||||
FAIL_BREAK(errctx, ERR_BEHAVIOR, "Valid collision missed");
|
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Valid collision missed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collision overlapping on the bottom left
|
// Collision overlapping on the bottom left
|
||||||
testrect1.x = 0;
|
testrect1.x = 0;
|
||||||
testrect1.y = 32;
|
testrect1.y = 32;
|
||||||
CATCH(errctx, collide_rectangles(&testrect1, &testrect2, &testcollide));
|
CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide));
|
||||||
if ( testcollide == false ) {
|
if ( testcollide == false ) {
|
||||||
FAIL_BREAK(errctx, ERR_BEHAVIOR, "Valid collision missed");
|
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Valid collision missed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collision overlapping on the bottom right
|
// Collision overlapping on the bottom right
|
||||||
testrect1.x = 32;
|
testrect1.x = 32;
|
||||||
testrect1.y = 32;
|
testrect1.y = 32;
|
||||||
CATCH(errctx, collide_rectangles(&testrect1, &testrect2, &testcollide));
|
CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide));
|
||||||
if ( testcollide == false ) {
|
if ( testcollide == false ) {
|
||||||
FAIL_BREAK(errctx, ERR_BEHAVIOR, "Valid collision missed");
|
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Valid collision missed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collision overlapping the top edge
|
// Collision overlapping the top edge
|
||||||
@@ -253,9 +253,9 @@ ErrorContext *test_collide_rectangles_logic(void)
|
|||||||
testrect1.y = 0;
|
testrect1.y = 0;
|
||||||
testrect1.w = 60;
|
testrect1.w = 60;
|
||||||
testrect1.h = 32;
|
testrect1.h = 32;
|
||||||
CATCH(errctx, collide_rectangles(&testrect1, &testrect2, &testcollide));
|
CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide));
|
||||||
if ( testcollide == false ) {
|
if ( testcollide == false ) {
|
||||||
FAIL_BREAK(errctx, ERR_BEHAVIOR, "Valid collision missed");
|
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Valid collision missed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collision overlapping the left edge
|
// Collision overlapping the left edge
|
||||||
@@ -263,9 +263,9 @@ ErrorContext *test_collide_rectangles_logic(void)
|
|||||||
testrect1.y = 0;
|
testrect1.y = 0;
|
||||||
testrect1.w = 35;
|
testrect1.w = 35;
|
||||||
testrect1.h = 80;
|
testrect1.h = 80;
|
||||||
CATCH(errctx, collide_rectangles(&testrect1, &testrect2, &testcollide));
|
CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide));
|
||||||
if ( testcollide == false ) {
|
if ( testcollide == false ) {
|
||||||
FAIL_BREAK(errctx, ERR_BEHAVIOR, "Valid collision missed");
|
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Valid collision missed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collision overlapping the right edge
|
// Collision overlapping the right edge
|
||||||
@@ -273,9 +273,9 @@ ErrorContext *test_collide_rectangles_logic(void)
|
|||||||
testrect1.y = 0;
|
testrect1.y = 0;
|
||||||
testrect1.w = 60;
|
testrect1.w = 60;
|
||||||
testrect1.h = 80;
|
testrect1.h = 80;
|
||||||
CATCH(errctx, collide_rectangles(&testrect1, &testrect2, &testcollide));
|
CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide));
|
||||||
if ( testcollide == false ) {
|
if ( testcollide == false ) {
|
||||||
FAIL_BREAK(errctx, ERR_BEHAVIOR, "Valid collision missed");
|
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Valid collision missed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collision overlapping the bottom edge
|
// Collision overlapping the bottom edge
|
||||||
@@ -283,9 +283,9 @@ ErrorContext *test_collide_rectangles_logic(void)
|
|||||||
testrect1.y = 65;
|
testrect1.y = 65;
|
||||||
testrect1.w = 80;
|
testrect1.w = 80;
|
||||||
testrect1.h = 32;
|
testrect1.h = 32;
|
||||||
CATCH(errctx, collide_rectangles(&testrect1, &testrect2, &testcollide));
|
CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide));
|
||||||
if ( testcollide == false ) {
|
if ( testcollide == false ) {
|
||||||
FAIL_BREAK(errctx, ERR_BEHAVIOR, "Valid collision missed");
|
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Valid collision missed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not colliding
|
// Not colliding
|
||||||
@@ -293,9 +293,9 @@ ErrorContext *test_collide_rectangles_logic(void)
|
|||||||
testrect1.y = 0;
|
testrect1.y = 0;
|
||||||
testrect1.w = 16;
|
testrect1.w = 16;
|
||||||
testrect1.h = 16;
|
testrect1.h = 16;
|
||||||
CATCH(errctx, collide_rectangles(&testrect1, &testrect2, &testcollide));
|
CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide));
|
||||||
if ( testcollide == true ) {
|
if ( testcollide == true ) {
|
||||||
FAIL_BREAK(errctx, ERR_BEHAVIOR, "Invalid collision reported");
|
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Invalid collision reported");
|
||||||
}
|
}
|
||||||
|
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
@@ -309,11 +309,11 @@ int main(void)
|
|||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, test_rectangle_points_nullpointers());
|
CATCH(errctx, test_akgl_rectangle_points_nullpointers());
|
||||||
CATCH(errctx, test_rectangle_points_math());
|
CATCH(errctx, test_akgl_rectangle_points_math());
|
||||||
CATCH(errctx, test_collide_point_rectangle_nullpointers());
|
CATCH(errctx, test_akgl_collide_point_rectangle_nullpointers());
|
||||||
CATCH(errctx, test_collide_rectangles_nullpointers());
|
CATCH(errctx, test_akgl_collide_rectangles_nullpointers());
|
||||||
CATCH(errctx, test_collide_rectangles_logic());
|
CATCH(errctx, test_akgl_collide_rectangles_logic());
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH_NORETURN(errctx);
|
} FINISH_NORETURN(errctx);
|
||||||
|
|||||||
BIN
util/assets/Actor1.png
Executable file
BIN
util/assets/Actor1.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 51 KiB |
BIN
util/assets/charviewer
Executable file
BIN
util/assets/charviewer
Executable file
Binary file not shown.
16
util/assets/little_guy_facing_down.json
Normal file
16
util/assets/little_guy_facing_down.json
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"spritesheet": {
|
||||||
|
"filename": "../assets/Actor1.png",
|
||||||
|
"frame_width": 48,
|
||||||
|
"frame_height": 48
|
||||||
|
},
|
||||||
|
"name": "little guy facing down",
|
||||||
|
"width": 48,
|
||||||
|
"height": 48,
|
||||||
|
"speed": 0,
|
||||||
|
"loop": false,
|
||||||
|
"loopReverse": false,
|
||||||
|
"frames": [
|
||||||
|
1
|
||||||
|
]
|
||||||
|
}
|
||||||
16
util/assets/little_guy_facing_left.json
Normal file
16
util/assets/little_guy_facing_left.json
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"spritesheet": {
|
||||||
|
"filename": "../assets/Actor1.png",
|
||||||
|
"frame_width": 48,
|
||||||
|
"frame_height": 48
|
||||||
|
},
|
||||||
|
"name": "little guy facing left",
|
||||||
|
"width": 48,
|
||||||
|
"height": 48,
|
||||||
|
"speed": 0,
|
||||||
|
"loop": false,
|
||||||
|
"loopReverse": false,
|
||||||
|
"frames": [
|
||||||
|
13
|
||||||
|
]
|
||||||
|
}
|
||||||
16
util/assets/little_guy_facing_right.json
Normal file
16
util/assets/little_guy_facing_right.json
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"spritesheet": {
|
||||||
|
"filename": "../assets/Actor1.png",
|
||||||
|
"frame_width": 48,
|
||||||
|
"frame_height": 48
|
||||||
|
},
|
||||||
|
"name": "little guy facing right",
|
||||||
|
"width": 48,
|
||||||
|
"height": 48,
|
||||||
|
"speed": 0,
|
||||||
|
"loop": false,
|
||||||
|
"loopReverse": false,
|
||||||
|
"frames": [
|
||||||
|
25
|
||||||
|
]
|
||||||
|
}
|
||||||
16
util/assets/little_guy_facing_up.json
Normal file
16
util/assets/little_guy_facing_up.json
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"spritesheet": {
|
||||||
|
"filename": "../assets/Actor1.png",
|
||||||
|
"frame_width": 48,
|
||||||
|
"frame_height": 48
|
||||||
|
},
|
||||||
|
"name": "little guy facing up",
|
||||||
|
"width": 48,
|
||||||
|
"height": 48,
|
||||||
|
"speed": 0,
|
||||||
|
"loop": false,
|
||||||
|
"loopReverse": false,
|
||||||
|
"frames": [
|
||||||
|
37
|
||||||
|
]
|
||||||
|
}
|
||||||
18
util/assets/little_guy_walking_down.json
Normal file
18
util/assets/little_guy_walking_down.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"spritesheet": {
|
||||||
|
"filename": "../assets/Actor1.png",
|
||||||
|
"frame_width": 48,
|
||||||
|
"frame_height": 48
|
||||||
|
},
|
||||||
|
"name": "little guy walking down",
|
||||||
|
"width": 48,
|
||||||
|
"height": 48,
|
||||||
|
"speed": 1000,
|
||||||
|
"loop": true,
|
||||||
|
"loopReverse": true,
|
||||||
|
"frames": [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
]
|
||||||
|
}
|
||||||
18
util/assets/little_guy_walking_left.json
Normal file
18
util/assets/little_guy_walking_left.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"spritesheet": {
|
||||||
|
"filename": "../assets/Actor1.png",
|
||||||
|
"frame_width": 48,
|
||||||
|
"frame_height": 48
|
||||||
|
},
|
||||||
|
"name": "little guy walking left",
|
||||||
|
"width": 48,
|
||||||
|
"height": 48,
|
||||||
|
"speed": 1000,
|
||||||
|
"loop": true,
|
||||||
|
"loopReverse": true,
|
||||||
|
"frames": [
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
14
|
||||||
|
]
|
||||||
|
}
|
||||||
18
util/assets/little_guy_walking_right.json
Normal file
18
util/assets/little_guy_walking_right.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"spritesheet": {
|
||||||
|
"filename": "../assets/Actor1.png",
|
||||||
|
"frame_width": 48,
|
||||||
|
"frame_height": 48
|
||||||
|
},
|
||||||
|
"name": "little guy walking right",
|
||||||
|
"width": 48,
|
||||||
|
"height": 48,
|
||||||
|
"speed": 1000,
|
||||||
|
"loop": true,
|
||||||
|
"loopReverse": true,
|
||||||
|
"frames": [
|
||||||
|
24,
|
||||||
|
25,
|
||||||
|
26
|
||||||
|
]
|
||||||
|
}
|
||||||
18
util/assets/little_guy_walking_up.json
Normal file
18
util/assets/little_guy_walking_up.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"spritesheet": {
|
||||||
|
"filename": "../assets/Actor1.png",
|
||||||
|
"frame_width": 48,
|
||||||
|
"frame_height": 48
|
||||||
|
},
|
||||||
|
"name": "little guy walking up",
|
||||||
|
"width": 48,
|
||||||
|
"height": 48,
|
||||||
|
"speed": 1000,
|
||||||
|
"loop": true,
|
||||||
|
"loopReverse": true,
|
||||||
|
"frames": [
|
||||||
|
36,
|
||||||
|
37,
|
||||||
|
38
|
||||||
|
]
|
||||||
|
}
|
||||||
68
util/assets/littleguy.json
Normal file
68
util/assets/littleguy.json
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
{
|
||||||
|
"name": "little guy",
|
||||||
|
"movementspeed": 1,
|
||||||
|
"velocity_x": 0.02,
|
||||||
|
"velocity_y": 0.02,
|
||||||
|
"sprite_mappings": [
|
||||||
|
{
|
||||||
|
"state": [
|
||||||
|
"ACTOR_STATE_ALIVE",
|
||||||
|
"ACTOR_STATE_FACE_LEFT",
|
||||||
|
"ACTOR_STATE_MOVING_LEFT"
|
||||||
|
],
|
||||||
|
"sprite": "little guy walking left"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": [
|
||||||
|
"ACTOR_STATE_ALIVE",
|
||||||
|
"ACTOR_STATE_FACE_RIGHT",
|
||||||
|
"ACTOR_STATE_MOVING_RIGHT"
|
||||||
|
],
|
||||||
|
"sprite": "little guy walking right"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": [
|
||||||
|
"ACTOR_STATE_ALIVE",
|
||||||
|
"ACTOR_STATE_FACE_UP",
|
||||||
|
"ACTOR_STATE_MOVING_UP"
|
||||||
|
],
|
||||||
|
"sprite": "little guy walking up"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": [
|
||||||
|
"ACTOR_STATE_ALIVE",
|
||||||
|
"ACTOR_STATE_FACE_DOWN",
|
||||||
|
"ACTOR_STATE_MOVING_DOWN"
|
||||||
|
],
|
||||||
|
"sprite": "little guy walking down"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": [
|
||||||
|
"ACTOR_STATE_ALIVE",
|
||||||
|
"ACTOR_STATE_FACE_UP"
|
||||||
|
],
|
||||||
|
"sprite": "little guy facing up"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": [
|
||||||
|
"ACTOR_STATE_ALIVE",
|
||||||
|
"ACTOR_STATE_FACE_RIGHT"
|
||||||
|
],
|
||||||
|
"sprite": "little guy facing right"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": [
|
||||||
|
"ACTOR_STATE_ALIVE",
|
||||||
|
"ACTOR_STATE_FACE_LEFT"
|
||||||
|
],
|
||||||
|
"sprite": "little guy facing left"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": [
|
||||||
|
"ACTOR_STATE_ALIVE",
|
||||||
|
"ACTOR_STATE_FACE_DOWN"
|
||||||
|
],
|
||||||
|
"sprite": "little guy facing down"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -5,26 +5,27 @@
|
|||||||
#include <SDL3_image/SDL_image.h>
|
#include <SDL3_image/SDL_image.h>
|
||||||
#include <SDL3_mixer/SDL_mixer.h>
|
#include <SDL3_mixer/SDL_mixer.h>
|
||||||
|
|
||||||
#include <sdlerror.h>
|
#include <akerror.h>
|
||||||
#include <sdl3game/assets.h>
|
#include <akgl/assets.h>
|
||||||
#include <sdl3game/iterator.h>
|
#include <akgl/iterator.h>
|
||||||
#include <sdl3game/tilemap.h>
|
#include <akgl/tilemap.h>
|
||||||
#include <sdl3game/heap.h>
|
#include <akgl/heap.h>
|
||||||
#include <sdl3game/game.h>
|
#include <akgl/game.h>
|
||||||
#include <sdl3game/controller.h>
|
#include <akgl/controller.h>
|
||||||
#include <sdl3game/draw.h>
|
#include <akgl/draw.h>
|
||||||
#include <sdl3game/sprite.h>
|
#include <akgl/sprite.h>
|
||||||
#include <sdl3game/actor.h>
|
#include <akgl/actor.h>
|
||||||
#include <sdl3game/registry.h>
|
#include <akgl/registry.h>
|
||||||
|
#include <akgl/error.h>
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
SDL3GControlMap *controlmap;
|
akgl_Actor *actorptr = NULL;
|
||||||
actor *actorptr = NULL;
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
int gamepadids[32];
|
||||||
char *characterjson = NULL;
|
char *characterjson = NULL;
|
||||||
char pathbuf[4096];
|
char pathbuf[4096];
|
||||||
char cwdbuf[1024];
|
char cwdbuf[1024];
|
||||||
@@ -41,18 +42,18 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
|||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
|
|
||||||
FAIL_ZERO_BREAK(errctx, appstate, ERR_NULLPOINTER, "NULL appstate pointer");
|
FAIL_ZERO_BREAK(errctx, appstate, AKERR_NULLPOINTER, "NULL appstate pointer");
|
||||||
FAIL_ZERO_BREAK(errctx, getcwd((char *)&cwdbuf, 1024), ERR_NULLPOINTER, "Couldn't get current working directory");
|
FAIL_ZERO_BREAK(errctx, getcwd((char *)&cwdbuf, 1024), AKERR_NULLPOINTER, "Couldn't get current working directory");
|
||||||
|
|
||||||
strcpy((char *)&game.name, "charviewer");
|
strcpy((char *)&game.name, "charviewer");
|
||||||
strcpy((char *)&game.version, "0.0.1");
|
strcpy((char *)&game.version, "0.0.1");
|
||||||
strcpy((char *)&game.uri, "net.aklabs.libsdl3game.charviewer");
|
strcpy((char *)&game.uri, "net.aklabs.libakgl.charviewer");
|
||||||
game.screenwidth = 640;
|
game.screenwidth = 640;
|
||||||
game.screenheight = 480;
|
game.screenheight = 480;
|
||||||
|
|
||||||
CATCH(errctx, GAME_init());
|
CATCH(errctx, akgl_game_init());
|
||||||
CATCH(errctx, heap_init());
|
CATCH(errctx, akgl_heap_init());
|
||||||
CATCH(errctx, registry_init());
|
CATCH(errctx, akgl_registry_init());
|
||||||
|
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
@@ -69,7 +70,7 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
|||||||
sprintf((char *)&pathbuf, "%s", argv[i]);
|
sprintf((char *)&pathbuf, "%s", argv[i]);
|
||||||
}
|
}
|
||||||
SDL_Log("Loading sprite %s...", (char *)&pathbuf);
|
SDL_Log("Loading sprite %s...", (char *)&pathbuf);
|
||||||
CATCH(errctx, sprite_load_json((char *)&pathbuf));
|
CATCH(errctx, akgl_sprite_load_json((char *)&pathbuf));
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} HANDLE_DEFAULT(errctx) {
|
} HANDLE_DEFAULT(errctx) {
|
||||||
@@ -86,51 +87,25 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
|||||||
sprintf((char *)&pathbuf, "%s", characterjson);
|
sprintf((char *)&pathbuf, "%s", characterjson);
|
||||||
}
|
}
|
||||||
SDL_Log("Loading character %s...", (char *)&pathbuf);
|
SDL_Log("Loading character %s...", (char *)&pathbuf);
|
||||||
CATCH(errctx, character_load_json((char *)&pathbuf));
|
CATCH(errctx, akgl_character_load_json((char *)&pathbuf));
|
||||||
CATCH(errctx, heap_next_actor(&actorptr));
|
CATCH(errctx, akgl_heap_next_actor(&actorptr));
|
||||||
CATCH(errctx, actor_initialize((actor *)actorptr, "player"));
|
CATCH(errctx, akgl_actor_initialize((akgl_Actor *)actorptr, "player"));
|
||||||
actorptr->basechar = SDL_GetPointerProperty(
|
actorptr->basechar = SDL_GetPointerProperty(
|
||||||
REGISTRY_CHARACTER,
|
AKGL_REGISTRY_CHARACTER,
|
||||||
"little guy",
|
"little guy",
|
||||||
NULL);
|
NULL);
|
||||||
FAIL_ZERO_BREAK(errctx, actorptr->basechar, ERR_REGISTRY, "Can't load character 'little guy' from the registry");
|
FAIL_ZERO_BREAK(errctx, actorptr->basechar, AKERR_REGISTRY, "Can't load character 'little guy' from the registry");
|
||||||
actorptr->movement_controls_face = false;
|
actorptr->movement_controls_face = false;
|
||||||
actorptr->state = (ACTOR_STATE_ALIVE | ACTOR_STATE_FACE_DOWN);
|
actorptr->state = (AKGL_ACTOR_STATE_ALIVE | AKGL_ACTOR_STATE_FACE_DOWN);
|
||||||
actorptr->x = 320;
|
actorptr->x = 320;
|
||||||
actorptr->y = 240;
|
actorptr->y = 240;
|
||||||
actorptr->visible = true;
|
actorptr->visible = true;
|
||||||
|
|
||||||
// set up the control map
|
// Open the first gamepad
|
||||||
controlmap = &GAME_ControlMaps[0];
|
FAIL_ZERO_BREAK(errctx, SDL_GetGamepads((int *)&gamepadids), AKGL_ERR_SDL, "%s", SDL_GetError());
|
||||||
controlmap->kbid = 0;
|
SDL_Log("Opening gamepad %d", gamepadids[0]);
|
||||||
controlmap->target = SDL_GetPointerProperty(REGISTRY_ACTOR, "player", NULL);
|
FAIL_ZERO_BREAK(errctx, SDL_OpenGamepad(gamepadids[0]), AKGL_ERR_SDL, "%s", SDL_GetError());
|
||||||
// Move down
|
CATCH(errctx, akgl_controller_default(0, "player", 0, gamepadids[0]));
|
||||||
controlmap->controls[0].key = SDLK_DOWN;
|
|
||||||
controlmap->controls[0].event_on = SDL_EVENT_KEY_DOWN;
|
|
||||||
controlmap->controls[0].event_off = SDL_EVENT_KEY_UP;
|
|
||||||
controlmap->controls[0].handler_on = &SDL3GActor_cmhf_down_on;
|
|
||||||
controlmap->controls[0].handler_off = &SDL3GActor_cmhf_down_off;
|
|
||||||
|
|
||||||
// Move up
|
|
||||||
controlmap->controls[1].key = SDLK_UP;
|
|
||||||
controlmap->controls[1].event_on = SDL_EVENT_KEY_DOWN;
|
|
||||||
controlmap->controls[1].event_off = SDL_EVENT_KEY_UP;
|
|
||||||
controlmap->controls[1].handler_on = &SDL3GActor_cmhf_up_on;
|
|
||||||
controlmap->controls[1].handler_off = &SDL3GActor_cmhf_up_off;
|
|
||||||
|
|
||||||
// Move left
|
|
||||||
controlmap->controls[2].key = SDLK_LEFT;
|
|
||||||
controlmap->controls[2].event_on = SDL_EVENT_KEY_DOWN;
|
|
||||||
controlmap->controls[2].event_off = SDL_EVENT_KEY_UP;
|
|
||||||
controlmap->controls[2].handler_on = &SDL3GActor_cmhf_left_on;
|
|
||||||
controlmap->controls[2].handler_off = &SDL3GActor_cmhf_left_off;
|
|
||||||
|
|
||||||
// Move right
|
|
||||||
controlmap->controls[3].key = SDLK_RIGHT;
|
|
||||||
controlmap->controls[3].event_on = SDL_EVENT_KEY_DOWN;
|
|
||||||
controlmap->controls[3].event_off = SDL_EVENT_KEY_UP;
|
|
||||||
controlmap->controls[3].handler_on = &SDL3GActor_cmhf_right_on;
|
|
||||||
controlmap->controls[3].handler_off = &SDL3GActor_cmhf_right_off;
|
|
||||||
|
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
@@ -147,10 +122,10 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
|
|||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
FAIL_ZERO_BREAK(errctx, appstate, ERR_NULLPOINTER, "NULL appstate pointer");
|
FAIL_ZERO_BREAK(errctx, appstate, AKERR_NULLPOINTER, "NULL appstate pointer");
|
||||||
FAIL_ZERO_BREAK(errctx, event, ERR_NULLPOINTER, "NULL event pointer");
|
FAIL_ZERO_BREAK(errctx, event, AKERR_NULLPOINTER, "NULL event pointer");
|
||||||
|
|
||||||
CATCH(errctx, controller_handle_event(appstate, event));
|
CATCH(errctx, akgl_controller_handle_event(appstate, event));
|
||||||
if (event->type == SDL_EVENT_QUIT) {
|
if (event->type == SDL_EVENT_QUIT) {
|
||||||
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
|
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
|
||||||
}
|
}
|
||||||
@@ -163,17 +138,17 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
|
|||||||
SDL_AppResult SDL_AppIterate(void *appstate)
|
SDL_AppResult SDL_AppIterate(void *appstate)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
iterator opflags;
|
akgl_Iterator opflags;
|
||||||
|
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
|
|
||||||
BITMASK_CLEAR(opflags.flags);
|
AKGL_BITMASK_CLEAR(opflags.flags);
|
||||||
BITMASK_ADD(opflags.flags, ITERATOR_OP_UPDATE);
|
AKGL_BITMASK_ADD(opflags.flags, AKGL_ITERATOR_OP_UPDATE);
|
||||||
BITMASK_ADD(opflags.flags, ITERATOR_OP_RENDER);
|
AKGL_BITMASK_ADD(opflags.flags, AKGL_ITERATOR_OP_RENDER);
|
||||||
GAME_draw_background(game.screenwidth, game.screenheight);
|
akgl_draw_background(game.screenwidth, game.screenheight);
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, tilemap_draw(renderer, (tilemap *)&gamemap, &camera, i));
|
CATCH(errctx, akgl_tilemap_draw(renderer, (akgl_Tilemap *)&gamemap, &camera, i));
|
||||||
SDL_EnumerateProperties(REGISTRY_ACTOR, ®istry_iterate_actor, (void *)&opflags);
|
SDL_EnumerateProperties(AKGL_REGISTRY_ACTOR, &akgl_registry_iterate_actor, (void *)&opflags);
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} HANDLE_DEFAULT(errctx) {
|
} HANDLE_DEFAULT(errctx) {
|
||||||
|
|||||||
Reference in New Issue
Block a user