示例

Android Game Development Extension 的示例展示了如何使用该扩展程序的主要功能。本主题介绍了运行这些功能所需的示例和设置。

下载页面上提供了以下示例:

  • HelloJNI:一个入门项目。
  • Endless-Tunnel:一个仅适用于 Android 的项目。
  • Teapot:一个适用于 Windows 和 Android 的跨平台项目。
  • AssemblyCode-Link-Objects:一个具有汇编源代码的模板项目。

准备工作

  • 安装 Android Game Development Extension 和示例。如需了解详情,请参阅快速入门。此外,本主题还以 Android 版 Teapot 示例为例介绍了如何构建并运行示例。

  • 项目配置指南介绍了如何为使用该扩展程序的项目配置设置,例如添加 Android 平台和 APK。

HelloJNI

HelloJNI 示例是一个简单的项目,它会在应用窗口中显示“Hello From JNI”消息。该项目针对 Windows 和 Android 使用一组不同的源代码。

  • Android 源代码和 Gradle 构建脚本目录:HelloJNI\AndroidPackaging
  • Windows 源代码和 Visual Studio 项目目录:HelloJNI

构建项目时,Visual Studio 会将以下设置传递给应用级 build.gradle 文件。您可以通过修改 Gradle 构建脚本更改这些设置。

  • MSBUILD_NDK_VERSION
  • MSBUILD_MIN_SDK_VERSION
  • MSBUILD_JNI_LIBS_SRC_DIR
  • MSBUILD_ANDROID_OUTPUT_APK_NAME
  • MSBUILD_ANDROID_GRADLE_BUILD_OUTPUT_DIR

如需设置和运行示例,请执行以下操作:

  1. 在 Visual Studio 中,打开并构建 HelloJNI 示例。
  2. 添加一个 Android arm64-v8a 平台。如需了解详情,请参阅添加 Android 平台
  3. 向新平台添加一个 Android APK 项
  4. 编译项目。
  5. 添加以下 Android 平台,然后将 Android APK 项添加到每个平台:Android-armeabi-v7aAndroid-x86Android-x86_64
  6. 构建并运行示例。

Endless-Tunnel

Endless-Tunnel 示例是一款 Android 游戏,玩家需要在努力到达隧道尽头的过程中收集白色立方体。它从 GitHub 上的 Android NDK 代码库中的 OpenGL 示例移植而来。此示例不提供游戏的 Windows 版本。

此示例已配置其设置和 Android 平台,因此您可以在 Visual Studio 中构建并运行项目,无需进行任何修改。当您打开该解决方案时,Solution Explorer 会显示以下模块:

  • endless-tunnel:该应用模块会显示游戏逻辑。
  • glm:OpenGL Math 代码库(构建为静态库)的快照。
  • native_app_glue:与 NativeActivity 对象通信的 NDK 封装容器。

Teapot

Teapot 示例显示了一个使用 OpenGL ES 呈现并移植到 Android Game Development Extension 的 Classic Teapot,用于展示以下功能:

  • 跨平台项目开发:您可以针对 Windows 和 Android 构建 Teapot 示例。
  • 自定义 Android 打包功能使用情况:Gradle 构建脚本已移至该示例的根目录(Teapot.sln 文件所在的位置)。
  • 自定义 Android 配置,演示了如何使用 Address Sanitizer (ASan) 和 Hardware Address Sanitizer (HWASan)。

Teapot 示例的实现分为多个部分,这对大型跨平台应用和游戏而言很常见:

  • GameApplication 模块:定义用户操作和应用状态,例如用户旋转茶壶或更新应用统计信息。
  • GameEngine 模块:实现核心呈现模块。

如需设置此示例并在 Android 上运行该示例,请参阅快速入门。如需设置此示例并在 Windows 上运行该示例,请执行以下操作:

  1. 安装 GLEW:
    1. 下载并解压缩 GLEW
    2. 将二进制文件从 $your-glew-directory\bin\Release\x64 复制到 %SystemRoot%\system32
  2. 安装 freeglut:
    1. 下载并解压缩 freeglut
    2. $your-freeglut-directory\bin\x86\freeglut.dll 复制到 %SystemRoot%\system32
  3. 添加 freeglut 项目依赖项:
    1. 在 Visual Studio 中打开 Teapot.sln
    2. 在菜单中,依次点击 Debug > x64 > Local Windows Debugger
    3. Solution Explorer 中,右键点击 GameApplication,然后依次选择 Properties > C/C++ > General > Additional Include Directories
    4. $your-freeglut-dir\include 添加到该路径。
      “Additional Include Directories”对话框的屏幕截图。
    5. 点击 OK
    6. 依次选择 Linker > General > Additional Library Directories
    7. $your-freeglut-dir\lib\x64 添加到该路径。 “Additional Library Directories”对话框的屏幕截图。
    8. 点击 OK
    9. 依次选择 Linker > General > Additional Library Directories
    10. freeglut.lib 添加到该路径。
    11. 点击 OK
  4. 添加 GLEW 项目依赖项:
    1. Solution Explorer 窗格中,右键点击 GameApplication,然后依次选择 Properties > C/C++ > General > Additional Include Directories
    2. $your-glew-dir\include 添加到该路径。
    3. 点击 OK
    4. 依次选择 Linker > General > Additional Library Directories
    5. $your-glew-dir\lib\Release\x86 添加到该路径。
    6. 点击 OK
    7. 依次选择 Linker > General > Additional Library Directories
    8. glew32.lib 添加到该路径。
    9. 点击 OK
  5. 在 Windows 上运行此示例:
    1. 在 Visual Studio 工具栏上,点击 Local Windows Debugger 运行按钮。
    2. 示例应如下所示:
      在 Windows 上运行的 Teapot 示例的屏幕截图。

这是一个模板项目,演示了如何基于汇编源代码和 C/C++ 源代码生成 Android 原生库。下面是提供的主要组件:

  • AssemblyCode-Link-Objects:基于 C++ 源代码和汇编源代码构建的主要 Android 原生库。
  • StaticLib:用于导出 from_static_lib_assembly_code_as 函数的辅助静态库。

此项目支持多个架构。每个受支持的架构都有其自己的源文件,可实现从 StaticLib 导出的函数。您只能为要构建的平台添加汇编源文件。此项目使用自定义构建工具在 build 中添加汇编文件。

如需设置和构建示例,请执行以下操作:

  1. 在 Visual Studio 中,验证是否已为汇编文件配置自定义构建工具:
    1. Solution Explorer 中,右键点击汇编文件,然后点击 Properties。此操作会打开该文件的 Properties Pages 对话框。
    2. 选择配置和平台,例如为 Android-arm64-v8a 选择 All configurations
    3. 确保 General > Exclude from Build 设置为 No
    4. 确保 General > Item Type 设置为 Custom Build Tool
    5. 如果有要应用的更改,请点击 Apply
    6. 确保 Configuration Properties > Custom Build Tool > Command Line 设置为 $(AsToolExe) -o "$(IntDir)%(FileName).o" %(FullPath)。NDK 会为每个 CPU 架构添加单独的汇编程序,并且 $(AsToolExe) 会映射到正确的汇编程序。此示例使用 NDK 工具链同时构建 x86 和 x86_64 Android 项目。如果您想要将 yasm 用于 x86_64 Android 平台,请改用 $(YasmToolExe)
    7. 确保 Configuration Properties > Custom Build Tool > Outputs 设置为 $(IntDir)%(FileName).o。此字符串必须包含在 Command Line 设置中。
    8. 确保 Configuration Properties > Custom Build Tool > Link Objects 设置为 Yes

    例如,Android-arm64-v8a 设置应类似于以下屏幕截图:

    “Property Pages”中“Custom Build Tool”的屏幕截图。
  2. 构建项目。这将构建 libAssmeblyCodeLinkObjects.so 文件:
    1. 打开 AssemblyCode-Link-Objects.sln 文件。
    2. 在菜单中,依次点击 Build > Build Solution
  3. 如需确认函数是否已正确导出到 Android 库,请使用 nm.exe NDK 工具:
    1. 在命令行中,进入示例目录。
    2. 转到由您的 build 生成的 Android 库位置。对于 arm64-v8a 平台,默认位置类似于 $sample_dir\$solution_configuration\$solution_platform\$platform$sample_dir\Debug\Android-arm64-v8a\arm64-v8a
    3. 运行以下命令,验证已导出的符号部分是否包含相应函数:
        \ndk\toolschains\llvm\prebuilt\windows-x86_64\aarch64-linux-android\bin\nm.exe --defined-only \Debug\Android-arm64-v8a\arm64-v8a\libAssmeblyCodeLinkObjects.so

      您应该会在输出中看到包含以下内容的符号列表:

         T from_shared_object_assembly_code_as
         T from_static_lib_assembly_code_as

PoolAllocator

PoolAllocator 示例是一个 Android 应用,它具有基于池的内存分配器,可非常高效地提供固定大小的块。

分配器会在初始化时使用 mmap 预分配整个内存。系统使用链表跟踪可用块。然后,内存分配是一种快速的 O(1) 操作,用于返回链表的头部,而取消分配也是 O(1) 操作,因为它会将块添加到链表的后面。

该示例包含两个用于使用 HWASan 的解决方案配置。

  • HWASan:此配置演示了将 HWASan 与自定义内存分配器搭配使用的最简单方法。内存分配器的内部实现已替换为由 HWASan 自动跟踪的 malloc/free 调用。虽然内存分配器不再作为基于池的分配器运行,但 HWASan 仍可帮助您识别重要内存 bug,例如释放后使用。

  • HWASan-Advanced:此配置演示了如何将 HWASan 完全集成到自定义内存分配器中,而无需更改分配器使用的原始分配机制。它使用 HWASan 标记方法为预分配池中的内存块添加标记,将块大小向上舍入到 HWASan 所需的最小块大小,并在块返回到池时重置标记。

使用 HWASan 配置,因为它更简单,并且可以帮助您发现常见的内存 bug。如果您想了解 HWASan 的运作方式,或者想在使用 HWASan 时保留内存分配器的内部语义,请探索 HWASan-Advanced 配置的实现。