在这篇文章中,我将描述我移植 3D 编辑器原型的经验 Android 上的 Cube Art Project。
首先,让我们看看模拟器中运行的结果;带有红色 3D 立方体光标的编辑器:

为了成功组装,您必须执行以下操作:
- 安装最新的 Android SDK 和 NDK(NDK 版本越新越好)。
- 下载 SDL2 源代码,从那里获取模板来构建 Android 应用程序。
- 将 SDL Image、SDL Mixer 添加到程序集中。
- 添加我的游戏引擎和工具包的库及其依赖项(GLM、现代 C++ 的 JSON)
- 调整 Gradle 的程序集文件。
- 调整 C++ 代码以与 Android 兼容,更改受影响的平台相关组件(OpenGL ES、图形上下文初始化)
- 在模拟器上构建并测试项目。
项目模板
加载源SDL、SDL Image、SDL Mixer:
https://www.libsdl.org/download-2.0.php
docs 文件夹包含使用 android 项目模板的详细说明;将 android-project 目录复制到单独的文件夹,创建符号链接或将 SDL 文件夹复制到 android-project/app/jni。
我们用正确的标识符替换 avd 标志,从 Sdk:
目录启动 android 模拟器
cd ~/Android/Sdk/emulator
./emulator -avd Pixel_2_API_24
在脚本中指定路径,组装项目:
rm -rf app/build || true
export ANDROID_HOME=/home/demensdeum/Android/Sdk/
export ANDROID_NDK_HOME=/home/demensdeum/Android/android-ndk-r21-beta2/
./gradlew clean build
./gradlew installDebug
应使用文件中的 C 代码组装 SDL 项目模板
android-sdl-test-app/cube-art-project-android/app/jni/src/YourSourceHere.c
依赖项
下载SDL_image、SDL_mixer的源代码:
https://www.libsdl.org/projects/SDL_image/
https://www.libsdl.org/projects/SDL_mixer/
加载项目的依赖项,例如我的共享库:
https://gitlab.com/demensdeum/FlameSteelCore/
https://gitlab.com/demensdeum/FlameSteelCommonTraits
https://gitlab.com/demensdeum/FlameSteelBattleHorn
https://gitlab.com/demensdeum/FlameSteelEngineGameToolkit/
https://gitlab.com/demensdeum/FlameSteelEngineGameToolkitFSGL
https://gitlab.com/demensdeum/FSGL
https://gitlab.com/demensdeum/cube-art-project
我们将所有这些上传到 app/jni,每个“模块”放入一个单独的文件夹,例如 app/jni/FSGL。接下来,您可以选择查找 Application.mk 和 Android.mk 文件的工作生成器,我没有找到它们,但也许有一个基于 CMake 的简单解决方案。点击链接并开始熟悉 Android NDK 的程序集文件格式:
https://developer.android.com/ndk/guides/application_mk
https://developer.android.com/ndk/guides/android_mk
您还应该了解 NDK 中不同的 APP_STL 实现:
https://developer.android.com/ndk/guides/cpp-support.html
熟悉后,我们为每个“模块”创建一个 Android.mk 文件,然后是共享库 Cube-Art-Project 的示例汇编文件:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
APP_STL := c++_static
APP_CPPFLAGS := -fexceptions
LOCAL_MODULE := CubeArtProject
LOCAL_C_INCLUDES := $(LOCAL_PATH)/src $(LOCAL_PATH)/../include $(LOCAL_PATH)/../include/FlameSteelCommonTraits/src/FlameSteelCommonTraits
LOCAL_EXPORT_C_INCLUDES = $(LOCAL_PATH)/src/
define walk
$(wildcard $(1)) $(foreach e, $(wildcard $(1)/*), $(call walk, $(e)))
endef
ALLFILES = $(call walk, $(LOCAL_PATH)/src)
FILE_LIST := $(filter %.cpp, $(ALLFILES))
$(info CubeArtProject source code files list)
$(info $(FILE_LIST))
LOCAL_SRC_FILES := $(FILE_LIST:$(LOCAL_PATH)/%=%)
LOCAL_SHARED_LIBRARIES += FlameSteelCore
LOCAL_SHARED_LIBRARIES += FlameSteelBattleHorn
LOCAL_SHARED_LIBRARIES += FlameSteelCommonTraits
LOCAL_SHARED_LIBRARIES += FlameSteelEngineGameToolkit
LOCAL_SHARED_LIBRARIES += FlameSteelEngineGameToolkitFSGL
LOCAL_SHARED_LIBRARIES += FSGL
LOCAL_SHARED_LIBRARIES += SDL2
LOCAL_SHARED_LIBRARIES += SDL2_image
LOCAL_LDFLAGS := -static-libstdc++
include $(BUILD_SHARED_LIBRARY)
任何有经验的 CMake 用户都会从第一行开始理解这个配置,格式非常相似,Android.mk 缺少 GLOB_RECURSIVE,所以你必须使用 walk 函数递归搜索源文件。
我们更改 Application.mk、Android.mk 来构建 C++ 而不是 C 代码:
APP_ABI := armeabi-v7a arm64-v8a x86 x86_64
APP_PLATFORM=android-16
APP_STL := c++_static
APP_CPPFLAGS := -fexceptions
重命名YourSourceHere.c -> YourSourceHere.cpp,grep条目,更改程序集中的路径,例如:
app/jni/src/Android.mk:LOCAL_SRC_FILES := YourSourceHere.cpp
接下来,尝试构建项目,如果编译器看到缺少标头的错误,请检查 Android.mk 中路径的正确性;如果链接器出现“未定义引用”等错误,请检查程序集中的源代码文件是否指定正确;可以通过在 Android.mk 文件中指定 $(info $(FILE_LIST)) 来跟踪列表。不要忘记双重链接机制,使用 LOCAL_SHARED_LIBRARIES 键中的模块并通过 LD 进行正确链接,例如 FSGL:
LOCAL_LDLIBS := -lEGL -lGLESv2
适应和启动
我必须改变一些东西,例如,从 iOS 和 Android 的构建中删除 GLEW,重命名一些 OpenGL 调用,添加 EOS 后缀(glGenVertexArrays -> glGenVertexArraysOES),包含用于缺少的现代调试功能的宏,锦上添花的是隐式包含指示宏的 GLES2 标头GL_GLEXT_PROTOTYPES 1:
#define GL_GLEXT_PROTOTYPES 1
#include "SDL_opengles2.h"
我还观察到第一次启动时出现黑屏,并出现类似“E/libEGL: validate_display:255 error 3008 (EGL_BAD_DISPLAY)”的错误,更改了 SDL 窗口的初始化、OpenGL 配置文件,一切正常:
SDL_DisplayMode mode;
SDL_GetDisplayMode(0,0,&mode);
int width = mode.w;
int height = mode.h;
window = SDL_CreateWindow(
title,
0,
0,
width,
height,
SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN | SDL_WINDOW_RESIZABLE
);
SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES );
在模拟器上,应用程序默认安装为 SDL 图标和名称“Game”。
我只需探索基于CMake自动生成程序集文件的可能性,或者将所有平台的程序集迁移到Gradle即可;然而,CMake 仍然是正在进行的 C++ 开发的事实上的选择。
源代码
https://gitlab.com/demensdeum/android- sdl-test-app
https://gitlab.com/demensdeum/android-sdl-test-app/tree/master/cube-art-project-android
来源
https://developer.android.com/ ndk/guides/cpp-support.html
https://developer.android.com/ndk/guides/application_mk
https://developer.android.com/ndk/guides/android_mk
https://lazyfoo.net/tutorials/SDL/52_hello_mobile/android_windows/index.php
https://medium.com/androiddevelopers/getting-started-with-c-and-android-native-activities-2213b402ffff