Repository navigation
Build and CI
Собрать порт можно четырьмя путями, и они не равноценны: один кроссплатформенный и главный, три остальных - короткие дороги под конкретную машину. Плюс два скрипта, которые игру не собирают вообще, а проверяют.
CMakeLists.txt - то, чем пользуется и CI, и любой сторонний сборщик:
set_target_properties(jumpyball PROPERTIES C_STANDARD 90 C_EXTENSIONS ON)Стандарт C90, но расширения включены нарочно: snprintf появился в C99, и в
чистом режиме -std=c89 системные заголовки его просто не объявляют. Отсюда
gnu89 вместо c89 - единственное послабление, и оно про заголовки, а не про
код. Строгость никуда не делась, её проверяют отдельно (ниже).
SDL2 ищется в три приёма, по убыванию точности:
-
find_package(SDL2 CONFIG QUIET)- vcpkg, Conan, любой пакет сSDL2Config.cmake; -
find_package(SDL2 MODULE QUIET)- классическийFindSDL2.cmake; -
pkg_check_modules(SDL2 REQUIRED sdl2)- Linux/BSD сpkg-config.
| Опция | По умолчанию | Что делает |
|---|---|---|
JUMPYBALL_WARNINGS |
ON |
/W4 на MSVC, -Wall -Wextra на остальных |
JUMPYBALL_BUILD_TOOLS |
OFF | собирает tools/modtest.c - плеер .tkm без игры |
JUMPYBALL_COPY_ASSETS |
ON | POST_BUILD копирует BITMAP/, Sounds/, Musics/ к бинарнику |
Цель объявлена как add_executable(jumpyball WIN32 ...), на Windows линкуется
shell32, на остальных системах ищется libm, install кладёт бинарник в
bin.
-
build.cmd- прямойclбез всякого cmake, x86:/W4 /O2 /TC /MT, 24 файла в одной строке,/SUBSYSTEM:WINDOWSи/NODEFAULTLIB:msvcrt.lib- иначе/MTиSDL2.libзатащат две разные копии рантайма./TCзначит «это всё C», а не «догадайся по расширению». Дальше скрипт сам копируетSDL2.dllи три папки ассетов вbuild\. -
build-cmake.cmd- тот же cmake, но с жёстко прописанными путями кvcvars32.bat,cmake.exe,ninja.exeи тулчейну vcpkg,VCPKG_TARGET_TRIPLET=x86-windows. -
tools/android_prepare.sh- Android. Скачивает SDL 2.32.10 с GitHub, разворачивает егоandroid-projectвbuild-android/, копирует весь SDL вapp/jni/SDL, всеjb_*.cиjb_*.hвapp/jni/src, ассеты вapp/src/main/assets, и правитbuild.gradleчерезsed:applicationId io.github.katamaran21.jumpyball,versionCode 3,versionName 1.2,minSdkVersion 21,APP_ABI := armeabi-v7a arm64-v8a x86 x86_64. Дальше -./gradlew assembleDebug.
android/Android.mk набирает исходники как
$(notdir $(wildcard $(LOCAL_PATH)/*.c)), поэтому новый файл порта попадает в
APK сам, без правки скрипта.
-
tools/c89check.cmd-clang-tidyиз Build Tools с-std=c89 -pedantic-errors -Wallпо каждому.c. Объектных файлов нет, только разбор: ищется то, что MSVC молча принимает, а строгий C89 отвергает. -
tools/modtest.cmd- собираетmodtest.exeизmodtest.c+jb_mod.c+jb_mod_effects.c, чтобы гонять.tkmбез игры и без SDL, см. Audio-and-TKM.
Разбор - в jb_main.c: четыре именованных ключа и два позиционных аргумента.
| Аргумент | Смысл |
|---|---|
--level=N |
сразу в уровень N, минуя меню |
--screen=N |
стартовый экран меню (screen_id, см. Menu-and-controls) |
--index=N |
стартовый пункт |
--unlocked=N |
max_unlocked |
| первое число | масштаб окна, < 1 -> 2 |
| второе слово | путь для дампа кадра |
Дамп - это и есть механизм проверки в CI:
if (dump_path && ticks > 1500u) {
FILE *fp = fopen(dump_path, "wb");
if (fp) { fwrite(back->pixels, sizeof(uint16_t), JB_VIEW_W * JB_VIEW_H, fp); fclose(fp); }
break;
}Полторы секунды на прогрев (за это время таймер успевает выйти из отрицательной
секунды, см. Levels), один кадр в файл, выход. Размер файла всегда один и тот
же: 240 * 320 * 2 = 153600 байт, потому что бекбуфер 16-битный.
Ещё две переменные окружения:
-
JUMPYBALL_ASSETS- папка, где лежатBITMAP/,Sounds/,Musics/(jb_assets.c); -
JUMPYBALL_TOUCH- включить сенсорную панель на десктопе. На Android она включена всегда (#ifdef __ANDROID__), а на десктопе переменная дополнительно ставитSDL_HINT_MOUSE_TOUCH_EVENTS=1(мышь работает как палец) и делает окноSDL_WINDOW_RESIZABLE, потому что раскладка панели считается от размеров окна.
.github/workflows/build.yml - три задачи. Триггеры: push в main, любой pull
request, ручной workflow_dispatch. Задачи release здесь нет: артефакты
собираются и выкладываются как artifacts прогона, но релиз не публикуется.
Матрица из двух раннеров: ubuntu-24.04 (x86_64) и ubuntu-24.04-arm (arm64).
-
Строгий C89 - цикл по всем
*.c:gcc -std=c89 -pedantic-errors -Wall -Wextra $sdl -c "$f" -o /dev/null. Здесь именноc89, безgnu, и-pedantic-errors- предупреждение становится ошибкой. Это и есть та проверка, которую cmake себе позволить не может. - Обычная сборка через cmake.
-
Два безголовых дампа:
SDL_VIDEODRIVER=dummy SDL_AUDIODRIVER=dummy timeout 60 ./jumpyball 1 frame.raw, проверяется код возврата 0 и размер файла ровно$((240 * 320 * 2)). Второй прогон - то же самое сJUMPYBALL_TOUCH=1.
Матрица windows-latest (x86 / Win32 / x86-windows) и windows-11-arm
(arm64 / ARM64 / arm64-windows), SDL2 из vcpkg. Запуск через
Start-Process .\jumpyball.exe -ArgumentList '1','frame.raw' -Wait -PassThru, те
же две проверки - код выхода и длина файла.
JDK temurin 17, sh tools/android_prepare.sh, ./gradlew --no-daemon assembleDebug, а затем проверка содержимого APK через unzip -l. В архиве
обязаны быть:
-
lib/<abi>/libmain.soиlib/<abi>/libSDL2.soдля всех четырёх ABI; -
assets/BITMAP/204.bmp,assets/Sounds/sblam.wav,assets/Musics/music1.tkm.
CI ловит не только «скомпилировалось», но и «ассеты действительно попали в APK» - самая частая поломка при сборке под Android.
Дамп берётся из бекбуфера (Platform_BackBuffer()), а сенсорная панель рисуется
в окно уже после того, как кадр скопирован: SDL_RenderCopy -> Touch_Draw ->
SDL_RenderPresent в jb_platform_sdl2.c. Поэтому прогон с JUMPYBALL_TOUCH=1
проверяет, что игра не падает с включённой панелью и что раскладка не ломает
кадр, но саму панель в файле не увидеть - см. Menu-and-controls.
Устройство порта
Сборка и происхождение