# The top-down JRPG tutorial game, quoted by docs/20-tutorial-jrpg.md. # # It is a real target built by `all`, not a snippet: a tutorial whose program # does not compile is the failure this whole documentation effort exists to # stop, and the chapter's `c excerpt=` blocks fail the moment this source moves # under them. add_executable(jrpg jrpg.c world.c textbox.c ) target_link_libraries(jrpg PRIVATE akstdlib::akstdlib akerror::akerror akgl SDL3::SDL3 SDL3_ttf::SDL3_ttf SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer jansson::jansson -lm) target_include_directories(jrpg PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") target_compile_options(jrpg PRIVATE ${AKGL_WARNING_FLAGS}) # The game finds its data through two absolute paths baked in here. A game that # ships would install its assets and resolve them against SDL_GetBasePath(); a # tutorial has to run from the build tree, from the source tree, and from # whatever working directory CTest hands it, so the paths are compiled in. get_filename_component(JRPG_REPO_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../.." ABSOLUTE) target_compile_definitions(jrpg PRIVATE JRPG_ASSET_DIR="${JRPG_REPO_ROOT}/docs/tutorials/assets/jrpg" # tests/assets/akgl_test_mono.ttf, which ships beside its licence file. JRPG_FONT_FILE="${JRPG_REPO_ROOT}/tests/assets/akgl_test_mono.ttf" ) # The vendored SDL satellite libraries land in per-project subdirectories that # are not on the loader's default search path, exactly as they do for the test # suites. AKGL_VENDORED_RPATH is set by the top-level CMakeLists.txt and is only # defined when something was actually vendored. if(AKGL_VENDORED_DEPENDENCIES) set_target_properties(jrpg PROPERTIES BUILD_RPATH "${AKGL_VENDORED_RPATH}") endif() # The headless smoke run. `--demo` drives the arrow keys from a script and steps # the physics clock by a fixed 1/60 s, so the run is deterministic and finishes # in well under a second; `--frames` bounds it. Between them the run walks the # player into a wall, opens the text box, and exercises the follower's render # hook -- rather than just proving that main() returns. # # add_test() reaches the real command here: the top-level CMakeLists.txt shadows # it to suppress the vendored projects' registrations and lifts the suppression # again long before examples/ is added. add_test(NAME example_jrpg COMMAND jrpg --frames 320 --demo) set_tests_properties(example_jrpg PROPERTIES TIMEOUT 120) # set_property, not set_tests_properties: the latter parses its PROPERTIES # arguments as name/value *pairs*, so a semicolon-separated value is split and # every element after the first is consumed as a bogus property name. The # audio and render entries of this list were silently lost that way -- # invisible on any machine whose real audio device works, and found the first # time CI ran on a runner without one. set_property(TEST example_jrpg PROPERTY ENVIRONMENT "SDL_VIDEODRIVER=dummy" "SDL_RENDER_DRIVER=software" "SDL_AUDIODRIVER=dummy" ) # LD_LIBRARY_PATH for the vendored satellite libraries. Only needed when they # were vendored; an installed build resolves them normally. if(AKGL_VENDORED_DEPENDENCIES) if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.22") set(JRPG_TEST_ENV_MOD "") foreach(dir IN LISTS AKGL_TEST_LIBPATH) list(APPEND JRPG_TEST_ENV_MOD "LD_LIBRARY_PATH=path_list_prepend:${dir}") endforeach() set_property(TEST example_jrpg PROPERTY ENVIRONMENT_MODIFICATION ${JRPG_TEST_ENV_MOD}) else() string(REPLACE ";" ":" JRPG_TEST_LIBPATH_JOINED "${AKGL_TEST_LIBPATH}") set_property(TEST example_jrpg APPEND PROPERTY ENVIRONMENT "LD_LIBRARY_PATH=${JRPG_TEST_LIBPATH_JOINED}:$ENV{LD_LIBRARY_PATH}") endif() endif()