diff --git a/proj-android/app/build.gradle b/proj-android/app/build.gradle
index 13f6b57..71b3cb2 100644
--- a/proj-android/app/build.gradle
+++ b/proj-android/app/build.gradle
@@ -11,10 +11,10 @@ android {
if (buildAsApplication) {
namespace "org.libsdl.app"
}
- compileSdkVersion 34
+ compileSdkVersion 37
defaultConfig {
- minSdkVersion 19
- targetSdkVersion 34
+ minSdkVersion 21
+ targetSdkVersion 37
versionCode 1
versionName "1.0"
externalNativeBuild {
@@ -23,8 +23,8 @@ android {
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
}*/
cmake {
- arguments "-DANDROID_APP_PLATFORM=android-19", "-DANDROID_STL=c++_static"
- cppFlags "-std=c++11 -frtti -fexceptions"
+ arguments /*"-DANDROID_APP_PLATFORM=android-19",*/ "-DANDROID_STL=c++_static"
+ cppFlags "-std=c++17 -frtti -fexceptions"
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
}
}
@@ -32,7 +32,7 @@ android {
buildTypes {
release {
minifyEnabled false
- proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
applicationVariants.all { variant ->
diff --git a/proj-android/app/jni/CMakeLists.txt b/proj-android/app/jni/CMakeLists.txt
index b40ad99..ec0946b 100644
--- a/proj-android/app/jni/CMakeLists.txt
+++ b/proj-android/app/jni/CMakeLists.txt
@@ -21,7 +21,7 @@ set(TP_ROOT "${THIRDPARTY_DIR}")
# ==============================================================================
# --- ZLIB ---
-add_subdirectory("${TP_ROOT}/zlib-1.3.1" zlib-build)
+#add_subdirectory("${TP_ROOT}/zlib-1.3.2" zlib-build)
# --- LIBPNG ---
set(PNG_STATIC ON CACHE BOOL "Build static library" FORCE)
@@ -39,6 +39,9 @@ add_subdirectory("${TP_ROOT}/libpng-1.6.51" libpng-build)
# --- SDL2 ---
# Android-версия SDL требует специфичных настроек, но add_subdirectory обычно подхватывает их сама
add_subdirectory("${TP_ROOT}/SDL-release-2.32.10" sdl-build)
+#add_subdirectory("${TP_ROOT}/SDL_mixer-release-2.8.0" sdl-mixer-build)
+
+add_subdirectory("${TP_ROOT}/SDL_ttf-release-2.24.0" sdl-ttf-build)
# --- LIBZIP ---
# Отключаем поиск системных крипто-библиотек, так как в NDK их может не быть в стандартных путях
diff --git a/proj-android/app/jni/src/CMakeLists.txt b/proj-android/app/jni/src/CMakeLists.txt
index 2744580..9497c26 100644
--- a/proj-android/app/jni/src/CMakeLists.txt
+++ b/proj-android/app/jni/src/CMakeLists.txt
@@ -33,62 +33,143 @@ endforeach()
# Создаем кастомную цель, которая будет запускать процесс копирования
add_custom_target(sync_resources ALL DEPENDS ${RES_OUTPUTS})
+set(LUA_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../thirdparty/lua-5.4.8")
+file(GLOB LUA_SOURCES "${LUA_SRC_DIR}/*.c")
+list(REMOVE_ITEM LUA_SOURCES
+ "${LUA_SRC_DIR}/lua.c"
+ "${LUA_SRC_DIR}/luac.c"
+ "${LUA_SRC_DIR}/onelua.c"
+)
+add_library(lua_static STATIC ${LUA_SOURCES})
+target_include_directories(lua_static PUBLIC "${LUA_SRC_DIR}")
+
+
add_library(main SHARED
- SDL_android_main.c
- ../../../../src/BoneAnimatedModel.cpp
- ../../../../src/Environment.cpp
- ../../../../src/Game.cpp
+ SDL_android_main.c
../../../../src/main.cpp
- ../../../../src/Projectile.cpp
- ../../../../src/SparkEmitter.cpp
- ../../../../src/TextModel.cpp
- ../../../../src/UiManager.cpp
- ../../../../src/utils/Perlin.cpp
- ../../../../src/utils/TaskManager.cpp
- ../../../../src/utils/Utils.cpp
- ../../../../src/navigation/PathFinder.cpp
- ../../../../src/planet/PlanetData.cpp
- ../../../../src/planet/PlanetObject.cpp
- ../../../../src/planet/StoneObject.cpp
- ../../../../src/render/FrameBuffer.cpp
- ../../../../src/render/ShadowMap.cpp
+ ../../../../src/Game.cpp
+ ../../../../src/Game.h
+ ../../../../src/Character.cpp
+ ../../../../src/Character.h
+ ../../../../src/CharacterState.cpp
+ ../../../../src/CharacterState.h
+ ../../../../src/Environment.cpp
+ ../../../../src/Environment.h
+ ../../../../src/Localization.cpp
+ ../../../../src/Localization.h
../../../../src/render/Renderer.cpp
+ ../../../../src/render/Renderer.h
../../../../src/render/ShaderManager.cpp
+ ../../../../src/render/ShaderManager.h
../../../../src/render/TextureManager.cpp
+ ../../../../src/render/TextureManager.h
+ ../../../../src/TextModel.cpp
+ ../../../../src/TextModel.h
+ ../../../../src/AudioPlayerAsync.cpp
+ ../../../../src/AudioPlayerAsync.h
+ ../../../../src/BoneAnimatedModelNew.cpp
+ ../../../../src/BoneAnimatedModelNew.h
../../../../src/render/OpenGlExtensions.cpp
-)
-
-# Подключаем заголовки
-target_include_directories(main PRIVATE
- ${CMAKE_CURRENT_SOURCE_DIR}/../SDL/include
- ${CMAKE_CURRENT_SOURCE_DIR}/../zlib
- ${CMAKE_CURRENT_SOURCE_DIR}/../libpng
- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../thirdparty/eigen-5.0.0
- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../thirdparty/boost_1_90_0
- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src
- ${CMAKE_CURRENT_SOURCE_DIR}/../libzip
-)
-
-# ВАЖНО: Линкуемся с png_static (статика) или png_shared (динамика)
-# Так как мы установили PNG_STATIC=ON и PNG_SHARED=OFF,
-# должна создаться цель png_static
-target_link_libraries(main
- png_static # ← ЭТО ПРАВИЛЬНОЕ ИМЯ ЦЕЛИ!
- z
- SDL2
+ ../../../../src/render/OpenGlExtensions.h
+ ../../../../src/utils/Utils.cpp
+ ../../../../src/utils/Utils.h
+ ../../../../src/SparkEmitter.cpp
+ ../../../../src/SparkEmitter.h
+ ../../../../src/TeleportZone.h
+ ../../../../src/TeleportZone.cpp
+ ../../../../src/utils/TaskManager.cpp
+ ../../../../src/utils/TaskManager.h
+ ../../../../src/render/FrameBuffer.cpp
+ ../../../../src/render/FrameBuffer.h
+ ../../../../src/render/ShadowMap.cpp
+ ../../../../src/render/ShadowMap.h
+ ../../../../src/UiManager.cpp
+ ../../../../src/UiManager.h
+ ../../../../src/render/TextRenderer.h
+ ../../../../src/render/TextRenderer.cpp
+ ../../../../src/MenuManager.h
+ ../../../../src/MenuManager.cpp
+ ../../../../src/Location.h
+ ../../../../src/Location.cpp
+ ../../../../src/LocationState.h
+ ../../../../src/LocationState.cpp
+ ../../../../src/LocationEditor.h
+ ../../../../src/LocationEditor.cpp
+ ../../../../src/NpcCar.h
+ ../../../../src/NpcCar.cpp
+ ../../../../src/GameConstants.h
+ ../../../../src/GameConstants.cpp
+ ../../../../src/GameState.h
+ ../../../../src/GameState.cpp
+ ../../../../src/ScriptEngine.h
+ ../../../../src/ScriptEngine.cpp
+ ../../../../src/navigation/PathFinder.h
+ ../../../../src/navigation/PathFinder.cpp
+ ../../../../src/items/GameObjectLoader.h
+ ../../../../src/items/GameObjectLoader.cpp
+ ../../../../src/items/Item.h
+ ../../../../src/items/Item.cpp
+ ../../../../src/items/ItemRegistry.h
+ ../../../../src/items/ItemRegistry.cpp
+ ../../../../src/items/InteractiveObject.h
+ ../../../../src/items/InteractiveObject.cpp
+ ../../../../src/items/InteractiveObjectState.h
+ ../../../../src/dialogue/DialogueTypes.h
+ ../../../../src/dialogue/DialogueDatabase.h
+ ../../../../src/dialogue/DialogueDatabase.cpp
+ ../../../../src/dialogue/DialogueRuntime.h
+ ../../../../src/dialogue/DialogueRuntime.cpp
+ ../../../../src/dialogue/DialogueOverlay.h
+ ../../../../src/dialogue/DialogueOverlay.cpp
+ ../../../../src/dialogue/DialogueSystem.h
+ ../../../../src/dialogue/DialogueSystem.cpp
+ ../../../../src/dialogue/TranslationDatabase.h
+ ../../../../src/dialogue/TranslationDatabase.cpp
+ ../../../../src/quest/QuestTypes.h
+ ../../../../src/quest/QuestJournal.h
+ ../../../../src/quest/QuestJournal.cpp
+ ../../../../src/cutscene/CutsceneTypes.h
+ ../../../../src/cutscene/CutsceneDatabase.h
+ ../../../../src/cutscene/CutsceneDatabase.cpp
+ ../../../../src/cutscene/CutsceneRuntime.h
+ ../../../../src/cutscene/CutsceneRuntime.cpp
+ ../../../../src/cutscene/CutsceneOverlay.h
+ ../../../../src/cutscene/CutsceneOverlay.cpp
+ ../../../../src/render/UiQuad.h
)
-find_library(OPENGLES2_LIB GLESv2)
+
+
+find_library(OPENGLES3_LIB GLESv3)
target_link_libraries(main
- ${OPENGLES2_LIB} # OpenGL ES 2.0/3.0
+ ${OPENGLES3_LIB}
+ png_static
+ z
+ SDL2
+ SDL2_ttf
log
android
OpenSLES
dl
- zip
+ zip
+ lua_static
+ #freetype
+)
+
+# Подключаем заголовки
+target_include_directories(main PRIVATE
+ #${CMAKE_CURRENT_SOURCE_DIR}/../SDL/include
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../thirdparty/SDL_ttf-release-2.24.0/external/freetype/include
+ #${CMAKE_CURRENT_SOURCE_DIR}/../zlib
+ #${CMAKE_CURRENT_SOURCE_DIR}/../libpng
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../thirdparty/eigen-5.0.0
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../thirdparty/boost_1_90_0
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../thirdparty/sol2-3.3.0/include
+ #${CMAKE_CURRENT_SOURCE_DIR}/../libzip
)
add_dependencies(main sync_resources)
diff --git a/proj-android/app/src/main/AndroidManifest.xml b/proj-android/app/src/main/AndroidManifest.xml
index 5157374..3b0863e 100644
--- a/proj-android/app/src/main/AndroidManifest.xml
+++ b/proj-android/app/src/main/AndroidManifest.xml
@@ -8,7 +8,7 @@
android:installLocation="auto">
-
+
-->
-
+
+#endif
#include
#include
#include
@@ -51,17 +53,18 @@ private:
std::queue> taskQueue;
#endif
bool stop = false;
-
+#if 0
std::unordered_map soundCache;
std::mutex soundCacheMutex;
std::string currentTrack;
- Mix_Music* currentMusic_ = nullptr;
+ Mix_Music* currentMusic_ = nullptr;
+#endif
int musicVolume_ = 128;
int soundVolume_ = 128;
bool musicEnabled_ = true;
bool soundEnabled_ = true;
bool initialized = false;
-};
\ No newline at end of file
+};
diff --git a/src/BoneAnimatedModelNew.cpp b/src/BoneAnimatedModelNew.cpp
index 958af73..463908f 100644
--- a/src/BoneAnimatedModelNew.cpp
+++ b/src/BoneAnimatedModelNew.cpp
@@ -528,12 +528,14 @@ namespace FRG
}
else
{
+ /*
std::ifstream f(fileName, std::ios::binary | std::ios::ate);
if (!f.is_open()) throw std::runtime_error("Failed to open binary file: " + fileName);
std::streamsize fileSize = f.tellg();
f.seekg(0);
fileData.resize(static_cast(fileSize));
- f.read(fileData.data(), fileSize);
+ f.read(fileData.data(), fileSize);*/
+ fileData = readFile(fileName);
}
const char* ptr = fileData.data();
diff --git a/src/Environment.cpp b/src/Environment.cpp
index 4bdf8e1..158d72f 100644
--- a/src/Environment.cpp
+++ b/src/Environment.cpp
@@ -23,7 +23,7 @@ int Environment::height = CONST_DEFAULT_HEIGHT;
float Environment::zoom = DEFAULT_ZOOM;
-bool Environment::enableLogging = false;
+bool Environment::enableLogging = true;
SDL_Window* Environment::window = nullptr;
diff --git a/src/Game.cpp b/src/Game.cpp
index 79cc94c..c20005a 100644
--- a/src/Game.cpp
+++ b/src/Game.cpp
@@ -24,11 +24,16 @@
#include "GameConstants.h"
+#ifdef __ANDROID__
+extern bool isAppActive;
+#endif
+
namespace FRG
{
static const float zoomMin = 6.0f;
static const float zoomMax = 20.0f;
+
#ifdef EMSCRIPTEN
const char* CONST_ZIP_FILE = "resources.zip";
#else
@@ -81,8 +86,10 @@ namespace FRG
}
void Game::setup() {
+#ifndef __ANDROID__
Environment::width = Environment::CONST_DEFAULT_WIDTH;
Environment::height = Environment::CONST_DEFAULT_HEIGHT;
+#endif
Environment::computeProjectionDimensions();
FRG::BindOpenGlFunctions();
@@ -156,7 +163,9 @@ namespace FRG
});
loadSteps.push([this]() {
-#if defined(EMSCRIPTEN)
+
+
+#if defined(EMSCRIPTEN) || defined(__ANDROID__)
renderer.shaderManager.AddShaderFromFiles("env_sky", "resources/shaders/env_sky.vertex", "resources/shaders/env_sky_web.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("defaultAtmosphere", "resources/shaders/defaultAtmosphere.vertex", "resources/shaders/defaultAtmosphere_web.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("planetBake", "resources/shaders/planet_bake.vertex", "resources/shaders/planet_bake_web.fragment", CONST_ZIP_FILE);
@@ -181,7 +190,14 @@ namespace FRG
renderer.shaderManager.AddShaderFromFiles("night_fog_skinning", "resources/shaders/night_fog_skinning_web.vertex", "resources/shaders/night_fog_web.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("night_fog_shadow", "resources/shaders/night_fog_shadow_web.vertex", "resources/shaders/night_fog_shadow_web.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("night_fog_skinning_shadow", "resources/shaders/night_fog_skinning_shadow_web.vertex", "resources/shaders/night_fog_shadow_web.fragment", CONST_ZIP_FILE);
-/*#elif defined(__linux__)
+
+ renderer.shaderManager.AddShaderFromFiles("text2d",
+ "resources/shaders/text2d.vertex",
+ "resources/shaders/text2d_web.fragment",
+ CONST_ZIP_FILE
+ );
+
+ /*#elif defined(__linux__)
renderer.shaderManager.AddShaderFromFiles("env_sky", "resources/shaders/env_sky.vertex", "resources/shaders/env_sky_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("defaultAtmosphere", "resources/shaders/defaultAtmosphere.vertex", "resources/shaders/defaultAtmosphere_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("planetBake", "resources/shaders/planet_bake.vertex", "resources/shaders/planet_bake_desktop.fragment", CONST_ZIP_FILE);
@@ -233,6 +249,12 @@ namespace FRG
renderer.shaderManager.AddShaderFromFiles("night_fog_skinning", "resources/shaders/night_fog_skinning.vertex", "resources/shaders/night_fog_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("night_fog_shadow", "resources/shaders/night_fog_shadow.vertex", "resources/shaders/night_fog_shadow_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("night_fog_skinning_shadow", "resources/shaders/night_fog_skinning_shadow.vertex", "resources/shaders/night_fog_shadow_desktop.fragment", CONST_ZIP_FILE);
+
+ renderer.shaderManager.AddShaderFromFiles("text2d",
+ "resources/shaders/text2d.vertex",
+ "resources/shaders/text2d_desktop.fragment",
+ CONST_ZIP_FILE
+ );
#endif
});
@@ -1175,6 +1197,23 @@ namespace FRG
Environment::exitGameLoop = true;
}
+#ifdef __ANDROID__
+ if (event.type == SDL_APP_WILLENTERBACKGROUND) {
+ isAppActive = false;
+ __android_log_print(ANDROID_LOG_INFO, "Game", "App moving to background, suspending loop");
+ break;
+ }
+ if (event.type == SDL_APP_DIDENTERFOREGROUND) {
+ isAppActive = true;
+ __android_log_print(ANDROID_LOG_INFO, "Game", "App returned to foreground, resuming loop");
+ break;
+ }
+ /*
+ __android_log_print(ANDROID_LOG_ERROR, "Game",
+ "Game::update step 1 event type: %d", event.type);
+ */
+#endif
+
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED) {
const bool wasPortrait = Environment::width < Environment::height;
@@ -1211,7 +1250,12 @@ namespace FRG
// Suppress all input while portrait overlay is shown
//if (mobileIsPortrait) continue;
-
+ /*
+#ifdef __ANDROID__
+ __android_log_print(ANDROID_LOG_ERROR, "Game",
+ "Game::update step 2 event type: %d", event.type);
+#endif
+*/
// Ignore pointer input until the initial loading screen has finished.
// Otherwise a click on the loading screen (e.g. at the spot where a
// main-menu button will later be) gets delivered to the menu UI as
@@ -1222,6 +1266,12 @@ namespace FRG
continue;
}
+ /*
+#ifdef __ANDROID__
+ __android_log_print(ANDROID_LOG_ERROR, "Game",
+ "Game::update step 3 event type: %d", event.type);
+#endif
+*/
#ifdef __ANDROID__
if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_AC_BACK) {
Environment::exitGameLoop = true;
@@ -1232,6 +1282,12 @@ namespace FRG
// SDL_HINT_TOUCH_MOUSE_EVENTS="0" is set in main.cpp so these do not
// also fire SDL_MOUSEBUTTONDOWN, preventing double-processing.
if (event.type == SDL_FINGERDOWN || event.type == SDL_FINGERUP || event.type == SDL_FINGERMOTION) {
+/*
+#ifdef __ANDROID__
+ __android_log_print(ANDROID_LOG_ERROR, "Game",
+ "Game::update step 4 event type: %d", event.type);
+#endif
+ */
int eventX = static_cast(event.tfinger.x * Environment::width);
int eventY = static_cast(event.tfinger.y * Environment::height);
int mx = static_cast(event.tfinger.x * Environment::projectionWidth);
@@ -1249,7 +1305,12 @@ namespace FRG
}
continue;
}
-
+ /*
+#ifdef __ANDROID__
+ __android_log_print(ANDROID_LOG_ERROR, "Game",
+ "Game::update step 5 event type: %d", event.type);
+#endif
+*/
// Mouse-left maps to a single virtual touch with MOUSE_FINGER_ID.
// Right mouse is intentionally unused now — camera rotation is on hold-and-drag.
if (event.type == SDL_MOUSEBUTTONDOWN || event.type == SDL_MOUSEBUTTONUP) {
@@ -1304,136 +1365,6 @@ namespace FRG
if (event.type == SDL_KEYDOWN && event.key.repeat == 0) {
switch (event.key.keysym.sym) {
- /*case SDLK_8:
- if (editorMode == EditorMode::InteractiveObjects && currentLocation()) {
- currentLocation()->editor.selectInteractiveObject(8);
- } else {
- gameState.isDawn = !gameState.isDawn;
- if (gameState.isDawn) gameState.isNight = true;
- }
- break;
- case SDLK_9:
- if (editorMode == EditorMode::InteractiveObjects && currentLocation()) {
- currentLocation()->editor.selectInteractiveObject(9);
- } else {
- startNightTransition();
- }
- break;
- case SDLK_0:
-
- if (editorMode == EditorMode::InteractiveObjects && currentLocation()) {
- currentLocation()->editor.selectInteractiveObject(event.key.keysym.sym - SDLK_0);
- }
- else {
- currentLocation()->requestDarklandsTransition();
- }
- break;
- case SDLK_1:
- case SDLK_2:
- case SDLK_3:
- case SDLK_4:
- case SDLK_5:
- case SDLK_6:
- case SDLK_7:
-
- if (editorMode == EditorMode::InteractiveObjects && currentLocation()) {
- currentLocation()->editor.selectInteractiveObject(event.key.keysym.sym - SDLK_0);
- } else {
- currentLocation()->switchNavigation(event.key.keysym.sym - SDLK_0);
- logger() << "Switched to nav mesh " << (event.key.keysym.sym - SDLK_0) << std::endl;
- }
- break;
- case SDLK_f:
- currentLocation()->dialogueSystem.startDialogue("phone_night_aiperi001");
-
-
- break;
- case SDLK_e:
- currentLocation()->dialogueSystem.startCutscene("computer_cutscene001"); //.startDialogue("test_cutscene_pan_dialogue");
- break;
-
-
- case SDLK_n:
- if (editorMode == EditorMode::None)
- editorMode = EditorMode::Navigation;
- else if (editorMode == EditorMode::Navigation)
- editorMode = EditorMode::InteractiveObjects;
- else
- editorMode = EditorMode::None;
- if (currentLocation()) {
- currentLocation()->editorMode = editorMode;
- if (editorMode == EditorMode::Navigation)
- currentLocation()->editor.buildNavMeshes();
- else if (editorMode == EditorMode::InteractiveObjects)
- currentLocation()->editor.buildInteractiveObjectBoundsMeshes();
- }
- {
- const char* modeName = (editorMode == EditorMode::Navigation) ? "Navigation"
- : (editorMode == EditorMode::InteractiveObjects) ? "InteractiveObjects"
- : "None";
- logger() << "[EDITOR] Mode: " << modeName << std::endl;
- }
- break;
-
- case SDLK_o:
- x = x + 0.05;
- logger() << "current x: " << x << std::endl;
- //y = y + 0.002;
- //currentLocation->player->hp = 200;
- //currentLocation->npcs[0]->walkSpeed += 0.01f;
- //logger() << "Walk speed: " << currentLocation->npcs[0]->walkSpeed << std::endl;
- break;
-
- case SDLK_k:
- x = x - 0.05;
- logger() << "current x: " << x << std::endl;
- logger() << "Player pos: " << currentLocation()->player->state.position.transpose() << std::endl;
- logger() << "Player rotation: " << currentLocation()->player->state.facingAngle*180.0/M_PI << std::endl;
- //currentLocation->npcs[0]->walkSpeed -= 0.01f;
- //logger() << "Walk speed: " << currentLocation->npcs[0]->walkSpeed << std::endl;
- break;
-
- case SDLK_p:
- gameState.currentLocationName = "uni_interior";
- currentLocation()->player->state.position = Eigen::Vector3f(-0.0189243, 0, -13.4314);
- currentLocation()->player->setTarget(currentLocation()->player->state.position);
- //logger() << "Switched to location " << ((currentLocation == locations["location1"]) ? "1" : "2") << std::endl;
- break;
-
- case SDLK_l:
- //x = x - 1;
- //logger() << "current x: " << x << std::endl;
- logger() << "Azimuth: " << currentLocation()->state.cameraAzimuth << std::endl;
- logger() << "Inclination: " << currentLocation()->state.cameraInclination << std::endl;
- break;
-
- case SDLK_c:
- logger() << "SLOW-MO activated!" << std::endl;
- activateSlowMoEffect();
- break;
-
- case SDLK_i:
- y = y - 1;
- logger() << "current y: " << y << std::endl;
- break;
-
- case SDLK_b:
- if (editorMode != EditorMode::None && currentLocation()) {
- currentLocation()->editor.saveAll();
- }
- break;
-
- case SDLK_j:
- currentLocation()->editor.placeTree();
- break;
-
- case SDLK_v:
- if (editorMode != EditorMode::None && currentLocation()) {
- currentLocation()->editor.saveObjects();
- }
- break;
-
- case SDLK_RETURN:*/
default:
break;
}
@@ -1586,21 +1517,41 @@ namespace FRG
const int uiX = mx;
const int uiY = Environment::projectionHeight - my;
+
+#ifdef __ANDROID__
+ __android_log_print(ANDROID_LOG_ERROR, "Game",
+ "Game::onPointerDown step 1");
+#endif
menuManager.topUiManager.onTouchDown(fingerId, uiX, uiY);
const bool capturedByTopUi = menuManager.topUiManager.isUiInteractionForFinger(fingerId);
const bool dialogueActive = currentLocation() && currentLocation()->dialogueSystem.isActive();
if (!dialogueActive && !capturedByTopUi) {
+#ifdef __ANDROID__
+ __android_log_print(ANDROID_LOG_ERROR, "Game",
+ "Game::onPointerDown step 2");
+#endif
menuManager.uiManager.onTouchDown(fingerId, uiX, uiY);
}
st.capturedByUi = capturedByTopUi || (!dialogueActive && menuManager.uiManager.isUiInteractionForFinger(fingerId));
activePointers[fingerId] = st;
-
+#ifdef __ANDROID__
+ __android_log_print(ANDROID_LOG_ERROR, "Game",
+ "Game::onPointerDown step 3");
+#endif
if (st.capturedByUi) {
// UI button / slider / text-field grabbed this press; don't drive
// gameplay or pinch from it.
+#ifdef __ANDROID__
+ __android_log_print(ANDROID_LOG_ERROR, "Game",
+ "Game::onPointerDown step 4");
+#endif
return;
}
+#ifdef __ANDROID__
+ __android_log_print(ANDROID_LOG_ERROR, "Game",
+ "Game::onPointerDown step 5");
+#endif
if (countNonUiPointers() >= 2) {
// Second finger landed on the gameplay area: switch to pinch-zoom
diff --git a/src/ScriptEngine.cpp b/src/ScriptEngine.cpp
index b845897..b80a07d 100644
--- a/src/ScriptEngine.cpp
+++ b/src/ScriptEngine.cpp
@@ -861,7 +861,39 @@ namespace FRG {
}
});
- lua.script_file(scriptPath);
+ //lua.script_file(scriptPath);
+
+#ifdef __ANDROID__
+ // Читаем файл в строку через SDL_RWops
+ std::string scriptContent = readTextFile(scriptPath);
+ if (scriptContent.empty()) {
+ std::cerr << "[script] Failed to read script file or file is empty: " << scriptPath << "\n";
+ }
+ else {
+
+ // Загружаем (компилируем) строку скрипта. Вторым аргументом передаем имя для логов
+ auto loadResult = lua.load(scriptContent, scriptPath);
+ if (!loadResult.valid()) {
+ sol::error err = loadResult;
+ std::cerr << "[script] Lua compile error: " << err.what() << "\n";
+ }
+ else {
+ // Если компиляция успешна — вызываем функцию для выполнения кода скрипта
+ auto runResult = loadResult();
+ if (!runResult.valid()) {
+ sol::error err = runResult;
+ std::cerr << "[script] Lua runtime error: " << err.what() << "\n";
+ }
+ }
+ }
+#else
+ // На остальных платформах оставляем стандартную загрузку из файла
+ auto result = lua.script_file(scriptPath, sol::script_pass_on_error);
+ if (!result.valid()) {
+ sol::error err = result;
+ std::cerr << "[script] Lua load error: " << err.what() << "\n";
+ }
+#endif
}
void ScriptEngine::callNpcInteractCallback(int npcIndex) {
@@ -885,14 +917,14 @@ namespace FRG {
std::cerr << "[SCRIPT] Lua function 'on_npc_interact' not found!" << std::endl;
}
}
-
+/*
void ScriptEngine::runScript(const std::string& path) {
auto result = impl->lua.safe_script_file(path, sol::script_pass_on_error);
if (!result.valid()) {
sol::error err = result;
std::cerr << "[script] Error in " << path << ": " << err.what() << "\n";
}
- }
+ }*/
void ScriptEngine::callActivateFunction(const std::string& functionName) {
if (!impl) {
diff --git a/src/ScriptEngine.h b/src/ScriptEngine.h
index 06a40e2..95587b6 100644
--- a/src/ScriptEngine.h
+++ b/src/ScriptEngine.h
@@ -22,7 +22,7 @@ public:
void init(Location* game, Inventory* inventory, AudioPlayerAsync* audioPlayer, const std::string& scriptPath);
// Execute a Lua script file. Logs errors to stderr.
- void runScript(const std::string& path);
+ //void runScript(const std::string& path);
void callItemPickupCallback(const std::string& objectName);
diff --git a/src/main.cpp b/src/main.cpp
index 7885596..715bb4b 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -117,6 +117,8 @@ int main(int argc, char* argv[]) {
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
+
FRG::Environment::window = SDL_CreateWindow("Game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
glContext_x = SDL_GL_CreateContext(FRG::Environment::window);
@@ -149,40 +151,61 @@ int main(int argc, char* argv[]) {
#ifdef __ANDROID__
-extern "C" int SDL_main(int argc, char* argv[]) {
- // Инициализация SDL перед получением информации о дисплее
+#include
+#include
+
+void Android_InitTouchDevices() {
+ JNIEnv* env = (JNIEnv*)SDL_AndroidGetJNIEnv();
+ if (!env) {
+ __android_log_print(ANDROID_LOG_ERROR, "Game", "[Android] Failed to get JNIEnv for touch init");
+ return;
+ }
+
+ jclass activityClass = env->FindClass("org/libsdl/app/SDLActivity");
+ if (!activityClass) {
+ __android_log_print(ANDROID_LOG_ERROR, "Game", "[Android] Failed to find SDLActivity class");
+ return;
+ }
+
+ jmethodID initTouchMethod = env->GetStaticMethodID(activityClass, "initTouch", "()V");
+ if (!initTouchMethod) {
+ __android_log_print(ANDROID_LOG_ERROR, "Game", "[Android] Failed to find initTouch method");
+ return;
+ }
+
+ env->CallStaticVoidMethod(activityClass, initTouchMethod);
+ __android_log_print(ANDROID_LOG_INFO, "Game", "[Android] JNI initTouch() successfully invoked");
+}
+
+// Переменная для отслеживания фокуса приложения на Android
+bool isAppActive = true;
+
+
+int main(int argc, char* argv[]) {
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) {
__android_log_print(ANDROID_LOG_ERROR, "Game", "SDL init failed: %s", SDL_GetError());
return 1;
}
- SDL_DisplayMode displayMode;
- if (SDL_GetCurrentDisplayMode(0, &displayMode) != 0) {
- __android_log_print(ANDROID_LOG_ERROR, "Game", "SDL_GetCurrentDisplayMode failed: %s", SDL_GetError());
- SDL_Quit();
- return 1;
- }
- FRG::Environment::width = displayMode.w;
- FRG::Environment::height = displayMode.h;
-
- __android_log_print(ANDROID_LOG_INFO, "Game", "Display resolution: %dx%d",
- FRG::Environment::width, FRG::Environment::height);
-
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
- SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
- SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
- SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
- SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
+ SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+ SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "0");
+ SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");
+ // Передаем 0, 0 — на Android SDL автоматически растянет окно
+ // на весь экран с учетом системной ориентации Активити
FRG::Environment::window = SDL_CreateWindow(
"Shadow Over Bishkek",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
- FRG::Environment::width, FRG::Environment::height,
+ 0, 0,
SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN
);
@@ -208,32 +231,87 @@ extern "C" int SDL_main(int argc, char* argv[]) {
return 1;
}
- // Настройка VSync
+ // СТРОГО ТУТ: Запрашиваем у созданного окна реальный размер буфера
+ // Это исключит баг перевернутых координат ширины и высоты
+ int realWidth, realHeight;
+ SDL_GL_GetDrawableSize(FRG::Environment::window, &realWidth, &realHeight);
+ FRG::Environment::width = realWidth;
+ FRG::Environment::height = realHeight;
+
+ __android_log_print(ANDROID_LOG_INFO, "Game", "Actual Render Resolution: %dx%d",
+ FRG::Environment::width, FRG::Environment::height);
+
+ // Теперь, когда окно гарантированно создано в правильной ориентации,
+ // привязываем тач-устройства на стороне Java
+ Android_InitTouchDevices();
+
+
if (SDL_GL_SetSwapInterval(1) < 0) {
__android_log_print(ANDROID_LOG_WARN, "Game", "Unable to set VSync: %s", SDL_GetError());
}
- // Настройка игры
try {
- game.setup();
+ g_game = new FRG::Game();
+ g_game->setup();
}
catch (const std::exception& e) {
__android_log_print(ANDROID_LOG_ERROR, "Game", "Game setup failed: %s", e.what());
+ if (g_game) {
+ delete g_game;
+ g_game = nullptr;
+ }
+ SDL_GL_DeleteContext(ctx);
+ SDL_DestroyWindow(FRG::Environment::window);
+ SDL_Quit();
return 1;
}
- while (!game.shouldExit()) {
- game.update();
- SDL_Delay(16);
+ while (!g_game->shouldExit()) {
+ SDL_Event event;
+ // Обрабатываем системные события Android до обновления кадра
+ /*while (SDL_PollEvent(&event)) {
+ // Перенаправляем событие в игру, чтобы сработал ваш внутренний цикл (память, ресайз и т.д.)
+ // Примечание: внутри Game::update у вас тоже стоит PollEvent.
+ // Чтобы события не терялись, лучше обрабатывать их в одном месте,
+ // но жизненно важные для ОС флаги перехватываем здесь:
+ if (event.type == SDL_QUIT) {
+ break;
+ }
+
+ // Сворачивание / Разворачивание приложения в Android
+ if (event.type == SDL_APP_WILLENTERBACKGROUND) {
+ isAppActive = false;
+ __android_log_print(ANDROID_LOG_INFO, "Game", "App moving to background, suspending loop");
+ }
+ if (event.type == SDL_APP_DIDENTERFOREGROUND) {
+ isAppActive = true;
+ __android_log_print(ANDROID_LOG_INFO, "Game", "App returned to foreground, resuming loop");
+ }
+ }*/
+
+ if (isAppActive) {
+ g_game->update();
+ // На Android шаг кадров завязан на VSync (SwapInterval = 1).
+ // SDL_Delay(16) здесь не нужен, он будет вызывать микро-фризы (stuttering).
+ }
+ else {
+ // Если игра свернута — спим, чтобы не нагружать CPU/GPU
+ SDL_Delay(100);
+ }
}
+ delete g_game;
+ g_game = nullptr;
+
+ SDL_GL_DeleteContext(ctx);
+ SDL_DestroyWindow(FRG::Environment::window);
+ SDL_Quit();
+
return 0;
-
}
-
-
#endif
+#ifndef __ANDROID__
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__linux__)
// Read the persisted fullscreen preference (if any) before creating the
@@ -417,3 +495,4 @@ int main(int argc, char* argv[]) {
return 0;
}
#endif
+#endif
\ No newline at end of file
diff --git a/src/render/OpenGlExtensions.h b/src/render/OpenGlExtensions.h
index ddb56c1..2d644c9 100644
--- a/src/render/OpenGlExtensions.h
+++ b/src/render/OpenGlExtensions.h
@@ -12,8 +12,8 @@
#ifdef __ANDROID__
- #include
- #include
+ #include
+ #include
#else
#ifdef __linux__
#include
diff --git a/src/render/ShadowMap.cpp b/src/render/ShadowMap.cpp
index df5e756..410e671 100644
--- a/src/render/ShadowMap.cpp
+++ b/src/render/ShadowMap.cpp
@@ -87,13 +87,13 @@ namespace FRG {
GL_TEXTURE_2D, depthTexture, 0);
// No color buffer for this FBO — depth only.
-#ifdef EMSCRIPTEN
+//#ifdef EMSCRIPTEN
GLenum drawBuffers[] = { GL_NONE };
glDrawBuffers(1, drawBuffers);
-#else
+/*#else
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
-#endif
+#endif*/
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
diff --git a/src/render/TextRenderer.cpp b/src/render/TextRenderer.cpp
index 58644c0..0b6af2b 100644
--- a/src/render/TextRenderer.cpp
+++ b/src/render/TextRenderer.cpp
@@ -1,6 +1,8 @@
#include "render/TextRenderer.h"
+
#include
#include FT_FREETYPE_H
+//#include "freetype/freetype.h"
#include "Environment.h"
#include "render/OpenGlExtensions.h"
@@ -50,27 +52,6 @@ bool TextRenderer::init(Renderer& renderer, const std::string& ttfPath, int pixe
r = &renderer;
- static bool shaderAlreadyAdded = false;
-
- if (shaderAlreadyAdded == false)
- {
- shaderAlreadyAdded = true;
-
-#ifdef EMSCRIPTEN
- r->shaderManager.AddShaderFromFiles(shaderName,
- "resources/shaders/text2d.vertex",
- "resources/shaders/text2d_web.fragment",
- zipfilename
- );
-#else
- r->shaderManager.AddShaderFromFiles(shaderName,
- "resources/shaders/text2d.vertex",
- "resources/shaders/text2d_desktop.fragment",
- zipfilename
- );
-#endif
-
- }
FRG::CheckGlError(__FILE__, __LINE__);
if (!loadGlyphs(ttfPath, pixelSize, zipfilename)) return false;
FRG::CheckGlError(__FILE__, __LINE__);
diff --git a/src/render/TextRenderer.h b/src/render/TextRenderer.h
index 43f3d37..59fb4b8 100644
--- a/src/render/TextRenderer.h
+++ b/src/render/TextRenderer.h
@@ -49,7 +49,7 @@ private:
VertexRenderStruct textMesh;
- std::string shaderName = "text2d";
+ const std::string shaderName = "text2d";
// caching for static texts
struct CachedText {