gameplay-main-android.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. #ifdef __ANDROID__
  2. #include "gameplay.h"
  3. #include <android/sensor.h>
  4. #include <android_native_app_glue.h>
  5. #include <android/log.h>
  6. #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__))
  7. using namespace gameplay;
  8. extern struct android_app* __state;
  9. AAssetManager* __assetManager;
  10. std::string __assetsPath;
  11. extern ASensorManager* __sensorManager;
  12. extern const ASensor* __accelerometerSensor;
  13. extern ASensorEventQueue* __sensorEventQueue;
  14. extern ASensorEvent __sensorEvent;
  15. extern Keyboard::Key getKey(int keycode, int metastate);
  16. bool __initialized;
  17. /**
  18. * Process the next input event.
  19. */
  20. static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)
  21. {
  22. Platform* platform = static_cast<Platform*>(app->userData);
  23. if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION)
  24. {
  25. int32_t data = AMotionEvent_getAction(event);
  26. int contactIndex = data >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
  27. Touch::TouchEvent touchEvent;
  28. switch (data & AMOTION_EVENT_ACTION_MASK)
  29. {
  30. case AMOTION_EVENT_ACTION_DOWN:
  31. touchEvent = Touch::TOUCH_PRESS;
  32. break;
  33. case AMOTION_EVENT_ACTION_UP:
  34. touchEvent = Touch::TOUCH_RELEASE;
  35. break;
  36. case AMOTION_EVENT_ACTION_MOVE:
  37. touchEvent = Touch::TOUCH_MOVE;
  38. break;
  39. }
  40. Game::getInstance()->touchEvent(touchEvent, AMotionEvent_getX(event, 0), AMotionEvent_getY(event, 0), contactIndex);
  41. return 1;
  42. }
  43. else if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY)
  44. {
  45. int32_t action = AKeyEvent_getAction(event);
  46. int32_t keycode = AKeyEvent_getKeyCode(event);
  47. int32_t metastate = AKeyEvent_getMetaState(event);
  48. WARN_VARG("Key event: action=%d keyCode=%d metaState=0x%x", action, keycode, metastate);
  49. switch(action)
  50. {
  51. case AKEY_EVENT_ACTION_DOWN:
  52. Game::getInstance()->keyEvent(Keyboard::KEY_PRESS, getKey(keycode, metastate));
  53. break;
  54. case AKEY_EVENT_ACTION_UP:
  55. Game::getInstance()->keyEvent(Keyboard::KEY_RELEASE, getKey(keycode, metastate));
  56. break;
  57. }
  58. }
  59. return 0;
  60. }
  61. /**
  62. * Process the next main command.
  63. */
  64. static void engine_handle_cmd(struct android_app* app, int32_t cmd)
  65. {
  66. switch (cmd)
  67. {
  68. case APP_CMD_SAVE_STATE:
  69. WARN("engine_handle_cmd - APP_CMD_SAVE_STATE");
  70. // TODO
  71. break;
  72. case APP_CMD_INIT_WINDOW:
  73. WARN("engine_handle_cmd - APP_CMD_INIT_WINDOW");
  74. // The window is being shown, get it ready.
  75. if (app->window != NULL)
  76. {
  77. Game* game = Game::getInstance();
  78. assert(game != NULL);
  79. Platform* platform = Platform::create(game);
  80. app->userData = platform;
  81. __initialized = true;
  82. }
  83. break;
  84. case APP_CMD_TERM_WINDOW:
  85. {
  86. WARN("engine_handle_cmd - APP_CMD_TERM_WINDOW");
  87. Game::getInstance()->exit();
  88. Platform* platform = static_cast<Platform*>(app->userData);
  89. if (!platform)
  90. {
  91. return;
  92. }
  93. delete platform;
  94. app->userData = NULL;
  95. break;
  96. }
  97. case APP_CMD_GAINED_FOCUS:
  98. WARN("engine_handle_cmd - APP_CMD_GAINED_FOCUS");
  99. // When our app gains focus, we start monitoring the accelerometer.
  100. if (__accelerometerSensor != NULL) {
  101. ASensorEventQueue_enableSensor(__sensorEventQueue, __accelerometerSensor);
  102. // We'd like to get 60 events per second (in us).
  103. ASensorEventQueue_setEventRate(__sensorEventQueue, __accelerometerSensor, (1000L/60)*1000);
  104. }
  105. Game::getInstance()->resume();
  106. break;
  107. case APP_CMD_LOST_FOCUS:
  108. WARN("engine_handle_cmd - APP_CMD_LOST_FOCUS");
  109. // When our app loses focus, we stop monitoring the accelerometer.
  110. // This is to avoid consuming battery while not being used.
  111. if (__accelerometerSensor != NULL) {
  112. ASensorEventQueue_disableSensor(__sensorEventQueue, __accelerometerSensor);
  113. }
  114. Game::getInstance()->pause();
  115. ((Platform*)static_cast<Platform*>(app->userData))->swapBuffers();
  116. break;
  117. }
  118. }
  119. /**
  120. * Main entry point.
  121. */
  122. void amain(struct android_app* state)
  123. {
  124. ANativeActivity* activity = state->activity;
  125. JNIEnv* env = activity->env;
  126. jclass clazz = env->GetObjectClass(activity->clazz);
  127. jmethodID methodID = env->GetMethodID(clazz, "getPackageName", "()Ljava/lang/String;");
  128. jobject result = env->CallObjectMethod(activity->clazz, methodID);
  129. const char* packageName;
  130. jboolean isCopy;
  131. packageName = env->GetStringUTFChars((jstring)result, &isCopy);
  132. __assetsPath = "/mnt/sdcard/android/data/";
  133. __assetsPath += packageName;
  134. __assetsPath += "/";
  135. __assetManager = state->activity->assetManager;
  136. state->onAppCmd = engine_handle_cmd;
  137. state->onInputEvent = engine_handle_input;
  138. __state = state;
  139. // Prepare to monitor accelerometer.
  140. __sensorManager = ASensorManager_getInstance();
  141. __accelerometerSensor = ASensorManager_getDefaultSensor(__sensorManager, ASENSOR_TYPE_ACCELEROMETER);
  142. __sensorEventQueue = ASensorManager_createEventQueue(__sensorManager, __state->looper, LOOPER_ID_USER, NULL, NULL);
  143. ANativeActivity_showSoftInput(state->activity, ANATIVEACTIVITY_SHOW_SOFT_INPUT_IMPLICIT);
  144. __initialized = false;
  145. while (true)
  146. {
  147. // Read all pending events.
  148. int ident;
  149. int events;
  150. struct android_poll_source* source;
  151. bool _shouldPoll = !(__initialized && Game::getInstance()->getState() == Game::UNINITIALIZED) && (Game::getInstance()->getState() != Game::PAUSED);
  152. while ((ident=ALooper_pollAll( _shouldPoll ? 0 : -1, NULL, &events, (void**)&source)) >= 0)
  153. {
  154. // Process this event.
  155. if (source != NULL)
  156. source->process(__state, source);
  157. // If a sensor has data, process it now.
  158. if (ident == LOOPER_ID_USER && __accelerometerSensor != NULL)
  159. ASensorEventQueue_getEvents(__sensorEventQueue, &__sensorEvent, 1);
  160. if (__state->destroyRequested != 0)
  161. break;
  162. }
  163. Platform* platform = static_cast<Platform*>(state->userData);
  164. if (platform)
  165. platform->enterMessagePump();
  166. // Check if we are exiting.
  167. if ((__state->destroyRequested != 0) || (__initialized && Game::getInstance()->getState() == Game::UNINITIALIZED))
  168. break;
  169. }
  170. // We need to exit the process to cleanup global resources.
  171. exit(0);
  172. }
  173. #endif