From 9ffa678b69b5b5b582bbdc7f22887a07853bbc48 Mon Sep 17 00:00:00 2001 From: XProger Date: Sat, 3 Mar 2018 22:08:14 +0300 Subject: [PATCH] #11 fix touch controls (action button as accept in inventory), fix aspect for "loading..." text; #15 android multiple gamepads support for split screen mode --- src/inventory.h | 2 +- src/level.h | 1 + .../android/app/src/main/cpp/main.cpp | 100 +++++++++++------- .../org/xproger/openlara/MainActivity.java | 90 +++++++++------- src/platform/win/main.cpp | 14 --- 5 files changed, 117 insertions(+), 90 deletions(-) diff --git a/src/inventory.h b/src/inventory.h index 1c18c6d..5274a2c 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -911,7 +911,7 @@ struct Inventory { Input::Joystick &joy = Input::joy[Core::settings.controls[playerIndex].joyIndex]; ControlKey key = cMAX; - if (Input::down[ikCtrl] || Input::down[ikEnter] || joy.down[jkA]) + if (Input::down[ikCtrl] || Input::down[ikEnter] || Input::state[playerIndex][cAction] || joy.down[jkA]) key = cAction; else if (Input::down[ikAlt] || joy.down[jkB] || Input::state[playerIndex][cInventory]) key = cInventory; diff --git a/src/level.h b/src/level.h index 5014a9c..47ddc74 100644 --- a/src/level.h +++ b/src/level.h @@ -2291,6 +2291,7 @@ struct Level : IGame { if (isEnded) { Core::setTarget(NULL, CLEAR_ALL); UI::begin(); + UI::updateAspect(float(Core::width) / float(Core::height)); UI::textOut(vec2(0, 480 - 16), STR_LOADING, UI::aCenter, UI::width); UI::end(); return; diff --git a/src/platform/android/app/src/main/cpp/main.cpp b/src/platform/android/app/src/main/cpp/main.cpp index 013094d..af97551 100644 --- a/src/platform/android/app/src/main/cpp/main.cpp +++ b/src/platform/android/app/src/main/cpp/main.cpp @@ -68,16 +68,71 @@ int osGetTime() { return int((t.tv_sec - startTime) * 1000 + t.tv_usec / 1000); } -bool osSave(const char *name, const void *data, int size) { - return false; + +// joystick +bool osJoyReady(int index) { + return index == 0; } +void osJoyVibrate(int index, float L, float R) { + // +} + + +// storage +void osCacheWrite(Stream *stream) { + char path[255]; + strcpy(path, Stream::cacheDir); + strcat(path, stream->name); + FILE *f = fopen(path, "wb"); + if (f) { + fwrite(stream->data, 1, stream->size, f); + fclose(f); + if (stream->callback) + stream->callback(new Stream(stream->name, NULL, 0), stream->userData); + } else + if (stream->callback) + stream->callback(NULL, stream->userData); + + delete stream; +} + +void osCacheRead(Stream *stream) { + char path[255]; + strcpy(path, Stream::cacheDir); + strcat(path, stream->name); + FILE *f = fopen(path, "rb"); + if (f) { + fseek(f, 0, SEEK_END); + int size = ftell(f); + fseek(f, 0, SEEK_SET); + char *data = new char[size]; + fread(data, 1, size, f); + fclose(f); + if (stream->callback) + stream->callback(new Stream(stream->name, data, size), stream->userData); + delete[] data; + } else + if (stream->callback) + stream->callback(NULL, stream->userData); + delete stream; +} + +void osSaveGame(Stream *stream) { + return osCacheWrite(stream); +} + +void osLoadGame(Stream *stream) { + return osCacheRead(stream); +} + + extern "C" { char Stream::cacheDir[255]; char Stream::contentDir[255]; -JNI_METHOD(void, nativeInit)(JNIEnv* env, jobject obj, jstring contentDir, jstring cacheDir, jstring packName, jint levelOffset) { +JNI_METHOD(void, nativeInit)(JNIEnv* env, jobject obj, jstring contentDir, jstring cacheDir) { timeval t; gettimeofday(&t, NULL); startTime = t.tv_sec; @@ -86,12 +141,6 @@ JNI_METHOD(void, nativeInit)(JNIEnv* env, jobject obj, jstring contentDir, jstri Stream::contentDir[0] = Stream::cacheDir[0] = 0; - str = env->GetStringUTFChars(packName, NULL); -/* - Stream *level = new Stream(str); - env->ReleaseStringUTFChars(packName, str); - level->seek(levelOffset); -*/ str = env->GetStringUTFChars(contentDir, NULL); strcat(Stream::contentDir, str); env->ReleaseStringUTFChars(contentDir, str); @@ -116,8 +165,6 @@ JNI_METHOD(void, nativeUpdate)(JNIEnv* env) { } JNI_METHOD(void, nativeRender)(JNIEnv* env) { - Core::stats.dips = 0; - Core::stats.tris = 0; Game::render(); } @@ -130,27 +177,6 @@ float DeadZone(float x) { return x = fabsf(x) < 0.2f ? 0.0f : x; } -int getPOV(int x, int y) { - switch (x) { - case -1 : { - if (y == -1) return 8; - if (y == 0) return 7; - if (y == +1) return 6; - } - case 0 : { - if (y == -1) return 1; - if (y == 0) return 0; - if (y == +1) return 5; - } - case +1 : { - if (y == -1) return 2; - if (y == 0) return 3; - if (y == +1) return 4; - } - } - return 0; -} - InputKey keyToInputKey(int code) { int codes[] = { 21, 22, 19, 20, 62, 61, 66, 111, 59, 113, 57, @@ -169,13 +195,13 @@ JNI_METHOD(void, nativeTouch)(JNIEnv* env, jobject obj, jint id, jint state, jfl // gamepad / keyboard if (state < 0) { switch (state) { - case -3 : Input::setJoyPos(0, jkL, vec2(DeadZone(x), DeadZone(y))); break; - case -4 : Input::setJoyPos(0, jkR, vec2(DeadZone(x), DeadZone(y))); break; - //case -5 : Input::setJoyPos(ikJoyPOV, vec2(float(getPOV(sign(x), sign(y))), 0.0f)); break; + case -3 : Input::setJoyPos(id, jkL, vec2(DeadZone(x), DeadZone(y))); break; + case -4 : Input::setJoyPos(id, jkR, vec2(DeadZone(x), DeadZone(y))); break; default : { int btn = int(x); - if (btn <= 0) - Input::setJoyDown(0, JoyKey(jkA - btn), state != -1); + LOG("key %d = %d\n", btn, state); + if (btn < 0) + Input::setJoyDown(id, JoyKey(jkNone - btn), state != -1); else Input::setDown(keyToInputKey(btn), state != -1); } diff --git a/src/platform/android/app/src/main/java/org/xproger/openlara/MainActivity.java b/src/platform/android/app/src/main/java/org/xproger/openlara/MainActivity.java index e309759..2affad9 100644 --- a/src/platform/android/app/src/main/java/org/xproger/openlara/MainActivity.java +++ b/src/platform/android/app/src/main/java/org/xproger/openlara/MainActivity.java @@ -30,6 +30,7 @@ import android.view.WindowManager; public class MainActivity extends Activity implements OnTouchListener, OnKeyListener, OnGenericMotionListener, SensorEventListener { private Wrapper wrapper; + private ArrayList joyList = new ArrayList(); @Override protected void onCreate(Bundle savedInstanceState) { @@ -64,12 +65,8 @@ public class MainActivity extends Activity implements OnTouchListener, OnKeyList sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR), SensorManager.SENSOR_DELAY_FASTEST); */ try { - String packName = getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_ACTIVITIES).applicationInfo.sourceDir; - // hardcoded demo level and music - //AssetFileDescriptor fLevel = this.getResources().openRawResourceFd(R.raw.title); - - String content = Environment.getExternalStorageDirectory().getAbsolutePath(); // System.getenv("EXTERNAL_STORAGE") - wrapper.onCreate(content + "/OpenLara/", getCacheDir().getAbsolutePath() + "/", packName, 0);//(int)fLevel.getStartOffset()); + String content = Environment.getExternalStorageDirectory().getAbsolutePath(); + wrapper.onCreate(content + "/OpenLara/", getCacheDir().getAbsolutePath() + "/"); } catch (Exception e) { e.printStackTrace(); finish(); @@ -128,22 +125,38 @@ public class MainActivity extends Activity implements OnTouchListener, OnKeyList wrapper.onTouch(-100, 1, event.values[2], event.values[3]); } + boolean isGamepad(int src) { + return (src & (InputDevice.SOURCE_GAMEPAD | InputDevice.SOURCE_JOYSTICK)) != 0; + } + + int getJoyIndex(int joyId) { + int joyIndex = joyList.indexOf(joyId); + if (joyIndex == -1) { + joyIndex = joyList.size(); + joyList.add(joyId); + } + return joyIndex; + } + @Override public boolean onGenericMotion(View v, MotionEvent event) { int src = event.getDevice().getSources(); - boolean isMouse = (src & (InputDevice.SOURCE_MOUSE)) != 0; - boolean isJoy = (src & (InputDevice.SOURCE_GAMEPAD | InputDevice.SOURCE_JOYSTICK)) != 0; + if (isGamepad(event.getDevice().getSources())) { + int index = getJoyIndex(event.getDeviceId()); + // axis + wrapper.onTouch(index, -3, event.getAxisValue(MotionEvent.AXIS_X), event.getAxisValue(MotionEvent.AXIS_Y)); + wrapper.onTouch(index, -4, event.getAxisValue(MotionEvent.AXIS_Z), event.getAxisValue(MotionEvent.AXIS_RZ)); - if (isJoy) { - wrapper.onTouch(0, -3, event.getAxisValue(MotionEvent.AXIS_X), - event.getAxisValue(MotionEvent.AXIS_Y)); - - wrapper.onTouch(0, -4, event.getAxisValue(MotionEvent.AXIS_Z), - event.getAxisValue(MotionEvent.AXIS_RZ)); - - wrapper.onTouch(0, -5, event.getAxisValue(MotionEvent.AXIS_HAT_X), - event.getAxisValue(MotionEvent.AXIS_HAT_Y)); + // d-pad + if ((src & InputDevice.SOURCE_DPAD) != InputDevice.SOURCE_DPAD) { + float dx = event.getAxisValue(MotionEvent.AXIS_HAT_X); + float dy = event.getAxisValue(MotionEvent.AXIS_HAT_Y); + wrapper.onTouch(index, dx > 0.9 ? -2 : -1, -14, 0); + wrapper.onTouch(index, dy < -0.9 ? -2 : -1, -15, 0); + wrapper.onTouch(index, dy > 0.9 ? -2 : -1, -16, 0); + wrapper.onTouch(index, dx < -0.9 ? -2 : -1, -13, 0); + } } return true; @@ -154,19 +167,23 @@ public class MainActivity extends Activity implements OnTouchListener, OnKeyList int btn; switch (keyCode) { - case KeyEvent.KEYCODE_BUTTON_A : btn = -0; break; - case KeyEvent.KEYCODE_BUTTON_B : btn = -1; break; - case KeyEvent.KEYCODE_BUTTON_X : btn = -2; break; - case KeyEvent.KEYCODE_BUTTON_Y : btn = -3; break; - case KeyEvent.KEYCODE_BUTTON_L1 : btn = -4; break; - case KeyEvent.KEYCODE_BUTTON_R1 : btn = -5; break; - case KeyEvent.KEYCODE_BUTTON_SELECT : btn = -6; break; - case KeyEvent.KEYCODE_BUTTON_START : btn = -7; break; - case KeyEvent.KEYCODE_BUTTON_THUMBL : btn = -8; break; - case KeyEvent.KEYCODE_BUTTON_THUMBR : btn = -9; break; - case KeyEvent.KEYCODE_BUTTON_L2 : btn = -10; break; - case KeyEvent.KEYCODE_BUTTON_R2 : btn = -11; break; - case KeyEvent.KEYCODE_BACK : btn = KeyEvent.KEYCODE_TAB; break; + case KeyEvent.KEYCODE_BUTTON_A : btn = -1; break; + case KeyEvent.KEYCODE_BUTTON_B : btn = -2; break; + case KeyEvent.KEYCODE_BUTTON_X : btn = -3; break; + case KeyEvent.KEYCODE_BUTTON_Y : btn = -4; break; + case KeyEvent.KEYCODE_BUTTON_L1 : btn = -5; break; + case KeyEvent.KEYCODE_BUTTON_R1 : btn = -6; break; + case KeyEvent.KEYCODE_BUTTON_SELECT : btn = -7; break; + case KeyEvent.KEYCODE_BUTTON_START : btn = -8; break; + case KeyEvent.KEYCODE_BUTTON_THUMBL : btn = -9; break; + case KeyEvent.KEYCODE_BUTTON_THUMBR : btn = -10; break; + case KeyEvent.KEYCODE_BUTTON_L2 : btn = -11; break; + case KeyEvent.KEYCODE_BUTTON_R2 : btn = -12; break; + case KeyEvent.KEYCODE_DPAD_LEFT : btn = -13; break; + case KeyEvent.KEYCODE_DPAD_RIGHT : btn = -14; break; + case KeyEvent.KEYCODE_DPAD_UP : btn = -15; break; + case KeyEvent.KEYCODE_DPAD_DOWN : btn = -16; break; + case KeyEvent.KEYCODE_BACK : btn = KeyEvent.KEYCODE_ESCAPE; break; case KeyEvent.KEYCODE_VOLUME_UP : case KeyEvent.KEYCODE_VOLUME_DOWN : case KeyEvent.KEYCODE_VOLUME_MUTE : return false; @@ -174,7 +191,8 @@ public class MainActivity extends Activity implements OnTouchListener, OnKeyList } boolean isDown = event.getAction() == KeyEvent.ACTION_DOWN; - wrapper.onTouch(0, isDown ? -2 : -1, btn, 0); + int index = btn < 0 ? getJoyIndex(event.getDevice().getId()) : 0; + wrapper.onTouch(index, isDown ? -2 : -1, btn, 0); return true; } @@ -268,7 +286,7 @@ class Touch { } class Wrapper implements Renderer { - public static native void nativeInit(String contentDir, String cacheDir, String packName, int levelOffset); + public static native void nativeInit(String contentDir, String cacheDir); public static native void nativeFree(); public static native void nativeReset(); public static native void nativeResize(int w, int h); @@ -280,16 +298,12 @@ class Wrapper implements Renderer { Boolean ready = false; private String contentDir; private String cacheDir; - private String packName; - private int levelOffset; private ArrayList touch = new ArrayList<>(); private Sound sound; - void onCreate(String contentDir, String cacheDir, String packName, int levelOffset) { + void onCreate(String contentDir, String cacheDir) { this.contentDir = contentDir; this.cacheDir = cacheDir; - this.packName = packName; - this.levelOffset = levelOffset; sound = new Sound(); sound.start(this); @@ -336,7 +350,7 @@ class Wrapper implements Renderer { @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { if (!ready) { - nativeInit(contentDir, cacheDir, packName, levelOffset); + nativeInit(contentDir, cacheDir); sound.play(); ready = true; } diff --git a/src/platform/win/main.cpp b/src/platform/win/main.cpp index 1c0b9fd..14c96e8 100644 --- a/src/platform/win/main.cpp +++ b/src/platform/win/main.cpp @@ -273,20 +273,6 @@ vec2 joyDir(float ax, float ay) { return dir.normal() * dist; } -float joyGetPOV(int mask) { - switch (mask) { - case 0b0001 : return 1; - case 0b1001 : return 2; - case 0b1000 : return 3; - case 0b1010 : return 4; - case 0b0010 : return 5; - case 0b0110 : return 6; - case 0b0100 : return 7; - case 0b0101 : return 8; - } - return 0; -} - int joyDeadZone(int value, int zone) { return (value < -zone || value > zone) ? value : 0; }