Викликаємо Java код з Love2D


Всім доброго часу доби!
Виникла потреба вбудувати рекламу в свою гру на Love2D. Вирішив показувати банер після виграшу гравця і тут виникли труднощі: банер викликається Java кодом програми, а виграш визначається Lua коді. Пов'язує їх код на Сі, туториалов, як додавати свої методи движок не було, і довелося копирсатися в коді самостійно. Репозиторій Love2D для Android лежить ось тут.
З чого почати?
я вирішив Почати з вивчення методу
love.system.vibrate()
– метод, який з'являється при використанні Love2D на андроїд, а значить його десь додають також як я хочу додати рекламу.
Якщо відкрити клас GameActivity, то там можна знайти метод vibrate, який ми шукаємо, і ось тут варто пояснити, як відбувається виклик Java коду з Lua.
Коли програма тільки запускається, для кожного модуля Love2D створюється екземпляр класу модуля і екземпляр класу зв'язки (об'єкт, який прив'язує Сишный об'єкт до змінної Lua). У об'єкта зв'язки для кожного методу, який потрібно інтегрувати в Lua є свій маленький метод і список, в якому вказано який метод у Lua сопостовляется сишной зв'язці. Виглядає це так:
// Список зв'язок
static const luaL_Reg functions[] =
{
{ "getOS", w_getOS },
{ "getProcessorCount", w_getProcessorCount },
{ "setClipboardText", w_setClipboardText },
{ "getClipboardText", w_getClipboardText },
{ "getPowerInfo", w_getPowerInfo },
{ "openURL", w_openURL },
{ "vibrate", w_vibrate },
{ 0, 0 }
};

extern "С" int luaopen_love_system(lua_State *L)
{
// Эземпляр модуля
System *instance = instance();
if (instance == nullptr)
{
instance = new love::system::sdl::System();
}
else
instance->retain();

// Підсумкова зв'язка
WrappedModule w;
w.module = instance;
w.name = "system";
w.type = MODULE_ID;
w.functions = functions;
w.types = nullptr;

return luax_register_module(L, w);
}

Так само зазначу, що додаткові методи, які додані для андроїда, зберігаються в окремому класі, який лежить в папці
./jni/love/src/common/
і називається
android
.
Додаємо свій метод
Спочатку створимо статичний метод у класі GameActivity:
private static GameActivity instance;

@Override
protected void onCreate(Bundle savedInstanceState) {
instance = this;
// ...
}

// ...

// Важливо, щоб метод був статичним, тому що доступ до
// екземпляру класу буде отримати складніше
public static void showAd() {
Toast.makeText(instance, "Ad example", Toast.LENGTH_LONG).show();
}

Тепер створимо метод в модулі
love.system
. Я вибрав цей модуль, тому що впроваджую рекламу, але використовувати саме system не обов'язково. Можна навіть созлать свій модуль, в залежності від того, що вам потрібно.
Спочатку потрібно написати головну частину методу в класі
android
. Оголошуємо:
// ./jni/love/src/common/android.h

bool openURL(const std::string &url);

void showAd();

void vibrate(double seconds);

І створюємо:
// ./jni/love/src/common/android.cpp

void showAd()
{
// Отримуємо середовище виконання Java
JNIEnv *env = (JNIEnv*) SDL_AndroidGetJNIEnv();
// І клас, в якому ми створили статичний метод
jclass activity = env->FindClass("org/love2d/android/GameActivity");

// Тепер сам метод
jmethodID show_ad_method = env->GetStaticMethodID(activity, "showAd", "()V");
// Викликаємо його
env->CallStaticVoidMethod(activity, show_ad_method);

env->DeleteLocalRef(activity);
}

При отриманні ідентифікатора методу третьому параметром ми вказуємо, що повертає метод і які параметри приймаємо. Якщо ваш метод буде приймати аргументи, то в дужках їх потрібно перелічити. Якщо ваш метод повертає значення, то також потрібно буде змінити
V
на відповідну літеру. Так, щоб описати ось такий метод:
bool isGreater(double a, double b) { return a > b; }

Буде використовуватися наступна рядок:
(DD)Z
. Детальніше можна прочитати ось тут.
Додаємо метод
showAd
в сам модуль:
// ./jni/love/src/modules/system/System.h

/**
* Shows ad
*/
virtual void showAd() const;

Ну і сам код:
// ./jni/love/src/modules/system/System.cpp
void System::showAd() const {
#ifdef LOVE_ANDROID
love::android::showAd();
#endif
}

Трохи клею
Тепер залишилося все це з'єднати з допомогою зв'язки. Додаємо відповідний метод в клас зв'язки:
int w_showAd(lua_State *L)
{
instance()->showAd();
return 0;
}

// Ну і список зв'язок звичайно ж
static const luaL_Reg functions[] =
{
{ "getOS", w_getOS },
{ "getProcessorCount", w_getProcessorCount },
{ "setClipboardText", w_setClipboardText },
{ "getClipboardText", w_getClipboardText },
{ "getPowerInfo", w_getPowerInfo },
{ "openURL", w_openURL },
{ "vibrate", w_vibrate },
{ "showAd", w_showAd },
{ 0, 0 }
};

Збираємо все це туториалу з самого початку.
Додаємо код в луа (
love.system.showAd()
), і перевіряємо:

Вуаля.
Висновок
З допомогою таких маніпуляцій можна вбудовувати рекламу, управляти світлодіодом, камерою і взагалі робити багато корисних речей за допомогою гри, що місцями буває дуже корисно для цікавих ігрових задумів.
Спасибі за прочитання (:
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.