AGDK

限制与要求

Android SDK 16 和 NDK version 17 以上:

  • GameActivity
  • GameController
  • GameTextInput
  • Oboe

Android SDK 14 和 NDK version 14 以上:

  • Android Performance Tuner
  • Frame Pacing

架构支持:

  • armv7a
  • arm64
  • x86
  • x86_64

GameActivity

设计思想

  1. Android端,设计了一个中间层 GameActivity,实现了跟 native 通信。游戏的 MainActivity 需要继承自 GameActivity。
  2. native 端,同步生成一个 GameActivity 结构体,保存各种 java 信息。
  3. native 端,实现了一套中间层逻辑 “glue”,维护 java 消息与 游戏 native 逻辑的交互,相关的各种状态信息存贮在一个 android_app 的结构体中。
  4. glue 在 onCreate 时,会创建一个 native 线程,在此线程中执行游戏逻辑。(glue 规定了游戏的入口为 android_main 函数)
  5. 游戏需要实现 android_main,并在此函数中实现 GameLoop。包括处理 java 层传来的生命周期事件、游戏帧逻辑。

源码分析

GameActivity

GameActivity_glue

使用 GameActivity

java 端

游戏 Main Activity 继承自 GameActivity,并完成 native library 加载。

1
2
3
4
5
6
7
8
9
import com.google.androidgamesdk.GameActivity;

public class YourGameActivity extends GameActivity {
static {
// Load the native library.
// The name "game" depends on your CMake configuration.
System.loadLibrary("game");
}
}

Native 端

  1. 在项目中引入 GameActivity.cpp、gametextinput.cpp、android_native_app_glue.c。
  2. 引入 android_native_app_glue 实现 android_main。

AGDK 在独立的线程(非主线程)中调用 android_main,并传递一个 android_app 的结构体,游戏需要在 loop 中通过此 android_app 处理各种事件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
extern "C" {

void android_main(struct android_app* app) {
GameLoop(app);
}

};

void GameLoop(struct android_app* app) {
app->userData = this;
app->onAppCmd = _handle_cmd;
//app->onInputEvent = _handle_input_proxy;

while (1) {
int events;
struct android_poll_source* source;

// If not animating, block until we get an event; if animating, don't block.
while ((ALooper_pollAll(IsAnimating() ? 0 : -1, NULL, &events, (void **) &source)) >= 0) {

// process 间接调用 app->onAppCmd
if (source != NULL) {
source->process(mApp, source);
}

// 接收到 MainActivity onDestroy 事件
if (mApp->destroyRequested) {
return;
}
}

if (IsAnimating()) {
DoFrame();
}
}
}


bool IsAnimating()
{
return mIsVisible;// && mHasFocus && mHasWindow;
}

static void _handle_cmd(struct android_app* app, int32_t cmd)
{
switch (cmd) {
case APP_CMD_SAVE_STATE:
// The system has asked us to save our current state.
app->savedState = malloc(sizeof(mState));
*(app->savedState) = mState;
app->savedStateSize = sizeof(mState);
break;

case APP_CMD_STOP:
mIsVisible = false;
break;
case APP_CMD_START:
mIsVisible = true;
break;
case APP_CMD_PAUSE:
case APP_CMD_RESUME:
case APP_CMD_CONFIG_CHANGED:
break;
}
}


参考

https://developer.android.google.cn/games/agdk