mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-17 10:30:47 +02:00
#11 fix touch controls (action button as accept in inventory), fix aspect for "loading..." text; #15 android multiple gamepads support for split screen mode
This commit is contained in:
@@ -911,7 +911,7 @@ struct Inventory {
|
|||||||
Input::Joystick &joy = Input::joy[Core::settings.controls[playerIndex].joyIndex];
|
Input::Joystick &joy = Input::joy[Core::settings.controls[playerIndex].joyIndex];
|
||||||
|
|
||||||
ControlKey key = cMAX;
|
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;
|
key = cAction;
|
||||||
else if (Input::down[ikAlt] || joy.down[jkB] || Input::state[playerIndex][cInventory])
|
else if (Input::down[ikAlt] || joy.down[jkB] || Input::state[playerIndex][cInventory])
|
||||||
key = cInventory;
|
key = cInventory;
|
||||||
|
@@ -2291,6 +2291,7 @@ struct Level : IGame {
|
|||||||
if (isEnded) {
|
if (isEnded) {
|
||||||
Core::setTarget(NULL, CLEAR_ALL);
|
Core::setTarget(NULL, CLEAR_ALL);
|
||||||
UI::begin();
|
UI::begin();
|
||||||
|
UI::updateAspect(float(Core::width) / float(Core::height));
|
||||||
UI::textOut(vec2(0, 480 - 16), STR_LOADING, UI::aCenter, UI::width);
|
UI::textOut(vec2(0, 480 - 16), STR_LOADING, UI::aCenter, UI::width);
|
||||||
UI::end();
|
UI::end();
|
||||||
return;
|
return;
|
||||||
|
@@ -68,16 +68,71 @@ int osGetTime() {
|
|||||||
return int((t.tv_sec - startTime) * 1000 + t.tv_usec / 1000);
|
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" {
|
extern "C" {
|
||||||
|
|
||||||
char Stream::cacheDir[255];
|
char Stream::cacheDir[255];
|
||||||
char Stream::contentDir[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;
|
timeval t;
|
||||||
gettimeofday(&t, NULL);
|
gettimeofday(&t, NULL);
|
||||||
startTime = t.tv_sec;
|
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;
|
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);
|
str = env->GetStringUTFChars(contentDir, NULL);
|
||||||
strcat(Stream::contentDir, str);
|
strcat(Stream::contentDir, str);
|
||||||
env->ReleaseStringUTFChars(contentDir, str);
|
env->ReleaseStringUTFChars(contentDir, str);
|
||||||
@@ -116,8 +165,6 @@ JNI_METHOD(void, nativeUpdate)(JNIEnv* env) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
JNI_METHOD(void, nativeRender)(JNIEnv* env) {
|
JNI_METHOD(void, nativeRender)(JNIEnv* env) {
|
||||||
Core::stats.dips = 0;
|
|
||||||
Core::stats.tris = 0;
|
|
||||||
Game::render();
|
Game::render();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,27 +177,6 @@ float DeadZone(float x) {
|
|||||||
return x = fabsf(x) < 0.2f ? 0.0f : 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) {
|
InputKey keyToInputKey(int code) {
|
||||||
int codes[] = {
|
int codes[] = {
|
||||||
21, 22, 19, 20, 62, 61, 66, 111, 59, 113, 57,
|
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
|
// gamepad / keyboard
|
||||||
if (state < 0) {
|
if (state < 0) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case -3 : Input::setJoyPos(0, jkL, vec2(DeadZone(x), DeadZone(y))); break;
|
case -3 : Input::setJoyPos(id, jkL, vec2(DeadZone(x), DeadZone(y))); break;
|
||||||
case -4 : Input::setJoyPos(0, jkR, vec2(DeadZone(x), DeadZone(y))); break;
|
case -4 : Input::setJoyPos(id, jkR, vec2(DeadZone(x), DeadZone(y))); break;
|
||||||
//case -5 : Input::setJoyPos(ikJoyPOV, vec2(float(getPOV(sign(x), sign(y))), 0.0f)); break;
|
|
||||||
default : {
|
default : {
|
||||||
int btn = int(x);
|
int btn = int(x);
|
||||||
if (btn <= 0)
|
LOG("key %d = %d\n", btn, state);
|
||||||
Input::setJoyDown(0, JoyKey(jkA - btn), state != -1);
|
if (btn < 0)
|
||||||
|
Input::setJoyDown(id, JoyKey(jkNone - btn), state != -1);
|
||||||
else
|
else
|
||||||
Input::setDown(keyToInputKey(btn), state != -1);
|
Input::setDown(keyToInputKey(btn), state != -1);
|
||||||
}
|
}
|
||||||
|
@@ -30,6 +30,7 @@ import android.view.WindowManager;
|
|||||||
|
|
||||||
public class MainActivity extends Activity implements OnTouchListener, OnKeyListener, OnGenericMotionListener, SensorEventListener {
|
public class MainActivity extends Activity implements OnTouchListener, OnKeyListener, OnGenericMotionListener, SensorEventListener {
|
||||||
private Wrapper wrapper;
|
private Wrapper wrapper;
|
||||||
|
private ArrayList joyList = new ArrayList();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
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);
|
sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR), SensorManager.SENSOR_DELAY_FASTEST);
|
||||||
*/
|
*/
|
||||||
try {
|
try {
|
||||||
String packName = getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_ACTIVITIES).applicationInfo.sourceDir;
|
String content = Environment.getExternalStorageDirectory().getAbsolutePath();
|
||||||
// hardcoded demo level and music
|
wrapper.onCreate(content + "/OpenLara/", getCacheDir().getAbsolutePath() + "/");
|
||||||
//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());
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
finish();
|
finish();
|
||||||
@@ -128,22 +125,38 @@ public class MainActivity extends Activity implements OnTouchListener, OnKeyList
|
|||||||
wrapper.onTouch(-100, 1, event.values[2], event.values[3]);
|
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
|
@Override
|
||||||
public boolean onGenericMotion(View v, MotionEvent event) {
|
public boolean onGenericMotion(View v, MotionEvent event) {
|
||||||
int src = event.getDevice().getSources();
|
int src = event.getDevice().getSources();
|
||||||
|
|
||||||
boolean isMouse = (src & (InputDevice.SOURCE_MOUSE)) != 0;
|
if (isGamepad(event.getDevice().getSources())) {
|
||||||
boolean isJoy = (src & (InputDevice.SOURCE_GAMEPAD | InputDevice.SOURCE_JOYSTICK)) != 0;
|
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) {
|
// d-pad
|
||||||
wrapper.onTouch(0, -3, event.getAxisValue(MotionEvent.AXIS_X),
|
if ((src & InputDevice.SOURCE_DPAD) != InputDevice.SOURCE_DPAD) {
|
||||||
event.getAxisValue(MotionEvent.AXIS_Y));
|
float dx = event.getAxisValue(MotionEvent.AXIS_HAT_X);
|
||||||
|
float dy = event.getAxisValue(MotionEvent.AXIS_HAT_Y);
|
||||||
wrapper.onTouch(0, -4, event.getAxisValue(MotionEvent.AXIS_Z),
|
wrapper.onTouch(index, dx > 0.9 ? -2 : -1, -14, 0);
|
||||||
event.getAxisValue(MotionEvent.AXIS_RZ));
|
wrapper.onTouch(index, dy < -0.9 ? -2 : -1, -15, 0);
|
||||||
|
wrapper.onTouch(index, dy > 0.9 ? -2 : -1, -16, 0);
|
||||||
wrapper.onTouch(0, -5, event.getAxisValue(MotionEvent.AXIS_HAT_X),
|
wrapper.onTouch(index, dx < -0.9 ? -2 : -1, -13, 0);
|
||||||
event.getAxisValue(MotionEvent.AXIS_HAT_Y));
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -154,19 +167,23 @@ public class MainActivity extends Activity implements OnTouchListener, OnKeyList
|
|||||||
int btn;
|
int btn;
|
||||||
|
|
||||||
switch (keyCode) {
|
switch (keyCode) {
|
||||||
case KeyEvent.KEYCODE_BUTTON_A : btn = -0; break;
|
case KeyEvent.KEYCODE_BUTTON_A : btn = -1; break;
|
||||||
case KeyEvent.KEYCODE_BUTTON_B : btn = -1; break;
|
case KeyEvent.KEYCODE_BUTTON_B : btn = -2; break;
|
||||||
case KeyEvent.KEYCODE_BUTTON_X : btn = -2; break;
|
case KeyEvent.KEYCODE_BUTTON_X : btn = -3; break;
|
||||||
case KeyEvent.KEYCODE_BUTTON_Y : btn = -3; break;
|
case KeyEvent.KEYCODE_BUTTON_Y : btn = -4; break;
|
||||||
case KeyEvent.KEYCODE_BUTTON_L1 : btn = -4; break;
|
case KeyEvent.KEYCODE_BUTTON_L1 : btn = -5; break;
|
||||||
case KeyEvent.KEYCODE_BUTTON_R1 : btn = -5; break;
|
case KeyEvent.KEYCODE_BUTTON_R1 : btn = -6; break;
|
||||||
case KeyEvent.KEYCODE_BUTTON_SELECT : btn = -6; break;
|
case KeyEvent.KEYCODE_BUTTON_SELECT : btn = -7; break;
|
||||||
case KeyEvent.KEYCODE_BUTTON_START : btn = -7; break;
|
case KeyEvent.KEYCODE_BUTTON_START : btn = -8; break;
|
||||||
case KeyEvent.KEYCODE_BUTTON_THUMBL : btn = -8; break;
|
case KeyEvent.KEYCODE_BUTTON_THUMBL : btn = -9; break;
|
||||||
case KeyEvent.KEYCODE_BUTTON_THUMBR : btn = -9; break;
|
case KeyEvent.KEYCODE_BUTTON_THUMBR : btn = -10; break;
|
||||||
case KeyEvent.KEYCODE_BUTTON_L2 : btn = -10; break;
|
case KeyEvent.KEYCODE_BUTTON_L2 : btn = -11; break;
|
||||||
case KeyEvent.KEYCODE_BUTTON_R2 : btn = -11; break;
|
case KeyEvent.KEYCODE_BUTTON_R2 : btn = -12; break;
|
||||||
case KeyEvent.KEYCODE_BACK : btn = KeyEvent.KEYCODE_TAB; 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_UP :
|
||||||
case KeyEvent.KEYCODE_VOLUME_DOWN :
|
case KeyEvent.KEYCODE_VOLUME_DOWN :
|
||||||
case KeyEvent.KEYCODE_VOLUME_MUTE : return false;
|
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;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,7 +286,7 @@ class Touch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Wrapper implements Renderer {
|
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 nativeFree();
|
||||||
public static native void nativeReset();
|
public static native void nativeReset();
|
||||||
public static native void nativeResize(int w, int h);
|
public static native void nativeResize(int w, int h);
|
||||||
@@ -280,16 +298,12 @@ class Wrapper implements Renderer {
|
|||||||
Boolean ready = false;
|
Boolean ready = false;
|
||||||
private String contentDir;
|
private String contentDir;
|
||||||
private String cacheDir;
|
private String cacheDir;
|
||||||
private String packName;
|
|
||||||
private int levelOffset;
|
|
||||||
private ArrayList<Touch> touch = new ArrayList<>();
|
private ArrayList<Touch> touch = new ArrayList<>();
|
||||||
private Sound sound;
|
private Sound sound;
|
||||||
|
|
||||||
void onCreate(String contentDir, String cacheDir, String packName, int levelOffset) {
|
void onCreate(String contentDir, String cacheDir) {
|
||||||
this.contentDir = contentDir;
|
this.contentDir = contentDir;
|
||||||
this.cacheDir = cacheDir;
|
this.cacheDir = cacheDir;
|
||||||
this.packName = packName;
|
|
||||||
this.levelOffset = levelOffset;
|
|
||||||
|
|
||||||
sound = new Sound();
|
sound = new Sound();
|
||||||
sound.start(this);
|
sound.start(this);
|
||||||
@@ -336,7 +350,7 @@ class Wrapper implements Renderer {
|
|||||||
@Override
|
@Override
|
||||||
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
|
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
|
||||||
if (!ready) {
|
if (!ready) {
|
||||||
nativeInit(contentDir, cacheDir, packName, levelOffset);
|
nativeInit(contentDir, cacheDir);
|
||||||
sound.play();
|
sound.play();
|
||||||
ready = true;
|
ready = true;
|
||||||
}
|
}
|
||||||
|
@@ -273,20 +273,6 @@ vec2 joyDir(float ax, float ay) {
|
|||||||
return dir.normal() * dist;
|
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) {
|
int joyDeadZone(int value, int zone) {
|
||||||
return (value < -zone || value > zone) ? value : 0;
|
return (value < -zone || value > zone) ? value : 0;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user