Функция запросов к плееру
Нужна функция, которая позволит спрашивать у плеера параметры среды выполнения, во время выполнения игры.
В настоящий момент из игры никак нельзя узнать, на каком из плееров игра выполняется(AeroQSP или классический Windows-плеер, или Android-плеер, или Quest Navigator, или плеер для покетбука), а также на какой платформе (Windows, Linux, MacOS, Android, iOS, WinPhone8).
Это было бы крайне удобным для создания универсальных игр, совместимых с максимально возможным количеством плееров и платформ. Например, в настоящий момент для создания игры, которая была бы играбельна на AeroQSP и классическом плеере, приходится держать две разные версии файла .qsp, не говоря уже о Quest Navigator. Даже в пределах одного плеера, Quest Navigator, мне приходится держать две разные версии файла - одну для Android, другую для iOS, из-за того, что нужно выводить разные ссылки и разные тексты для Google Play и App Store соответственно. А когда будет поддерживаться WindowsPhone8, то ещё одна добавится, и так далее.
Есть вариант задавать переменные средствами плеера, в которых будут содержаться необходимые сведения. Но это противоречит общей концепции “переменные обнулены в начале игры”.
Поэтому, самым практичным и универсальным решением мне видится создание функции в библиотеке, которая обращается к плееру и выдаёт игре результат.
В таком духе:
$platform = GETPLAYER("platform")
IF $platform = 'iOS':
...
ELSEIF $platform = 'Android':
...
END
Начать можно с предоставления версии операционной системы и плеера, в дальнейшем можно по необходимости расширять список характеристик. Можно будет даже добавлять параметры для уточнения. Что самое приятное - вся обработка этой функции будет лежать на плеере, поэтому при дальнейшем совершенствовании списка характеристик никаких изменений в библиотеке не потребуется.
Конечно, можно “костылями” присобачить такую возможность к плееру и на существующей версии библиотеки, например вызывать INPUT с определённым текстовым тегом. Но хотелось бы чтобы это был официальный функционал, т.к. вещь полезная и нужная.
Для проблемы со ссылками могу добавить такое предложение обработки: делать одну ссылку, а в отдельном файле автоматически пересылать её куда нужно в зависимости уже от параметров среды. Конечно можно сделать то же самое и в самой игре, но не все догадаются.
Baz,
я же написал, что не только ссылки нужно разные сделать, но и текст описания. К игрокам, открывшим игру с Google Play, у меня одно обращение, к игрокам с App Store - другое. Запихивать текст во внешний файл - уже не комильфо.
Патч для библиотеки:
Spoiler
Index: bindings/default/default_callbacks.c
===================================================================
--- bindings/default/default_callbacks.c (revision 685)
+++ bindings/default/default_callbacks.c (working copy)
@@ -290,4 +290,24 @@
return buffer;
}
+QSP_CHAR *qspCallPlayerVersion(QSP_CHAR *text)
+{
+ /* Здесь получаем строку по заданному параметру */
+ QSPCallState state;
+ QSP_CHAR *buffer;
+ int maxLen = 511;
+ if (qspCallBacks[QSP_CALL_PLAYERVERSION])
+ {
+ qspSaveCallState(&state, QSP_TRUE, QSP_FALSE);
+ buffer = (QSP_CHAR *)malloc((maxLen + 1) * sizeof(QSP_CHAR));
+ *buffer = 0;
+ qspCallBacks[QSP_CALL_PLAYERVERSION](text, buffer, maxLen);
+ buffer[maxLen] = 0;
+ qspRestoreCallState(&state);
+ }
+ else
+ buffer = qspGetNewText(QSP_FMT(""), 0);
+ return buffer;
+}
+
#endif
Index: callbacks.h
===================================================================
--- callbacks.h (revision 685)
+++ callbacks.h (working copy)
@@ -61,5 +61,6 @@
void qspCallCloseFile(QSP_CHAR *);
void qspCallDeleteMenu();
QSP_CHAR *qspCallInputBox(QSP_CHAR *);
+ QSP_CHAR *qspCallPlayerVersion(QSP_CHAR *);
#endif
Index: mathops.c
===================================================================
--- mathops.c (revision 685)
+++ mathops.c (working copy)
@@ -195,6 +195,7 @@
qspAddOperation(qspOpMainText, 30, 0, 1, 0, 0);
qspAddOperation(qspOpStatText, 30, 0, 1, 0, 0);
qspAddOperation(qspOpCurActs, 30, 0, 1, 0, 0);
+ qspAddOperation(qspOpPlayerVer, 30, 0, 1, 1, 1, 1);
/* Names */
qspAddOpName(qspOpCloseBracket, QSP_RRBRACK, 1);
qspAddOpName(qspOpAdd, QSP_ADD, 1);
@@ -281,6 +282,8 @@
qspAddOpName(qspOpStatText, QSP_STRCHAR QSP_FMT("STATTXT"), 1);
qspAddOpName(qspOpCurActs, QSP_FMT("CURACTS"), 1);
qspAddOpName(qspOpCurActs, QSP_STRCHAR QSP_FMT("CURACTS"), 1);
+ qspAddOpName(qspOpPlayerVer, QSP_FMT("GETPLAYER"), 1);
+ qspAddOpName(qspOpPlayerVer, QSP_STRCHAR QSP_FMT("GETPLAYER"), 1);
for (i = 0; i < QSP_OPSLEVELS; ++i)
qsort(qspOpsNames[i], qspOpsNamesCounts[i], sizeof(QSPMathOpName), qspMathOpsCompare);
}
@@ -596,6 +599,9 @@
case qspOpCurActs:
QSP_STR(tos) = qspGetAllActionsAsCode();
break;
+ case qspOpPlayerVer:
+ QSP_STR(tos) = qspCallPlayerVersion(QSP_STR(args[0]));
+ break;
/* External functions -------------------------------------------------------------- */
default:
qspOps[opCode].Func(args, argsCount, &tos);
Index: mathops.h
===================================================================
--- mathops.h (revision 685)
+++ mathops.h (working copy)
@@ -114,6 +114,7 @@
qspOpMainText,
qspOpStatText,
qspOpCurActs,
+ qspOpPlayerVer,
qspOpLast_Operation
};
Index: qsp.h
===================================================================
--- qsp.h (revision 685)
+++ qsp.h (working copy)
@@ -88,6 +88,7 @@
QSP_CALL_SLEEP, /* void func(int msecs) */
QSP_CALL_GETMSCOUNT, /* int func() */
QSP_CALL_INPUTBOX, /* void func(const QSP_CHAR *text, QSP_CHAR *buffer, int maxLen) */
+ QSP_CALL_PLAYERVERSION, /* void func(const QSP_CHAR *text, QSP_CHAR *buffer, int maxLen) */
QSP_CALL_DUMMY
};
Пример для классического плеера:
Spoiler
Index: callbacks_gui.cpp
===================================================================
--- callbacks_gui.cpp (revision 685)
+++ callbacks_gui.cpp (working copy)
@@ -58,6 +58,7 @@
QSPSetCallBack(QSP_CALL_SHOWWINDOW, (QSP_CALLBACK)&ShowPane);
QSPSetCallBack(QSP_CALL_OPENGAMESTATUS, (QSP_CALLBACK)&OpenGameStatus);
QSPSetCallBack(QSP_CALL_SAVEGAMESTATUS, (QSP_CALLBACK)&SaveGameStatus);
+ QSPSetCallBack(QSP_CALL_PLAYERVERSION, (QSP_CALLBACK)&PlayerVersion);
}
void QSPCallBacks::DeInit()
@@ -425,3 +426,24 @@
}
}
}
+
+void QSPCallBacks::PlayerVersion(const QSP_CHAR *text, QSP_CHAR *buffer, int maxLen)
+{
+ wxString parm = wxString(text);
+ if (parm == _("os"))
+ {
+#ifdef _UNICODE
+ wcsncpy(buffer, _("windows"), maxLen);
+#else
+ strncpy(buffer, _("windows"), maxLen);
+#endif
+ } else if (parm == _("platform"))
+ {
+#ifdef _UNICODE
+ wcsncpy(buffer, _("classic"), maxLen);
+#else
+ strncpy(buffer, _("classic"), maxLen);
+#endif
+ }
+
+}
Index: callbacks_gui.h
===================================================================
--- callbacks_gui.h (revision 685)
+++ callbacks_gui.h (working copy)
@@ -64,6 +64,7 @@
static void ShowImage(const QSP_CHAR *file);
static void OpenGameStatus(const QSP_CHAR *file);
static void SaveGameStatus(const QSP_CHAR *file);
+ static void PlayerVersion(const QSP_CHAR *text, QSP_CHAR *buffer, int maxLen);
private:
// Internal methods
static void UpdateGamePath();
Index: qsp.h
===================================================================
--- qsp.h (revision 685)
+++ qsp.h (working copy)
@@ -88,6 +88,7 @@
QSP_CALL_SLEEP, /* void func(int msecs) */
QSP_CALL_GETMSCOUNT, /* int func() */
QSP_CALL_INPUTBOX, /* void func(const QSP_CHAR *text, QSP_CHAR *buffer, int maxLen) */
+ QSP_CALL_PLAYERVERSION, /* void func(const QSP_CHAR *text, QSP_CHAR *buffer, int maxLen) */
QSP_CALL_DUMMY
};
Проверялось на:
Spoiler
$ОС = GETPLAYER('os')
'ОС: <<$ОС>>'
$Платформа = GETPLAYER('platform')
'Платформа: <<$Платформа>>'
Результат:
Spoiler

rrock.ru,
спасибо большое! Осталось только добавить это в библиотеку.
Кстати QSP_CALL_PLAYERVERSION не очень подходит, скорее уж QSP_CALL_PLAYERINFO - т.к. информация может быть разная.
Nex:
Кстати QSP_CALL_PLAYERVERSION не очень подходит, скорее уж QSP_CALL_PLAYERINFO - т.к. информация может быть разная.
Ну это уже дело вкуса :)
Я думал над PLAYERINFO, ну уж как-то смахивает на информацию об игроке..
P.S. Добавил бы сам, но у меня доступ только к репе редактора.
Есть 2 варианта реализации этого без модификации библиотеки:
1. GUI устанавливает соответствующую переменную (API библиотеки это предусматривает)
2. Использовать готовую callback функцию SYSTEM - она также предусмотрена в библиотеке.
Например, SYSTEM(”PLATFORM”) может возвращать платформу.
Я еще подумаю как лучше сделать.
PS: Возможно, SYSTEM сейчас не возвращает значение - уже забыл.
- GUI устанавливает соответствующую переменную (API библиотеки это предусматривает)
Я согласен, это можно сделать, но как я писал выше, это поведение будет отличаться от общепринятого. Того, что в начале игры все переменные обнулены, а параметры среды запрашиваются функциями. Помнится, когда-то ты настаивал на соблюдении этого принципа.
- Использовать готовую callback функцию SYSTEM - она также предусмотрена в библиотеке.
“SYSTEM” не возвращает значение. К тому же не очень понятно, как она вообще должна себя вести - никакой документации по ней нет.
Да, я вспомнил - SYSTEM сейчас зарезервирован для оператора. Вообще, этот оператор задумывался для выполнения различных служебных действий, которые могут предоставлять плееры.
Byte,
это хорошо. Я как раз его собираюсь заюзать для выполнения яваскрипта из Quest Navigator.
Учитывая, что поведение SYSTEM зависит от плеера, тем нужнее функция запросов к плееру.