diff --git a/app/src/main/cpp/NativeEngine.cpp b/app/src/main/cpp/NativeEngine.cpp index 64802df..e52494f 100644 --- a/app/src/main/cpp/NativeEngine.cpp +++ b/app/src/main/cpp/NativeEngine.cpp @@ -15,7 +15,7 @@ #include #include -static GameState g_app_state = { false }; +static GameState g_app_state = {false}; static void _handle_cmd_proxy(struct android_app* app, int32_t cmd) { @@ -23,16 +23,16 @@ static void _handle_cmd_proxy(struct android_app* app, int32_t cmd) engine->handleAppCmd(cmd); } -NativeEngine::NativeEngine(struct android_app *app) - : m_app(app), - m_egl_display(EGL_NO_DISPLAY), - m_egl_surface(EGL_NO_SURFACE), - m_egl_context(EGL_NO_CONTEXT), - m_jni_env(nullptr), - m_has_focus(false), - m_has_window(false), - m_is_visible(false), - m_in_motion(false) +NativeEngine::NativeEngine(struct android_app* app) + : m_app(app), + m_egl_display(EGL_NO_DISPLAY), + m_egl_surface(EGL_NO_SURFACE), + m_egl_context(EGL_NO_CONTEXT), + m_jni_env(nullptr), + m_has_focus(false), + m_has_window(false), + m_is_visible(false), + m_in_motion(false) { SwappyGL_init(getJniEnv(), m_app->activity->javaGameActivity); SwappyGL_setSwapIntervalNS(SWAPPY_SWAP_20FPS); @@ -42,7 +42,6 @@ NativeEngine::NativeEngine(struct android_app *app) AndroidAssetManager::create(m_app->activity->assetManager); - // INTEGRATION // Hier kannst du Initialisierungscode aufrufen. // Beachte das Renderer noch _nicht_ gültig ist. @@ -54,8 +53,8 @@ NativeEngine::NativeEngine(struct android_app *app) // BEISPIELCODE m_smiley = StringRepository::global->internString("smiley_PNG42.png"); - //m_smiley_pos = { 100, 100 }; - // ENDE VOM BEISPIELCODE + // m_smiley_pos = { 100, 100 }; + // ENDE VOM BEISPIELCODE } NativeEngine::~NativeEngine() @@ -84,8 +83,7 @@ void NativeEngine::gameLoop() struct android_poll_source* source; // Poll commands - while ((ALooper_pollAll(isAnimating() ? 0 : -1, nullptr, - &events, reinterpret_cast(&source))) >= 0) { + while ((ALooper_pollAll(isAnimating() ? 0 : -1, nullptr, &events, reinterpret_cast(&source))) >= 0) { if (source) source->process(source->app, source); if (m_app->destroyRequested) @@ -104,11 +102,11 @@ void NativeEngine::gameLoop() } if (input_buffer->motionEventsCount > 0) { float rel_size = m_display_height; - if (m_display_height > m_display_width){ + if (m_display_height > m_display_width) { rel_size = m_display_width; } rel_size *= 0.04f; - //float rel_size = MIN(m_display_height, m_display_width) * 0.04f; + // float rel_size = MIN(m_display_height, m_display_width) * 0.04f; for (unsigned int i = 0; i < input_buffer->motionEventsCount; ++i) { GameActivityMotionEvent motion_event = input_buffer->motionEvents[i]; if (motion_event.action == AMOTION_EVENT_ACTION_DOWN) { @@ -158,20 +156,18 @@ void NativeEngine::gameLoop() float y = GameActivityPointerAxes_getY(&pointer); float dist = sqrtf((x - m_last_down.x) * (x - m_last_down.x) + - (y - m_last_down.y) * (y - m_last_down.y)); + (y - m_last_down.y) * (y - m_last_down.y)); if (dist < rel_size) { // TAP ALOGI("TAP at %f %f", x, y); input_events[input_event_count].kind = TouchInputEventKind::Tap; - input_events[input_event_count].start = { x, y }; - input_events[input_event_count].end = { x, y }; + input_events[input_event_count].start = {x, y}; + input_events[input_event_count].end = {x, y}; ++input_event_count; } else { // Swipe - ALOGI("Swipe from %f %f to %f %f", - m_last_down.x, m_last_down.y, - x, y); + ALOGI("Swipe from %f %f to %f %f", m_last_down.x, m_last_down.y, x, y); input_events[input_event_count].kind = TouchInputEventKind::EndSwipe; input_events[input_event_count].start = {m_last_down.x, m_last_down.y}; input_events[input_event_count].end = {x, y}; @@ -197,33 +193,28 @@ void NativeEngine::gameLoop() // INTEGRATION Rufe hier deine "gameloop"/"update" funktion auf, die als Parameter // den GameState, input_events und input_event_count und die Displaygröße bekommen sollte: // - // kUpdate(&m_state, input_events, input_event_count, m_display_width, m_display_height) + // kUpdate(&m_state, input_events, input_event_count, + // nullptr, 0, + // m_display_width, m_display_height) // + // (Für Kompatibilität zu Windows sollte die funktion auch tastatur input akzeptieren, + // den es unter Android aber momentan nicht gibt.) // // Die Funktion könnte folgende Definition haben: // void kUpdate(GameState* state, // const TouchInputEvent* touch_events, // unsigned int touch_event_count, + // unsigned int* pressed_codepoints, + // unsigned int codepoint_count, // float display_width, // float display_height) - - /*static bool erster_aufruf = true; - if (erster_aufruf){ - computeWindowWidthHeight(m_display_width, m_display_height); - initKrimiDinner(); - erster_aufruf = false; - } - - krimiDinnerLoop(&m_state, input_events, input_event_count, - m_display_width, m_display_height);*/ - - //ENDE INTEGRATION + // ENDE INTEGRATION // BEISPIELCODE static float x = 1.f; static float d = -0.01f; x += d; - if ( x <= 0.f) + if (x <= 0.f) d *= -1.f; else if (x >= 1.f) d *= -1.f; @@ -235,7 +226,7 @@ void NativeEngine::gameLoop() } Renderer::ptr->addRect(100, 100, 500, 500, 0.3f, 0.3f, 0.3f, 1.f); - Renderer::ptr->addRect(m_smiley_pos.x, m_smiley_pos.y, 500, 500, 0.f, x*x, 1.f - x*x, 1.f, m_smiley); + Renderer::ptr->addRect(m_smiley_pos.x, m_smiley_pos.y, 500, 500, 0.f, x * x, 1.f - x * x, 1.f, m_smiley); // ENDE VOM BEISPIELCODE } @@ -250,68 +241,71 @@ bool NativeEngine::isAnimating() const return m_has_window && m_has_focus && m_is_visible; } - void NativeEngine::handleAppCmd(int32_t cmd) { ALOGV("NativeEngine: Handling command %d.", cmd); switch (cmd) { - case APP_CMD_SAVE_STATE: - ALOGV("NativeEngine:: APP_CMD_SAVE_STATE"); - m_state.has_focus = m_has_focus; - m_app->savedState = malloc(sizeof(m_state)); - *reinterpret_cast(m_app->savedState) = m_state; - m_app->savedStateSize = sizeof(m_state); - break; - case APP_CMD_INIT_WINDOW: - ALOGV("NativeEngine:: APP_CMD_INIT_WINDOW"); - if (m_app->window) { - m_has_window = true; - SwappyGL_setWindow(m_app->window); - if (m_app->savedStateSize == sizeof(m_state) && m_app->savedState) { - m_state = *reinterpret_cast(m_app->savedState); - m_has_focus = m_state.has_focus; - } - else { - // Workaround APP_CMD_GAINED_FOCUS issue where the focus state is not passed - // down from GameActivity when restarting Activity - m_has_focus = g_app_state.has_focus; - } + case APP_CMD_SAVE_STATE: + ALOGV("NativeEngine:: APP_CMD_SAVE_STATE"); + m_state.has_focus = m_has_focus; + m_app->savedState = malloc(sizeof(m_state)); + *reinterpret_cast(m_app->savedState) = m_state; + m_app->savedStateSize = sizeof(m_state); + break; + case APP_CMD_INIT_WINDOW: + ALOGV("NativeEngine:: APP_CMD_INIT_WINDOW"); + if (m_app->window) { + m_has_window = true; + SwappyGL_setWindow(m_app->window); + if (m_app->savedStateSize == sizeof(m_state) && m_app->savedState) { + m_state = *reinterpret_cast(m_app->savedState); + m_has_focus = m_state.has_focus; } - ALOGV("HandleCommand(%d): hasWindow = %d, hasFocus = %d", cmd, - m_has_window ? 1 : 0, m_has_focus ? 1 : 0); - break; - case APP_CMD_TERM_WINDOW: - ALOGV("NativeEngine: APP_CMD_TERM_WINDOW"); - killSurface(); - m_has_window = false; - break; - case APP_CMD_GAINED_FOCUS: - ALOGV("NativeEngine: APP_CMD_GAINED_FOCUS"); - m_has_focus = true; - m_state.has_focus = g_app_state.has_focus = m_has_focus; - break; - case APP_CMD_LOST_FOCUS: - ALOGV("NativeEngine: APP_CMD_LOST_FOCUS"); - m_has_focus = false; - m_state.has_focus = g_app_state.has_focus = m_has_focus; - break; - case APP_CMD_START: - ALOGV("NativeEngine: APP_CMD_START"); - m_is_visible = true; - break; - case APP_CMD_STOP: - ALOGV("NativeEngine: APP_CMD_STOP"); - m_is_visible = false; - break; - case APP_CMD_RESUME: - ALOGV("NativeEngine: APP_CMD_RESUME"); - break; - default: - ALOGW("Unhandled command."); - break; + else { + // Workaround APP_CMD_GAINED_FOCUS issue where the focus state is not passed + // down from GameActivity when restarting Activity + m_has_focus = g_app_state.has_focus; + } + } + ALOGV("HandleCommand(%d): hasWindow = %d, hasFocus = %d", cmd, m_has_window ? 1 : 0, m_has_focus ? 1 : 0); + break; + case APP_CMD_TERM_WINDOW: + ALOGV("NativeEngine: APP_CMD_TERM_WINDOW"); + killSurface(); + m_has_window = false; + break; + case APP_CMD_GAINED_FOCUS: + ALOGV("NativeEngine: APP_CMD_GAINED_FOCUS"); + m_has_focus = true; + m_state.has_focus = g_app_state.has_focus = m_has_focus; + break; + case APP_CMD_LOST_FOCUS: + ALOGV("NativeEngine: APP_CMD_LOST_FOCUS"); + m_has_focus = false; + m_state.has_focus = g_app_state.has_focus = m_has_focus; + break; + case APP_CMD_START: + ALOGV("NativeEngine: APP_CMD_START"); + m_is_visible = true; + break; + case APP_CMD_STOP: + ALOGV("NativeEngine: APP_CMD_STOP"); + m_is_visible = false; + break; + case APP_CMD_RESUME: + ALOGV("NativeEngine: APP_CMD_RESUME"); + break; + default: + ALOGW("Unhandled command."); + break; } ALOGV("NativeEngine STATUS: F%d, V%d, W%d, EGL: D %p, S %p, CTX %p, CFG %p", - m_has_focus, m_is_visible, m_has_window, m_egl_display, m_egl_surface, m_egl_context, + m_has_focus, + m_is_visible, + m_has_window, + m_egl_display, + m_egl_surface, + m_egl_context, m_egl_config); } @@ -346,7 +340,9 @@ bool NativeEngine::prepareToRender() } ALOGI("NativeEngine: binding surface and context (display %p, surface %p, context %p)", - m_egl_display, m_egl_surface, m_egl_context); + m_egl_display, + m_egl_surface, + m_egl_context); if (eglMakeCurrent(m_egl_display, m_egl_surface, m_egl_surface, m_egl_context) == EGL_FALSE) { ALOGE("NativeEngine: eglMakeCurrent failed, EGL error: %d", eglGetError()); @@ -396,13 +392,19 @@ bool NativeEngine::initSurface() EGLint num_configs; const EGLint attribs[] = { - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT, - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_BLUE_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_RED_SIZE, 8, - EGL_DEPTH_SIZE, 16, - EGL_NONE, + EGL_RENDERABLE_TYPE, + EGL_OPENGL_ES3_BIT, + EGL_SURFACE_TYPE, + EGL_WINDOW_BIT, + EGL_BLUE_SIZE, + 8, + EGL_GREEN_SIZE, + 8, + EGL_RED_SIZE, + 8, + EGL_DEPTH_SIZE, + 16, + EGL_NONE, }; eglChooseConfig(m_egl_display, attribs, &m_egl_config, 1, &num_configs); @@ -429,10 +431,7 @@ bool NativeEngine::initContext() ALOGI("NativeEngine: initializing context"); assert(m_egl_display != EGL_NO_DISPLAY); - EGLint attrib_list[] = { - EGL_CONTEXT_CLIENT_VERSION, 3, - EGL_NONE - }; + EGLint attrib_list[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE}; if (m_egl_context != EGL_NO_CONTEXT) return true; diff --git a/app/src/main/cpp/win32_kde.cpp b/app/src/main/cpp/win32_kde.cpp index 8cef54b..2922b49 100644 --- a/app/src/main/cpp/win32_kde.cpp +++ b/app/src/main/cpp/win32_kde.cpp @@ -6,16 +6,34 @@ #include "Win32AssetManager.h" #include "TouchInput.h" #include "Position.h" +#include "GameState.h" #undef APIENTRY #define WIN32_LEAN_AND_MEAN #include +#include + +struct CodePointsArray +{ + unsigned int* cps; // codepoints + unsigned int count; + unsigned int cap; +}; + static void errorCallback(int error, const char* desc) { MessageBoxA(NULL, desc, "Error", MB_ICONERROR | MB_OK); } +static void charCallback(GLFWwindow* window, unsigned int cp) +{ + CodePointsArray* cp_array = reinterpret_cast(glfwGetWindowUserPointer(window)); + assert(cp_array != nullptr); + if (cp_array->count < cp_array->cap) + cp_array->cps[cp_array->count++] = cp; +} + int main() { glfwSetErrorCallback(errorCallback); @@ -24,6 +42,12 @@ int main() return 1; } + unsigned int pressed_codepoints[100]; + CodePointsArray cp_array; + cp_array.cps = pressed_codepoints; + cp_array.cap = 100; + cp_array.count = 0; + glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); @@ -32,6 +56,9 @@ int main() glfwTerminate(); return 1; } + glfwSetWindowUserPointer(window, &cp_array); + glfwSetCharCallback(window, charCallback); + glfwMakeContextCurrent(window); int ret = gladLoadGLES2Loader((GLADloadproc)glfwGetProcAddress); if (!ret) { @@ -41,6 +68,8 @@ int main() return 1; } + GameState state = {}; + const char* asset_dir = "app\\src\\main\\assets"; Win32AssetManager::create(asset_dir); @@ -53,35 +82,51 @@ int main() glfwSwapInterval(1); while (!glfwWindowShouldClose(window)) { + /* Reset the pressed codepoints array, + * because glfwPollEvents() will call our characterCallback + */ + cp_array.count = 0; + glfwPollEvents(); /* Gather keyboard input */ /* Gather mouse input */ - TouchInputEvent touch_event = {}; + TouchInputEvent input_events[1] = {}; int input_event_count = 0; if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS) { double x, y; glfwGetCursorPos(window, &x, &y); - touch_event.kind = TouchInputEventKind::Tap; - touch_event.start = {static_cast(x), static_cast(y)}; - touch_event.end = touch_event.start; + input_events[0].kind = TouchInputEventKind::Tap; + input_events[0].start = {static_cast(x), static_cast(y)}; + input_events[0].end = input_events[0].start; input_event_count = 1; } + if (cp_array.count > 0) { + printf("CP: %u\n", cp_array.cps[0]); + } + int w, h; glfwGetFramebufferSize(window, &w, &h); + float display_width = static_cast(w); + float display_height = static_cast(h); + // INTEGRATION Rufe hier deine "gameloop"/"update" funktion auf, die als Parameter // den GameState, input_events und input_event_count und die Displaygröße bekommen sollte: // - // kUpdate(&m_state, input_events, input_event_count, m_display_width, m_display_height) + // kUpdate(&state, input_events, input_event_count, + // cp_array.cps, cp_array.count, + // display_width, display_height) // // // Die Funktion könnte folgende Definition haben: // void kUpdate(GameState* state, // const TouchInputEvent* touch_events, // unsigned int touch_event_count, + // unsigned int* pressed_codepoints, + // unsigned int codepoint_count, // float display_width, // float display_height) // ENDE INTEGRATION @@ -96,7 +141,7 @@ int main() d *= -1.f; if (input_event_count > 0) { - smiley_pos = touch_event.end; + smiley_pos = input_events[0].end; smiley_pos.x -= 250; smiley_pos.y -= 250; }