Added Steam support for Windows
This commit is contained in:
parent
9da0ae1016
commit
76287dda46
@ -1,16 +1,19 @@
|
|||||||
cmake_minimum_required(VERSION 3.16)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
project(witcher001 LANGUAGES C CXX)
|
project(ShadowOverBishkekDemo LANGUAGES C CXX)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
# Опция для интеграции Steamworks SDK (по умолчанию выключена)
|
||||||
|
option(STEAMSDK "Enable Steamworks SDK integration" OFF)
|
||||||
|
|
||||||
include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/ThirdParty.cmake)
|
include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/ThirdParty.cmake)
|
||||||
|
|
||||||
# ===========================================
|
# ===========================================
|
||||||
# Основной проект witcher001
|
# Основной проект ShadowOverBishkekDemo
|
||||||
# ===========================================
|
# ===========================================
|
||||||
add_executable(witcher001
|
add_executable(ShadowOverBishkekDemo
|
||||||
../src/main.cpp
|
../src/main.cpp
|
||||||
../src/Game.cpp
|
../src/Game.cpp
|
||||||
../src/Game.h
|
../src/Game.h
|
||||||
@ -42,34 +45,34 @@ add_executable(witcher001
|
|||||||
../src/SparkEmitter.h
|
../src/SparkEmitter.h
|
||||||
../src/TeleportZone.h
|
../src/TeleportZone.h
|
||||||
../src/TeleportZone.cpp
|
../src/TeleportZone.cpp
|
||||||
../src/utils/TaskManager.cpp
|
../src/utils/TaskManager.cpp
|
||||||
../src/utils/TaskManager.h
|
../src/utils/TaskManager.h
|
||||||
../src/render/FrameBuffer.cpp
|
../src/render/FrameBuffer.cpp
|
||||||
../src/render/FrameBuffer.h
|
../src/render/FrameBuffer.h
|
||||||
../src/render/ShadowMap.cpp
|
../src/render/ShadowMap.cpp
|
||||||
../src/render/ShadowMap.h
|
../src/render/ShadowMap.h
|
||||||
../src/UiManager.cpp
|
../src/UiManager.cpp
|
||||||
../src/UiManager.h
|
../src/UiManager.h
|
||||||
../src/render/TextRenderer.h
|
../src/render/TextRenderer.h
|
||||||
../src/render/TextRenderer.cpp
|
../src/render/TextRenderer.cpp
|
||||||
../src/MenuManager.h
|
../src/MenuManager.h
|
||||||
../src/MenuManager.cpp
|
../src/MenuManager.cpp
|
||||||
../src/Location.h
|
../src/Location.h
|
||||||
../src/Location.cpp
|
../src/Location.cpp
|
||||||
../src/LocationState.h
|
../src/LocationState.h
|
||||||
../src/LocationState.cpp
|
../src/LocationState.cpp
|
||||||
../src/LocationEditor.h
|
../src/LocationEditor.h
|
||||||
../src/LocationEditor.cpp
|
../src/LocationEditor.cpp
|
||||||
../src/NpcCar.h
|
../src/NpcCar.h
|
||||||
../src/NpcCar.cpp
|
../src/NpcCar.cpp
|
||||||
../src/GameConstants.h
|
../src/GameConstants.h
|
||||||
../src/GameConstants.cpp
|
../src/GameConstants.cpp
|
||||||
../src/GameState.h
|
../src/GameState.h
|
||||||
../src/GameState.cpp
|
../src/GameState.cpp
|
||||||
../src/ScriptEngine.h
|
../src/ScriptEngine.h
|
||||||
../src/ScriptEngine.cpp
|
../src/ScriptEngine.cpp
|
||||||
../src/navigation/PathFinder.h
|
../src/navigation/PathFinder.h
|
||||||
../src/navigation/PathFinder.cpp
|
../src/navigation/PathFinder.cpp
|
||||||
../src/items/GameObjectLoader.h
|
../src/items/GameObjectLoader.h
|
||||||
../src/items/GameObjectLoader.cpp
|
../src/items/GameObjectLoader.cpp
|
||||||
../src/items/Item.h
|
../src/items/Item.h
|
||||||
@ -79,73 +82,121 @@ add_executable(witcher001
|
|||||||
../src/items/InteractiveObject.h
|
../src/items/InteractiveObject.h
|
||||||
../src/items/InteractiveObject.cpp
|
../src/items/InteractiveObject.cpp
|
||||||
../src/items/InteractiveObjectState.h
|
../src/items/InteractiveObjectState.h
|
||||||
../src/dialogue/DialogueTypes.h
|
../src/dialogue/DialogueTypes.h
|
||||||
../src/dialogue/DialogueDatabase.h
|
../src/dialogue/DialogueDatabase.h
|
||||||
../src/dialogue/DialogueDatabase.cpp
|
../src/dialogue/DialogueDatabase.cpp
|
||||||
../src/dialogue/DialogueRuntime.h
|
../src/dialogue/DialogueRuntime.h
|
||||||
../src/dialogue/DialogueRuntime.cpp
|
../src/dialogue/DialogueRuntime.cpp
|
||||||
../src/dialogue/DialogueOverlay.h
|
../src/dialogue/DialogueOverlay.h
|
||||||
../src/dialogue/DialogueOverlay.cpp
|
../src/dialogue/DialogueOverlay.cpp
|
||||||
../src/dialogue/DialogueSystem.h
|
../src/dialogue/DialogueSystem.h
|
||||||
../src/dialogue/DialogueSystem.cpp
|
../src/dialogue/DialogueSystem.cpp
|
||||||
../src/dialogue/TranslationDatabase.h
|
../src/dialogue/TranslationDatabase.h
|
||||||
../src/dialogue/TranslationDatabase.cpp
|
../src/dialogue/TranslationDatabase.cpp
|
||||||
../src/quest/QuestTypes.h
|
../src/quest/QuestTypes.h
|
||||||
../src/quest/QuestJournal.h
|
../src/quest/QuestJournal.h
|
||||||
../src/quest/QuestJournal.cpp
|
../src/quest/QuestJournal.cpp
|
||||||
../src/cutscene/CutsceneTypes.h
|
../src/cutscene/CutsceneTypes.h
|
||||||
../src/cutscene/CutsceneDatabase.h
|
../src/cutscene/CutsceneDatabase.h
|
||||||
../src/cutscene/CutsceneDatabase.cpp
|
../src/cutscene/CutsceneDatabase.cpp
|
||||||
../src/cutscene/CutsceneRuntime.h
|
../src/cutscene/CutsceneRuntime.h
|
||||||
../src/cutscene/CutsceneRuntime.cpp
|
../src/cutscene/CutsceneRuntime.cpp
|
||||||
../src/cutscene/CutsceneOverlay.h
|
../src/cutscene/CutsceneOverlay.h
|
||||||
../src/cutscene/CutsceneOverlay.cpp
|
../src/cutscene/CutsceneOverlay.cpp
|
||||||
../src/render/UiQuad.h
|
../src/render/UiQuad.h
|
||||||
)
|
)
|
||||||
|
|
||||||
# Установка проекта по умолчанию для Visual Studio
|
# Установка проекта по умолчанию для Visual Studio
|
||||||
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT witcher001)
|
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ShadowOverBishkekDemo)
|
||||||
|
|
||||||
# include-пути проекта
|
# include-пути проекта
|
||||||
target_include_directories(witcher001 PRIVATE
|
target_include_directories(ShadowOverBishkekDemo PRIVATE
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/../src"
|
"${CMAKE_CURRENT_SOURCE_DIR}/../src"
|
||||||
)
|
)
|
||||||
|
|
||||||
set_target_properties(witcher001 PROPERTIES
|
set_target_properties(ShadowOverBishkekDemo PROPERTIES
|
||||||
OUTPUT_NAME "witcher001"
|
OUTPUT_NAME "ShadowOverBishkekDemo"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Определения препроцессора:
|
# Определения препроцессора:
|
||||||
# PNG_ENABLED – включает код PNG в TextureManager
|
# PNG_ENABLED – включает код PNG в TextureManager
|
||||||
# SDL_MAIN_HANDLED – отключает переопределение main -> SDL_main
|
# SDL_MAIN_HANDLED – отключает переопределение main -> SDL_main
|
||||||
target_compile_definitions(witcher001 PRIVATE
|
target_compile_definitions(ShadowOverBishkekDemo PRIVATE
|
||||||
WIN32_LEAN_AND_MEAN
|
WIN32_LEAN_AND_MEAN
|
||||||
PNG_ENABLED
|
PNG_ENABLED
|
||||||
SDL_MAIN_HANDLED
|
SDL_MAIN_HANDLED
|
||||||
# DEBUG_LIGHT
|
# DEBUG_LIGHT
|
||||||
# SHOW_PATH
|
# SHOW_PATH
|
||||||
)
|
)
|
||||||
|
|
||||||
# Линкуем с SDL2main, если он вообще установлен
|
# Линкуем с SDL2main, если он вообще установлен
|
||||||
target_link_libraries(witcher001 PRIVATE SDL2main_external_lib)
|
target_link_libraries(ShadowOverBishkekDemo PRIVATE SDL2main_external_lib)
|
||||||
|
|
||||||
# Линкуем сторонние библиотеки
|
# Линкуем сторонние библиотеки
|
||||||
target_link_libraries(witcher001 PRIVATE
|
target_link_libraries(ShadowOverBishkekDemo PRIVATE
|
||||||
SDL2_external_lib
|
SDL2_external_lib
|
||||||
libpng_external_lib
|
libpng_external_lib
|
||||||
zlib_external_lib
|
zlib_external_lib
|
||||||
libzip_external_lib
|
libzip_external_lib
|
||||||
freetype_external_lib
|
freetype_external_lib
|
||||||
SDL2_ttf_external_lib
|
SDL2_ttf_external_lib
|
||||||
eigen_external_lib
|
eigen_external_lib
|
||||||
boost_external_lib
|
boost_external_lib
|
||||||
sol2_external_lib
|
sol2_external_lib
|
||||||
SDL2_mixer_external_lib
|
SDL2_mixer_external_lib
|
||||||
)
|
)
|
||||||
|
|
||||||
# Линкуем OpenGL (Windows)
|
# Линкуем OpenGL (Windows)
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
target_link_libraries(witcher001 PRIVATE opengl32)
|
target_link_libraries(ShadowOverBishkekDemo PRIVATE opengl32)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# ===========================================
|
||||||
|
# Интеграция Steamworks SDK (если STEAMSDK=ON)
|
||||||
|
# ===========================================
|
||||||
|
if(STEAMSDK)
|
||||||
|
message(STATUS "Steamworks SDK integration is ENABLED.")
|
||||||
|
|
||||||
|
# Макрос STEAMSDK для условной компиляции в C++ коде (#ifdef STEAMSDK)
|
||||||
|
target_compile_definitions(ShadowOverBishkekDemo PRIVATE STEAMSDK)
|
||||||
|
|
||||||
|
set(STEAM_SDK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty/steamworks_sdk_164/sdk")
|
||||||
|
|
||||||
|
# Подключение заголовочных файлов Steamworks
|
||||||
|
target_include_directories(ShadowOverBishkekDemo PRIVATE
|
||||||
|
"${STEAM_SDK_DIR}/public"
|
||||||
|
"${STEAM_SDK_DIR}/public/steam"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Определение разрядности сборки (x86 vs x64) для выбора версий lib и dll
|
||||||
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
|
set(STEAM_LIB_DIR "${STEAM_SDK_DIR}/redistributable_bin/win64")
|
||||||
|
set(STEAM_LIB_NAME "steam_api64")
|
||||||
|
set(STEAM_DLL_NAME "steam_api64.dll")
|
||||||
|
else()
|
||||||
|
set(STEAM_LIB_DIR "${STEAM_SDK_DIR}/redistributable_bin")
|
||||||
|
set(STEAM_LIB_NAME "steam_api")
|
||||||
|
set(STEAM_DLL_NAME "steam_api.dll")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Поиск библиотеки линковки (.lib)
|
||||||
|
find_library(STEAM_LIBRARY
|
||||||
|
NAMES ${STEAM_LIB_NAME}
|
||||||
|
PATHS ${STEAM_LIB_DIR}
|
||||||
|
NO_DEFAULT_PATH
|
||||||
|
)
|
||||||
|
|
||||||
|
if(STEAM_LIBRARY)
|
||||||
|
target_link_libraries(ShadowOverBishkekDemo PRIVATE ${STEAM_LIBRARY})
|
||||||
|
message(STATUS "Found Steam API library: ${STEAM_LIBRARY}")
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "Steam API library (${STEAM_LIB_NAME}) NOT found in ${STEAM_LIB_DIR}!")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Генерация временного файла steam_appid.txt с ID демо-версии (4945840)
|
||||||
|
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/steam_appid.txt" "4945840")
|
||||||
|
else()
|
||||||
|
message(STATUS "Steamworks SDK integration is DISABLED.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# ===========================================
|
# ===========================================
|
||||||
@ -155,19 +206,19 @@ if (WIN32)
|
|||||||
|
|
||||||
# SDL2: в Debug - SDL2d.dll, в Release - SDL2.dll
|
# SDL2: в Debug - SDL2d.dll, в Release - SDL2.dll
|
||||||
set(SDL2_DLL_SRC "$<IF:$<CONFIG:Debug>,${SDL2_INSTALL_DIR}/bin/SDL2d.dll,${SDL2_INSTALL_DIR}/bin/SDL2.dll>")
|
set(SDL2_DLL_SRC "$<IF:$<CONFIG:Debug>,${SDL2_INSTALL_DIR}/bin/SDL2d.dll,${SDL2_INSTALL_DIR}/bin/SDL2.dll>")
|
||||||
set(SDL2_DLL_DST "$<IF:$<CONFIG:Debug>,$<TARGET_FILE_DIR:witcher001>/SDL2d.dll,$<TARGET_FILE_DIR:witcher001>/SDL2.dll>")
|
set(SDL2_DLL_DST "$<IF:$<CONFIG:Debug>,$<TARGET_FILE_DIR:ShadowOverBishkekDemo>/SDL2d.dll,$<TARGET_FILE_DIR:ShadowOverBishkekDemo>/SDL2.dll>")
|
||||||
|
|
||||||
|
|
||||||
set(LIBZIP_DLL_SRC "$<IF:$<CONFIG:Debug>,${LIBZIP_BASE_DIR}-Debug/bin/zip.dll,${LIBZIP_BASE_DIR}-Release/bin/zip.dll>")
|
set(LIBZIP_DLL_SRC "$<IF:$<CONFIG:Debug>,${LIBZIP_BASE_DIR}-Debug/bin/zip.dll,${LIBZIP_BASE_DIR}-Release/bin/zip.dll>")
|
||||||
|
|
||||||
set(ZLIB_DLL_SRC "$<IF:$<CONFIG:Debug>,${ZLIB_INSTALL_DIR}/bin/zd.dll,${ZLIB_INSTALL_DIR}/bin/z.dll>")
|
set(ZLIB_DLL_SRC "$<IF:$<CONFIG:Debug>,${ZLIB_INSTALL_DIR}/bin/zd.dll,${ZLIB_INSTALL_DIR}/bin/z.dll>")
|
||||||
set(ZLIB_DLL_DST "$<IF:$<CONFIG:Debug>,$<TARGET_FILE_DIR:witcher001>/zd.dll,$<TARGET_FILE_DIR:witcher001>/z.dll>")
|
set(ZLIB_DLL_DST "$<IF:$<CONFIG:Debug>,$<TARGET_FILE_DIR:ShadowOverBishkekDemo>/zd.dll,$<TARGET_FILE_DIR:ShadowOverBishkekDemo>/z.dll>")
|
||||||
|
|
||||||
set(SDL2TTF_DLL_SRC "$<IF:$<CONFIG:Debug>,${SDL2TTF_BASE_DIR}-Debug/bin/SDL2_ttfd.dll,${SDL2TTF_BASE_DIR}-Release/bin/SDL2_ttf.dll>")
|
set(SDL2TTF_DLL_SRC "$<IF:$<CONFIG:Debug>,${SDL2TTF_BASE_DIR}-Debug/bin/SDL2_ttfd.dll,${SDL2TTF_BASE_DIR}-Release/bin/SDL2_ttf.dll>")
|
||||||
|
|
||||||
set(SDL2MIXER_DLL_SRC "$<IF:$<CONFIG:Debug>,${SDL2MIXER_BASE_DIR}-Debug/bin/SDL2_mixerd.dll,${SDL2MIXER_BASE_DIR}-Release/bin/SDL2_mixer.dll>")
|
set(SDL2MIXER_DLL_SRC "$<IF:$<CONFIG:Debug>,${SDL2MIXER_BASE_DIR}-Debug/bin/SDL2_mixerd.dll,${SDL2MIXER_BASE_DIR}-Release/bin/SDL2_mixer.dll>")
|
||||||
|
|
||||||
add_custom_command(TARGET witcher001 POST_BUILD
|
add_custom_command(TARGET ShadowOverBishkekDemo POST_BUILD
|
||||||
COMMAND ${CMAKE_COMMAND} -E echo "Copying DLLs to output folder..."
|
COMMAND ${CMAKE_COMMAND} -E echo "Copying DLLs to output folder..."
|
||||||
|
|
||||||
# Копируем SDL2 (целевое имя всегда SDL2.dll)
|
# Копируем SDL2 (целевое имя всегда SDL2.dll)
|
||||||
@ -178,23 +229,39 @@ add_custom_command(TARGET witcher001 POST_BUILD
|
|||||||
# Копируем LIBZIP (целевое имя всегда zip.dll)
|
# Копируем LIBZIP (целевое имя всегда zip.dll)
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
"${LIBZIP_DLL_SRC}"
|
"${LIBZIP_DLL_SRC}"
|
||||||
"$<TARGET_FILE_DIR:witcher001>/zip.dll"
|
"$<TARGET_FILE_DIR:ShadowOverBishkekDemo>/zip.dll"
|
||||||
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
"${ZLIB_DLL_SRC}"
|
"${ZLIB_DLL_SRC}"
|
||||||
"${ZLIB_DLL_DST}"
|
"${ZLIB_DLL_DST}"
|
||||||
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
"${SDL2TTF_DLL_SRC}"
|
"${SDL2TTF_DLL_SRC}"
|
||||||
"$<TARGET_FILE_DIR:witcher001>"
|
"$<TARGET_FILE_DIR:ShadowOverBishkekDemo>"
|
||||||
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty/SDL_mixer-release-2.8.0/install-$<CONFIG>/bin/SDL2_mixer$<$<CONFIG:Debug>:d>.dll"
|
"${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty/SDL_mixer-release-2.8.0/install-$<CONFIG>/bin/SDL2_mixer$<$<CONFIG:Debug>:d>.dll"
|
||||||
|
"$<TARGET_FILE_DIR:ShadowOverBishkekDemo>/SDL2_mixer$<$<CONFIG:Debug>:d>.dll"
|
||||||
# This is only for profiling:
|
|
||||||
#"${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty/SDL_mixer-release-2.8.0/install-Release/bin/SDL2_mixer$<$<CONFIG:Debug>:d>.dll"
|
|
||||||
"$<TARGET_FILE_DIR:witcher001>/SDL2_mixer$<$<CONFIG:Debug>:d>.dll"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Если включен Steam, добавляем шаги копирования DLL и appid в этот же POST_BUILD
|
||||||
|
if(STEAMSDK)
|
||||||
|
add_custom_command(TARGET ShadowOverBishkekDemo POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E echo "Copying Steam SDK components..."
|
||||||
|
# Копирование dll к исполняемому файлу
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
|
"${STEAM_LIB_DIR}/${STEAM_DLL_NAME}"
|
||||||
|
"$<TARGET_FILE_DIR:ShadowOverBishkekDemo>/${STEAM_DLL_NAME}"
|
||||||
|
# Копирование steam_appid.txt к исполняемому файлу
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/steam_appid.txt"
|
||||||
|
"$<TARGET_FILE_DIR:ShadowOverBishkekDemo>/steam_appid.txt"
|
||||||
|
# Дублируем steam_appid.txt в корень сборки (полезно при отладке прямо из MSVC)
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/steam_appid.txt"
|
||||||
|
"${CMAKE_BINARY_DIR}/steam_appid.txt"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# ===========================================
|
# ===========================================
|
||||||
@ -204,17 +271,17 @@ endif()
|
|||||||
# Какие папки с ресурсами нужно копировать
|
# Какие папки с ресурсами нужно копировать
|
||||||
set(RUNTIME_RESOURCE_DIRS
|
set(RUNTIME_RESOURCE_DIRS
|
||||||
"resources"
|
"resources"
|
||||||
"audio"
|
"audio"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Копируем ресурсы и шейдеры в папку exe и в корень build/
|
# Копируем ресурсы и шейдеры в папку exe и в корень build/
|
||||||
foreach(resdir IN LISTS RUNTIME_RESOURCE_DIRS)
|
foreach(resdir IN LISTS RUNTIME_RESOURCE_DIRS)
|
||||||
add_custom_command(TARGET witcher001 POST_BUILD
|
add_custom_command(TARGET ShadowOverBishkekDemo POST_BUILD
|
||||||
COMMAND ${CMAKE_COMMAND} -E echo "Copying ${resdir} to runtime folders..."
|
COMMAND ${CMAKE_COMMAND} -E echo "Copying ${resdir} to runtime folders..."
|
||||||
# 1) туда, где лежит exe (build/Debug, build/Release и т.п.)
|
# 1) туда, где лежит exe (build/Debug, build/Release и т.п.)
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||||
"${CMAKE_SOURCE_DIR}/../${resdir}"
|
"${CMAKE_SOURCE_DIR}/../${resdir}"
|
||||||
"$<TARGET_FILE_DIR:witcher001>/${resdir}"
|
"$<TARGET_FILE_DIR:ShadowOverBishkekDemo>/${resdir}"
|
||||||
# 2) в корень build, если захочешь запускать из этой папки
|
# 2) в корень build, если захочешь запускать из этой папки
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||||
"${CMAKE_SOURCE_DIR}/../${resdir}"
|
"${CMAKE_SOURCE_DIR}/../${resdir}"
|
||||||
|
|||||||
473
src/main.cpp
473
src/main.cpp
@ -11,120 +11,114 @@
|
|||||||
#include <emscripten/html5.h>
|
#include <emscripten/html5.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef STEAMSDK
|
||||||
// For Emscripten the game is heap-allocated so it can be destroyed and
|
#include "steam_api.h"
|
||||||
// re-created when the WebGL context is lost and restored (e.g. fullscreen).
|
|
||||||
// For Android and Desktop a plain global value is used (no context loss).
|
|
||||||
#ifdef EMSCRIPTEN
|
|
||||||
ZL::Game* g_game = nullptr;
|
|
||||||
//static SDL_Window* win_x = nullptr;
|
|
||||||
static SDL_GLContext glContext_x; // Не указатель, а сам объект (который суть void*)
|
|
||||||
|
|
||||||
#else
|
|
||||||
ZL::Game game;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef EMSCRIPTEN
|
#if defined(EMSCRIPTEN)
|
||||||
|
static SDL_GLContext glContext_x;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Единый указатель на объект игры для всех платформ
|
||||||
|
ZL::Game* g_game = nullptr;
|
||||||
|
|
||||||
|
|
||||||
void MainLoop() {
|
void MainLoop() {
|
||||||
g_game->update();
|
g_game->update();
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
void MainLoop() {
|
|
||||||
game.update();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef EMSCRIPTEN
|
#ifdef EMSCRIPTEN
|
||||||
|
|
||||||
EM_BOOL onWebGLContextLost(int /*eventType*/, const void* /*reserved*/, void* /*userData*/) {
|
EM_BOOL onWebGLContextLost(int /*eventType*/, const void* /*reserved*/, void* /*userData*/) {
|
||||||
return EM_TRUE;
|
return EM_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
EM_BOOL onWebGLContextRestored(int /*eventType*/, const void* /*reserved*/, void* /*userData*/) {
|
EM_BOOL onWebGLContextRestored(int /*eventType*/, const void* /*reserved*/, void* /*userData*/) {
|
||||||
return EM_TRUE;
|
return EM_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void applyResize(int logicalW, int logicalH) {
|
static void applyResize(int logicalW, int logicalH) {
|
||||||
// Получаем коэффициент плотности пикселей (например, 2.625 на Pixel или 3.0 на Samsung)
|
// Получаем коэффициент плотности пикселей (например, 2.625 на Pixel или 3.0 на Samsung)
|
||||||
double dpr = emscripten_get_device_pixel_ratio();
|
double dpr = emscripten_get_device_pixel_ratio();
|
||||||
//double dpr = 1; // low quality
|
//double dpr = 1; // low quality
|
||||||
|
|
||||||
// Вычисляем реальные физические пиксели
|
// Вычисляем реальные физические пиксели
|
||||||
int physicalW = static_cast<int>(logicalW * dpr);
|
int physicalW = static_cast<int>(logicalW * dpr);
|
||||||
int physicalH = static_cast<int>(logicalH * dpr);
|
int physicalH = static_cast<int>(logicalH * dpr);
|
||||||
|
|
||||||
// Устанавливаем размер внутреннего буфера канваса
|
// Устанавливаем размер внутреннего буфера канваса
|
||||||
emscripten_set_canvas_element_size("#canvas", physicalW, physicalH);
|
emscripten_set_canvas_element_size("#canvas", physicalW, physicalH);
|
||||||
|
|
||||||
// Сообщаем SDL о новом размере.
|
// Сообщаем SDL о новом размере.
|
||||||
// ВАЖНО: SDL2 в Emscripten ожидает здесь именно физические пиксели
|
// ВАЖНО: SDL2 в Emscripten ожидает здесь именно физические пиксели
|
||||||
// для корректной работы последующих вызовов glViewport.
|
// для корректной работы последующих вызовов glViewport.
|
||||||
if (ZL::Environment::window) {
|
if (ZL::Environment::window) {
|
||||||
SDL_SetWindowSize(ZL::Environment::window, physicalW, physicalH);
|
SDL_SetWindowSize(ZL::Environment::window, physicalW, physicalH);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Пушим событие, чтобы движок пересчитал матрицы проекции
|
// Пушим событие, чтобы движок пересчитал матрицы проекции
|
||||||
SDL_Event e = {};
|
SDL_Event e = {};
|
||||||
e.type = SDL_WINDOWEVENT;
|
e.type = SDL_WINDOWEVENT;
|
||||||
e.window.event = SDL_WINDOWEVENT_RESIZED;
|
e.window.event = SDL_WINDOWEVENT_RESIZED;
|
||||||
e.window.data1 = physicalW;
|
e.window.data1 = physicalW;
|
||||||
e.window.data2 = physicalH;
|
e.window.data2 = physicalH;
|
||||||
SDL_PushEvent(&e);
|
SDL_PushEvent(&e);
|
||||||
|
|
||||||
std::cout << "Resized, new size: " << logicalW << "x" << logicalH
|
std::cout << "Resized, new size: " << logicalW << "x" << logicalH
|
||||||
<< " (physical: " << physicalW << "x" << physicalH
|
<< " (physical: " << physicalW << "x" << physicalH
|
||||||
<< ", DPR: " << dpr << ")" << std::endl;
|
<< ", DPR: " << dpr << ")" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
EM_BOOL onWindowResized(int /*eventType*/, const EmscriptenUiEvent* e, void* /*userData*/) {
|
EM_BOOL onWindowResized(int /*eventType*/, const EmscriptenUiEvent* e, void* /*userData*/) {
|
||||||
// Use the event's window dimensions — querying the canvas element would
|
// Use the event's window dimensions — querying the canvas element would
|
||||||
// return its old fixed size (e.g. 1280x720) before it has been resized.
|
// return its old fixed size (e.g. 1280x720) before it has been resized.
|
||||||
applyResize(e->windowInnerWidth, e->windowInnerHeight);
|
applyResize(e->windowInnerWidth, e->windowInnerHeight);
|
||||||
return EM_FALSE;
|
return EM_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
EM_BOOL onFullscreenChanged(int /*eventType*/, const EmscriptenFullscreenChangeEvent* e, void* /*userData*/) {
|
EM_BOOL onFullscreenChanged(int /*eventType*/, const EmscriptenFullscreenChangeEvent* e, void* /*userData*/) {
|
||||||
ZL::Environment::isFullscreen = e->isFullscreen;
|
ZL::Environment::isFullscreen = e->isFullscreen;
|
||||||
|
|
||||||
// Вместо window.innerWidth, попробуйте запросить размер целевого элемента
|
// Вместо window.innerWidth, попробуйте запросить размер целевого элемента
|
||||||
// так как после перехода в FS именно он растягивается на весь экран.
|
// так как после перехода в FS именно он растягивается на весь экран.
|
||||||
double clientW, clientH;
|
double clientW, clientH;
|
||||||
emscripten_get_element_css_size("#canvas", &clientW, &clientH);
|
emscripten_get_element_css_size("#canvas", &clientW, &clientH);
|
||||||
applyResize(clientW, clientH);
|
applyResize(clientW, clientH);
|
||||||
return EM_FALSE;
|
return EM_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
|
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
|
||||||
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); // Для WebGL 2.0
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); // Для WebGL 2.0
|
||||||
|
|
||||||
ZL::Environment::window = SDL_CreateWindow("Game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
|
ZL::Environment::window = SDL_CreateWindow("Game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
|
||||||
glContext_x = SDL_GL_CreateContext(ZL::Environment::window);
|
glContext_x = SDL_GL_CreateContext(ZL::Environment::window);
|
||||||
|
|
||||||
SDL_GL_MakeCurrent(ZL::Environment::window, glContext_x);
|
SDL_GL_MakeCurrent(ZL::Environment::window, glContext_x);
|
||||||
|
|
||||||
g_game = new ZL::Game();
|
g_game = new ZL::Game();
|
||||||
g_game->setup();
|
g_game->setup();
|
||||||
|
|
||||||
emscripten_set_webglcontextlost_callback("#canvas", nullptr, EM_TRUE, onWebGLContextLost);
|
emscripten_set_webglcontextlost_callback("#canvas", nullptr, EM_TRUE, onWebGLContextLost);
|
||||||
emscripten_set_webglcontextrestored_callback("#canvas", nullptr, EM_TRUE, onWebGLContextRestored);
|
emscripten_set_webglcontextrestored_callback("#canvas", nullptr, EM_TRUE, onWebGLContextRestored);
|
||||||
|
|
||||||
// Keep Environment::width/height in sync when the canvas is resized.
|
// Keep Environment::width/height in sync when the canvas is resized.
|
||||||
emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, EM_FALSE, onWindowResized);
|
emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, EM_FALSE, onWindowResized);
|
||||||
emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, nullptr, EM_FALSE, onFullscreenChanged);
|
emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, nullptr, EM_FALSE, onFullscreenChanged);
|
||||||
|
|
||||||
// 2. ИНИЦИАЛИЗАЦИЯ РАЗМЕРОВ:
|
// 2. ИНИЦИАЛИЗАЦИЯ РАЗМЕРОВ:
|
||||||
// Получаем реальные размеры окна браузера на момент запуска
|
// Получаем реальные размеры окна браузера на момент запуска
|
||||||
int canvasW = EM_ASM_INT({ return window.innerWidth; });
|
int canvasW = EM_ASM_INT({ return window.innerWidth; });
|
||||||
int canvasH = EM_ASM_INT({ return window.innerHeight; });
|
int canvasH = EM_ASM_INT({ return window.innerHeight; });
|
||||||
|
|
||||||
// Вызываем вашу функцию — она сама применит DPR, выставит физический размер
|
// Вызываем вашу функцию — она сама применит DPR, выставит физический размер
|
||||||
// канваса и отправит SDL_WINDOWEVENT_RESIZED для настройки проекции.
|
// канваса и отправит SDL_WINDOWEVENT_RESIZED для настройки проекции.
|
||||||
applyResize(canvasW, canvasH);
|
applyResize(canvasW, canvasH);
|
||||||
|
|
||||||
// Prevent mouse clicks from generating fake SDL_FINGERDOWN events (desktop browser)
|
// Prevent mouse clicks from generating fake SDL_FINGERDOWN events (desktop browser)
|
||||||
SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "0");
|
SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "0");
|
||||||
@ -132,12 +126,12 @@ int main(int argc, char* argv[]) {
|
|||||||
// since we now handle SDL_FINGERDOWN directly for multi-touch support.
|
// since we now handle SDL_FINGERDOWN directly for multi-touch support.
|
||||||
SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");
|
SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");
|
||||||
|
|
||||||
ZL::emscriptenInitFileSystem();
|
ZL::emscriptenInitFileSystem();
|
||||||
|
|
||||||
emscripten_set_main_loop(MainLoop, 0, 1);
|
emscripten_set_main_loop(MainLoop, 0, 1);
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -147,82 +141,83 @@ int main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
extern "C" int SDL_main(int argc, char* argv[]) {
|
extern "C" int SDL_main(int argc, char* argv[]) {
|
||||||
// Инициализация SDL перед получением информации о дисплее
|
// Инициализация SDL перед получением информации о дисплее
|
||||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) {
|
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) {
|
||||||
__android_log_print(ANDROID_LOG_ERROR, "Game", "SDL init failed: %s", SDL_GetError());
|
__android_log_print(ANDROID_LOG_ERROR, "Game", "SDL init failed: %s", SDL_GetError());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_DisplayMode displayMode;
|
SDL_DisplayMode displayMode;
|
||||||
if (SDL_GetCurrentDisplayMode(0, &displayMode) != 0) {
|
if (SDL_GetCurrentDisplayMode(0, &displayMode) != 0) {
|
||||||
__android_log_print(ANDROID_LOG_ERROR, "Game", "SDL_GetCurrentDisplayMode failed: %s", SDL_GetError());
|
__android_log_print(ANDROID_LOG_ERROR, "Game", "SDL_GetCurrentDisplayMode failed: %s", SDL_GetError());
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
ZL::Environment::width = displayMode.w;
|
ZL::Environment::width = displayMode.w;
|
||||||
ZL::Environment::height = displayMode.h;
|
ZL::Environment::height = displayMode.h;
|
||||||
|
|
||||||
__android_log_print(ANDROID_LOG_INFO, "Game", "Display resolution: %dx%d",
|
__android_log_print(ANDROID_LOG_INFO, "Game", "Display resolution: %dx%d",
|
||||||
ZL::Environment::width, ZL::Environment::height);
|
ZL::Environment::width, ZL::Environment::height);
|
||||||
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
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, 2);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||||
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
|
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
|
||||||
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
|
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
|
||||||
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
|
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
|
||||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
|
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
|
||||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||||
|
|
||||||
|
|
||||||
ZL::Environment::window = SDL_CreateWindow(
|
ZL::Environment::window = SDL_CreateWindow(
|
||||||
"Shadow Over Bishkek",
|
"Shadow Over Bishkek",
|
||||||
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
|
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
|
||||||
ZL::Environment::width, ZL::Environment::height,
|
ZL::Environment::width, ZL::Environment::height,
|
||||||
SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN
|
SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!ZL::Environment::window) {
|
if (!ZL::Environment::window) {
|
||||||
__android_log_print(ANDROID_LOG_ERROR, "Game", "Failed to create window: %s", SDL_GetError());
|
__android_log_print(ANDROID_LOG_ERROR, "Game", "Failed to create window: %s", SDL_GetError());
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_GLContext ctx = SDL_GL_CreateContext(ZL::Environment::window);
|
SDL_GLContext ctx = SDL_GL_CreateContext(ZL::Environment::window);
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
__android_log_print(ANDROID_LOG_ERROR, "Game", "SDL_GL_CreateContext failed: %s", SDL_GetError());
|
__android_log_print(ANDROID_LOG_ERROR, "Game", "SDL_GL_CreateContext failed: %s", SDL_GetError());
|
||||||
SDL_DestroyWindow(ZL::Environment::window);
|
SDL_DestroyWindow(ZL::Environment::window);
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SDL_GL_MakeCurrent(ZL::Environment::window, ctx) != 0) {
|
if (SDL_GL_MakeCurrent(ZL::Environment::window, ctx) != 0) {
|
||||||
__android_log_print(ANDROID_LOG_ERROR, "Game", "SDL_GL_MakeCurrent failed: %s", SDL_GetError());
|
__android_log_print(ANDROID_LOG_ERROR, "Game", "SDL_GL_MakeCurrent failed: %s", SDL_GetError());
|
||||||
SDL_GL_DeleteContext(ctx);
|
SDL_GL_DeleteContext(ctx);
|
||||||
SDL_DestroyWindow(ZL::Environment::window);
|
SDL_DestroyWindow(ZL::Environment::window);
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Настройка VSync
|
// Настройка VSync
|
||||||
if (SDL_GL_SetSwapInterval(1) < 0) {
|
if (SDL_GL_SetSwapInterval(1) < 0) {
|
||||||
__android_log_print(ANDROID_LOG_WARN, "Game", "Unable to set VSync: %s", SDL_GetError());
|
__android_log_print(ANDROID_LOG_WARN, "Game", "Unable to set VSync: %s", SDL_GetError());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Настройка игры
|
// Настройка игры
|
||||||
try {
|
try {
|
||||||
game.setup();
|
game.setup();
|
||||||
} catch (const std::exception &e) {
|
}
|
||||||
__android_log_print(ANDROID_LOG_ERROR, "Game", "Game setup failed: %s", e.what());
|
catch (const std::exception& e) {
|
||||||
return 1;
|
__android_log_print(ANDROID_LOG_ERROR, "Game", "Game setup failed: %s", e.what());
|
||||||
}
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
while (!game.shouldExit()) {
|
while (!game.shouldExit()) {
|
||||||
game.update();
|
game.update();
|
||||||
SDL_Delay(16);
|
SDL_Delay(16);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,113 +226,157 @@ extern "C" int SDL_main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__linux__)
|
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__linux__)
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
try
|
|
||||||
{
|
|
||||||
|
|
||||||
SDL_SetHint(SDL_HINT_WINDOWS_DPI_AWARENESS, "permonitorv2");
|
SDL_GLContext ctx = nullptr;
|
||||||
//SDL_SetHint(SDL_HINT_WINDOWS_DPI_SCALING, "1");
|
try
|
||||||
|
{
|
||||||
|
#ifdef STEAMSDK
|
||||||
|
// Передаем явный App ID демо-версии
|
||||||
|
if (SteamAPI_RestartAppIfNecessary(4945840)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
constexpr int CONST_WIDTH = ZL::Environment::CONST_DEFAULT_WIDTH;
|
if (!SteamAPI_Init()) {
|
||||||
constexpr int CONST_HEIGHT = ZL::Environment::CONST_DEFAULT_HEIGHT;
|
std::cerr << "SteamAPI_Init() failed! Steam client might not be running.\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ZL::Environment::width = CONST_WIDTH;
|
SDL_SetHint(SDL_HINT_WINDOWS_DPI_AWARENESS, "permonitorv2");
|
||||||
ZL::Environment::height = CONST_HEIGHT;
|
|
||||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) {
|
|
||||||
SDL_Log("SDL init failed: %s", SDL_GetError());
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
constexpr int CONST_WIDTH = ZL::Environment::CONST_DEFAULT_WIDTH;
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
|
constexpr int CONST_HEIGHT = ZL::Environment::CONST_DEFAULT_HEIGHT;
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
|
||||||
|
|
||||||
// Read the persisted fullscreen preference (if any) before creating the
|
ZL::Environment::width = CONST_WIDTH;
|
||||||
// window, so it opens directly in the right mode instead of flashing
|
ZL::Environment::height = CONST_HEIGHT;
|
||||||
// windowed -> fullscreen once settings are loaded later during setupPart2().
|
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) {
|
||||||
{
|
SDL_Log("SDL init failed: %s", SDL_GetError());
|
||||||
const std::string settingsContent = ZL::readSavedTextFile("settings.json");
|
return 1;
|
||||||
if (!settingsContent.empty()) {
|
}
|
||||||
try {
|
|
||||||
const nlohmann::json settingsRoot = nlohmann::json::parse(settingsContent);
|
|
||||||
if (settingsRoot.contains("fullscreen")) {
|
|
||||||
ZL::Environment::isFullscreen = settingsRoot["fullscreen"].get<bool>();
|
|
||||||
}
|
|
||||||
if (settingsRoot.contains("isHighDPIEnabled")) {
|
|
||||||
ZL::Environment::isHighDPIEnabled = settingsRoot["isHighDPIEnabled"].get<bool>();
|
|
||||||
}
|
|
||||||
} catch (const std::exception& e) {
|
|
||||||
std::cerr << "[settings] Failed to parse settings.json: " << e.what() << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Uint32 windowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_RESIZABLE;
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||||
if (ZL::Environment::isFullscreen) {
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
|
||||||
windowFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||||
}
|
|
||||||
|
|
||||||
//ZL::Environment::isFullscreen = false;
|
// Read the persisted fullscreen preference (if any) before creating the
|
||||||
|
// window, so it opens directly in the right mode instead of flashing
|
||||||
|
// windowed -> fullscreen once settings are loaded later during setupPart2().
|
||||||
|
{
|
||||||
|
|
||||||
SDL_DisplayMode dm;
|
const std::string settingsContent = ZL::readSavedTextFile("settings.json");
|
||||||
if (SDL_GetCurrentDisplayMode(0, &dm) == 0) {
|
if (!settingsContent.empty()) {
|
||||||
std::cout << "Desktop resolution: " << dm.w << "x" << dm.h << " @ " << dm.refresh_rate << "Hz\n";
|
try {
|
||||||
}
|
const nlohmann::json settingsRoot = nlohmann::json::parse(settingsContent);
|
||||||
else {
|
if (settingsRoot.contains("fullscreen")) {
|
||||||
SDL_Log("SDL_GetCurrentDisplayMode failed: %s", SDL_GetError());
|
ZL::Environment::isFullscreen = settingsRoot["fullscreen"].get<bool>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (settingsRoot.contains("isHighDPIEnabled")) {
|
||||||
|
ZL::Environment::isHighDPIEnabled = settingsRoot["isHighDPIEnabled"].get<bool>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (const std::exception& e) {
|
||||||
|
std::cerr << "[settings] Failed to parse settings.json: " << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Uint32 windowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_RESIZABLE;
|
||||||
|
if (ZL::Environment::isFullscreen) {
|
||||||
|
windowFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_DisplayMode dm;
|
||||||
|
if (SDL_GetCurrentDisplayMode(0, &dm) == 0) {
|
||||||
|
std::cout << "Desktop resolution: " << dm.w << "x" << dm.h << " @ " << dm.refresh_rate << "Hz\n";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SDL_Log("SDL_GetCurrentDisplayMode failed: %s", SDL_GetError());
|
||||||
|
}
|
||||||
|
|
||||||
int windowWidth = ZL::Environment::width;
|
int windowWidth = ZL::Environment::width;
|
||||||
int windowHeight = ZL::Environment::height;
|
int windowHeight = ZL::Environment::height;
|
||||||
|
|
||||||
//In case if the game is launched on a small screen
|
|
||||||
if (dm.w <= 1280 && dm.h <= 720) {
|
if (dm.w <= 1280 && dm.h <= 720) {
|
||||||
windowWidth = round(dm.w / 1.5);
|
windowWidth = round(dm.w / 1.5);
|
||||||
windowHeight = round(dm.h / 1.5);
|
windowHeight = round(dm.h / 1.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
ZL::Environment::window = SDL_CreateWindow(
|
ZL::Environment::window = SDL_CreateWindow(
|
||||||
"Shadow Over Bishkek",
|
"Shadow Over Bishkek Demo",
|
||||||
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
|
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
|
||||||
windowWidth, windowHeight,
|
windowWidth, windowHeight,
|
||||||
windowFlags
|
windowFlags
|
||||||
);
|
);
|
||||||
|
|
||||||
SDL_GLContext ctx = SDL_GL_CreateContext(ZL::Environment::window);
|
ctx = SDL_GL_CreateContext(ZL::Environment::window);
|
||||||
SDL_GL_MakeCurrent(ZL::Environment::window, ctx);
|
SDL_GL_MakeCurrent(ZL::Environment::window, ctx);
|
||||||
|
|
||||||
// On HiDPI displays the drawable (physical) size is larger than the
|
if (ZL::Environment::isHighDPIEnabled) {
|
||||||
// logical window size. Use the drawable size so the GL framebuffer
|
int drawW, drawH;
|
||||||
// covers every physical pixel and the image stays sharp.
|
SDL_GL_GetDrawableSize(ZL::Environment::window, &drawW, &drawH);
|
||||||
if (ZL::Environment::isHighDPIEnabled)
|
ZL::Environment::width = drawW;
|
||||||
{
|
ZL::Environment::height = drawH;
|
||||||
int drawW, drawH;
|
|
||||||
SDL_GL_GetDrawableSize(ZL::Environment::window, &drawW, &drawH);
|
|
||||||
ZL::Environment::width = drawW;
|
|
||||||
ZL::Environment::height = drawH;
|
|
||||||
std::cout << "HiDPI enabled, drawable size: " << drawW << "x" << drawH << std::endl;
|
std::cout << "HiDPI enabled, drawable size: " << drawW << "x" << drawH << std::endl;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
int winW, winH;
|
int winW, winH;
|
||||||
SDL_GetWindowSize(ZL::Environment::window, &winW, &winH);
|
SDL_GetWindowSize(ZL::Environment::window, &winW, &winH);
|
||||||
ZL::Environment::width = winW;
|
ZL::Environment::width = winW;
|
||||||
ZL::Environment::height = winH;
|
ZL::Environment::height = winH;
|
||||||
std::cout << "HiDPI disabled, window size: " << winW << "x" << winH << std::endl;
|
std::cout << "HiDPI disabled, window size: " << winW << "x" << winH << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
game.setup();
|
// Динамическое создание объекта игры
|
||||||
|
g_game = new ZL::Game();
|
||||||
|
g_game->setup();
|
||||||
|
|
||||||
while (!game.shouldExit()) {
|
while (!g_game->shouldExit()) {
|
||||||
game.update();
|
g_game->update();
|
||||||
SDL_Delay(2);
|
SDL_Delay(2);
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (const std::exception& e)
|
|
||||||
{
|
|
||||||
std::cout << e.what() << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
#ifdef STEAMSDK
|
||||||
|
SteamAPI_RunCallbacks();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Явное уничтожение объекта игры ДО завершения работы Steamworks
|
||||||
|
delete g_game;
|
||||||
|
g_game = nullptr;
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
std::cerr << "Exception caught: " << e.what() << std::endl;
|
||||||
|
if (g_game) {
|
||||||
|
delete g_game;
|
||||||
|
g_game = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
std::cerr << "Unknown exception happened: " << std::endl;
|
||||||
|
if (g_game) {
|
||||||
|
delete g_game;
|
||||||
|
g_game = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef STEAMSDK
|
||||||
|
// Деинициализация Steamworks происходит только тогда, когда все объекты игры гарантированно уничтожены
|
||||||
|
SteamAPI_Shutdown();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Очистка ресурсов SDL
|
||||||
|
if (ctx) {
|
||||||
|
SDL_GL_DeleteContext(ctx);
|
||||||
|
}
|
||||||
|
if (ZL::Environment::window) {
|
||||||
|
SDL_DestroyWindow(ZL::Environment::window);
|
||||||
|
}
|
||||||
|
SDL_Quit();
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user