gameplay-main-android.cpp 6.8 KB

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