Compare commits

...
112 Commits
Author SHA1 Message Date
Vlad 181132e092 merge 2026-03-10 14:36:35 +06:00
Vlad 6fe10eacfc Merge remote-tracking branch 'origin/main' into spark 2026-03-10 14:26:51 +06:00
Vlad 9e692c9ec3 added enter nicknamw 2026-03-10 14:25:00 +06:00
Vladislav Khorev 785b96ce82 Working on list of players 2026-03-09 23:04:48 +03:00
Vladislav Khorev a8ded217df Fixing ui bugs 2026-03-09 20:52:16 +03:00
Vladislav Khorev 3e8dba36a4 fixing minor bugs, fixing velocity not changed after death, fixing server crash 2026-03-09 19:27:20 +03:00
Vladislav Khorev 84a5e888a0 Added pickup boxes 2026-03-09 18:36:04 +03:00
Vladislav Khorev 86a9f38c3b Some UI changes 2026-03-09 13:50:59 +03:00
Vladislav Khorev 24aa7007bb Added trails to other ships toos 2026-03-08 21:27:45 +03:00
Vladislav Khorev 59b5bea540 Fixing particles 2026-03-08 19:07:02 +03:00
Vladislav Khorev 9da3cc4401 Fixing bug in particle emitter 2026-03-08 00:22:13 +03:00
Vladislav Khorev 4a542fd6c8 Added multi-touch, added on press down 2026-03-07 22:41:25 +03:00
Vladislav Khorev a06cb77a66 Fixing minor stuff, refactoring 2026-03-07 20:51:34 +03:00
Vladislav Khorev 3c2c06ca40 Working on refactoring 2026-03-07 20:03:16 +03:00
Vladislav Khorev 928600acd4 Refactoring 2026-03-07 19:41:15 +03:00
Vladislav Khorev 7ccda081b0 Fixing bugs 2026-03-06 23:15:56 +03:00
Vladislav Khorev 41f370f2ee Minor fixing 2026-03-06 22:34:03 +03:00
Vladislav Khorev 4af20c65e6 Make menu to state machine 2026-03-06 21:52:00 +03:00
Vladislav Khorev ac551122d9 Added force disconnect from server 2026-03-06 20:05:55 +03:00
Vladislav Khorev 8528b4dc90 Clean up server 2026-03-06 19:08:55 +03:00
Vladislav Khorev c35e093cc5 Working on encoding 2026-03-06 17:51:46 +03:00
Vladislav Khorev a8c76dee3c Working on fixing minor bugs 2026-03-05 23:58:35 +03:00
Vladislav Khorev e84a094ad9 Merge branch 'spark' 2026-03-05 19:54:24 +03:00
Vladislav Khorev b0b7391939 Fixed low quality 2026-03-05 19:53:27 +03:00
Vlad 3e2632c5b5 added textures 2026-03-05 20:14:02 +06:00
Vladislav Khorev 70ef730e86 Merge branch 'main' into ShipSpawn 2026-03-05 10:24:17 +03:00
Vladislav Khorev 92b288d978 fixing bugs 2026-03-05 10:15:55 +03:00
Vladislav Khorev cca1d0ece2 Merge branch 'spark' 2026-03-05 09:10:38 +03:00
Vladislav Khorev 8effdd5dfa Merge branch 'sergey' 2026-03-05 09:10:00 +03:00
Vladislav Khorev e78429b600 Working on running the game even in Telegram 2026-03-04 21:41:51 +03:00
anime 05a13a40e7 fixed: Box destroition 2026-03-04 16:37:00 +06:00
vottozi ef7617701e fix server collision radius mismatch 2026-03-04 03:37:58 +06:00
vottozi 2f50dc1522 fix Lead Indicator rendering when target off-screen 2026-03-04 01:42:57 +06:00
vottozi 9eafcd27fb Fix lead indicator prediction & align projectile lifetime (client/server) 2026-03-03 19:42:08 +06:00
Vlad 3879eb1d75 fixed web ship types boxes / local boxes collision and projectiles 2026-03-03 19:17:07 +06:00
anime 78046e5e2d Merge remote-tracking branch 'origin/main' into ShipSpawn 2026-03-02 17:49:09 +06:00
anime 26233f934f fixed: spawning ships 2026-03-02 17:47:46 +06:00
Vlad 167c04b107 install 2026-03-02 14:05:23 +06:00
Vladislav Khorev 5fcb1d1234 server changes 2026-03-01 22:35:17 +03:00
Vladislav Khorev 70a617b688 More changes 2026-03-01 22:34:12 +03:00
Vladislav Khorev bb0f584bf6 Working on UI and web game 2026-03-01 21:22:57 +03:00
Vladislav Khorev 6b4b549b3c Working on UI for web 2026-02-28 23:01:26 +03:00
Vladislav Khorev ffbecbbcde Working on ui 2026-02-28 22:21:08 +03:00
Vladislav Khorev 2728ca9646 Adapting web version 2026-02-28 20:37:47 +03:00
Vladislav Khorev 7e5aa22fee merge 2026-02-28 13:33:33 +03:00
Vlad c20e82634a fix game over 2026-02-28 12:07:40 +06:00
Vladislav Khorev 9f82e7a2e6 Adapt for web 2026-02-27 22:31:07 +03:00
Vlad 7418bbbe27 fix spaceship rotation fix sync boxes 2026-02-27 17:37:00 +06:00
Vladislav Khorev be2aa76f8b Working on server optimization 2026-02-26 22:26:43 +03:00
Vladislav Khorev e8f1786a2a merge 2026-02-26 21:22:38 +03:00
Vladislav Khorev e30f8a4c70 merge 2026-02-26 21:10:27 +03:00
Vladislav Khorev f8642efa23 merge 2026-02-26 21:02:16 +03:00
vottozi 5da5a754fe add configurable HUD crosshair 2026-02-26 01:49:49 +06:00
vottozi fb1b0a1c2e Lead Indicator fix 2026-02-25 22:18:47 +06:00
Vlad 74c2f786a1 added choising spaceship type for multiplayer and some fix in respawn 2026-02-25 19:17:42 +06:00
Vlad 5216965496 added choosing spaceship in singleplay 2026-02-24 20:34:01 +06:00
Vlad ad7294ceea added random spaceship type 2026-02-24 19:51:33 +06:00
Vlad 3893038d9a Merge remote-tracking branch 'origin/main' into spark 2026-02-23 15:30:01 +06:00
Vlad cb2e8318e7 added multi_menu 2026-02-23 15:29:05 +06:00
Vladislav Khorev 5cca2413fe changes 2026-02-23 11:46:57 +03:00
Vladislav Khorev db4254e205 working on web 2026-02-23 11:45:55 +03:00
vottozi fa3a4c66c9 add lead indicator 2026-02-23 14:43:23 +06:00
Vladislav Khorev 84006380db Added loading screen 2026-02-23 09:55:01 +03:00
Vladislav Khorev f6cc30a30c Try out Cursor 2026-02-22 21:20:39 +03:00
Vladislav Khorev d883b58260 Adapt for web 2026-02-22 20:04:18 +03:00
Vladislav Khorev b59a10b7e6 Major refactoring for game menu 2026-02-22 19:50:13 +03:00
Vladislav Khorev 5b57696acf Refactoring major 2026-02-22 19:15:25 +03:00
Vladislav Khorev 1265d87bc5 Updated UI 2026-02-22 18:23:27 +03:00
Vladislav Khorev 46d7a2a25d Merge branch 'spark' 2026-02-22 17:02:40 +03:00
Vlad 0babfff28b added multiplayer menu 2026-02-22 19:21:12 +06:00
Vladislav Khorev ed6e1bacc7 merge 2026-02-22 16:03:11 +03:00
Vladislav Khorev 9c39782729 Fixing bug with collisions 2026-02-22 15:53:04 +03:00
Vladislav Khorev efad2dde3e Restore as it was before 2026-02-22 14:08:12 +03:00
Vladislav Khorev 84d8ee7eee Merge branch 'spark' 2026-02-22 13:30:33 +03:00
Vladislav Khorev 7693237aa5 Added websocket 2026-02-22 13:29:06 +03:00
vottozi 528c94e921 Add enemy target brackets + off-screen arrows 2026-02-19 01:13:08 +06:00
Vlad a8700af1d0 added npc destroy 2026-02-13 15:40:40 +06:00
Vlad 9793c5bf06 fix npc 2026-02-12 18:13:19 +06:00
vottozi b56fafa0e0 Add mesh caching for unchanging text labels 2026-02-12 13:23:16 +06:00
Vladislav Khorev 22ee99418d Working on web version 2026-02-11 21:48:25 +03:00
vottozi 4eda57b4e4 single texture atlas for all font glyphs in TextRenderer 2026-02-12 00:08:52 +06:00
Vladislav Khorev 2ffd8124f2 Change the way fire happens 2026-02-11 20:02:15 +03:00
Vladislav Khorev 210c191d41 Added different hash func 2026-02-10 21:06:21 +03:00
Vladislav Khorev 251a59ddbe added hash 2026-02-10 11:42:23 +03:00
Vlad 5df2216da6 added npc 2026-02-10 12:42:19 +06:00
Vladislav Khorev 2c1c077611 Added time offset sync, added web version multiplayer 2026-02-09 22:56:48 +03:00
Vlad 629c9ba7b1 add local server 2026-02-09 18:42:07 +06:00
Vladislav Khorev a59bcc0c4b Adapting for web 2026-02-08 22:38:24 +03:00
Vladislav Khorev cf1ec1e76f merge 2026-02-08 15:53:55 +03:00
Vladislav Khorev 8a374a4231 Merge with main 2026-02-08 15:31:25 +03:00
Vlad da2b6e5577 some fix/added sync boxes 2026-02-06 19:16:17 +06:00
vottozi aa9590e2f4 Add velocity HUD display (Velocity: 0) in top-left corner 2026-02-06 18:04:33 +06:00
vottozi a1d54b01b0 Add TextView UI component 2026-02-06 15:11:27 +06:00
Vlad 65a2066727 size 2026-02-05 14:00:20 +06:00
Vladislav Khorev c49c4626d0 merge 2026-02-05 10:43:24 +03:00
Vlad ec156bd679 add sync projectiles 2026-02-05 13:29:21 +06:00
Vladislav Khorev 7b1d9363a0 Fixing lag compensation and make more smooth 2026-02-05 09:00:54 +03:00
Vladislav Khorev 82ca994fac merge 2026-02-05 07:33:13 +03:00
Vladislav Khorev 0d2f705d42 merge 2026-02-05 07:30:12 +03:00
vottozi e799b4ec79 conflict resolution 2026-02-05 01:43:45 +06:00
vottozi c8076b6018 adjust label scale: constant far, smooth growth near 2026-02-05 01:34:14 +06:00
Vlad 88f68b20ea some fix 2026-02-02 14:45:36 +06:00
vottozi d249f17d22 everything uselles 2026-02-02 13:50:43 +06:00
vottozi bee3545196 change to permanent visibility of ship labels 2026-02-02 13:48:28 +06:00
vottozi e050d7d0ec Improve ship nickname rendering 2026-02-02 04:44:18 +06:00
vottozi e18484ea62 add player ID labels for ships 2026-02-01 23:34:21 +06:00
Vlad 204b79bf06 add main menu 2026-01-31 19:25:40 +06:00
Vlad 50232c0816 fix shooting 2026-01-31 16:44:00 +06:00
Vlad e8fb14b809 added sync projectiles/boxes 2026-01-27 19:38:18 +06:00
Vladislav Khorev d425167dce Added planet physics and simple base 2026-01-25 20:55:36 +03:00
vottozi f41228acf8 add freetype-based text rendering and box labels 2026-01-22 15:54:21 +06:00
Vlad cacc18dc7e added boxes from server 2026-01-19 22:04:33 +06:00
165 changed files with 22592 additions and 2358 deletions

No files matched your search

+6 -4
View File
@@ -398,8 +398,10 @@ add_library(freetype_external_lib UNKNOWN IMPORTED GLOBAL)
set_target_properties(freetype_external_lib PROPERTIES set_target_properties(freetype_external_lib PROPERTIES
IMPORTED_LOCATION_DEBUG "${_ft_debug_lib}" IMPORTED_LOCATION_DEBUG "${_ft_debug_lib}"
IMPORTED_LOCATION_RELEASE "${_ft_release_lib}" IMPORTED_LOCATION_RELEASE "${_ft_release_lib}"
INTERFACE_INCLUDE_DIRECTORIES )
"$<IF:$<CONFIG:Debug>,${FREETYPE_BASE_DIR}-Debug/include,${FREETYPE_BASE_DIR}-Release/include>" target_include_directories(freetype_external_lib INTERFACE
"$<IF:$<CONFIG:Debug>,${FREETYPE_BASE_DIR}-Debug/include/freetype2,${FREETYPE_BASE_DIR}-Release/include/freetype2>"
"$<IF:$<CONFIG:Debug>,${FREETYPE_BASE_DIR}-Debug/include,${FREETYPE_BASE_DIR}-Release/include>"
) )
# =========================================== # ===========================================
@@ -453,8 +455,8 @@ if(NOT _have_sdl2ttf)
-DSDL2_LIBRARY=${_SDL2_LIB} -DSDL2_LIBRARY=${_SDL2_LIB}
-DSDL2_INCLUDE_DIR=${SDL2_INSTALL_DIR}/include/SDL2 -DSDL2_INCLUDE_DIR=${SDL2_INSTALL_DIR}/include/SDL2
-DFREETYPE_LIBRARY=${_FT_LIB} -DFREETYPE_LIBRARY=${_FT_LIB}
-DFREETYPE_INCLUDE_DIR=${_FT_PREFIX}/include -DFREETYPE_INCLUDE_DIR=${_FT_PREFIX}/include/freetype2
-DFREETYPE_INCLUDE_DIRS=${_FT_PREFIX}/include -DFREETYPE_INCLUDE_DIRS=${_FT_PREFIX}/include/freetype2
-DSDL2TTF_VENDORED=OFF -DSDL2TTF_VENDORED=OFF
-DSDL2TTF_SAMPLES=OFF -DSDL2TTF_SAMPLES=OFF
RESULT_VARIABLE _ttf_cfg_res RESULT_VARIABLE _ttf_cfg_res
+62 -22
View File
@@ -21,23 +21,60 @@ include("${CMAKE_CURRENT_SOURCE_DIR}/../cmake/FetchDependencies.cmake")
set(SOURCES set(SOURCES
../src/main.cpp ../src/main.cpp
../src/Game.cpp ../src/Game.cpp
../src/Game.h
../src/Environment.cpp ../src/Environment.cpp
../src/BoneAnimatedModel.cpp ../src/Environment.h
../src/TextModel.cpp
../src/Projectile.cpp
../src/SparkEmitter.cpp
../src/UiManager.cpp
../src/render/Renderer.cpp ../src/render/Renderer.cpp
../src/render/Renderer.h
../src/render/ShaderManager.cpp ../src/render/ShaderManager.cpp
../src/render/ShaderManager.h
../src/render/TextureManager.cpp ../src/render/TextureManager.cpp
../src/render/FrameBuffer.cpp ../src/render/TextureManager.h
../src/TextModel.cpp
../src/TextModel.h
../src/AudioPlayerAsync.cpp
../src/AudioPlayerAsync.h
../src/BoneAnimatedModel.cpp
../src/BoneAnimatedModel.h
../src/render/OpenGlExtensions.cpp ../src/render/OpenGlExtensions.cpp
../src/render/OpenGlExtensions.h
../src/utils/Utils.cpp ../src/utils/Utils.cpp
../src/utils/TaskManager.cpp ../src/utils/Utils.h
../src/utils/Perlin.cpp ../src/SparkEmitter.cpp
../src/planet/PlanetData.cpp ../src/SparkEmitter.h
../src/planet/PlanetObject.cpp ../src/planet/PlanetObject.cpp
../src/planet/StoneObject.cpp ../src/planet/PlanetObject.h
../src/planet/PlanetData.cpp
../src/planet/PlanetData.h
../src/utils/Perlin.cpp
../src/utils/Perlin.h
../src/utils/TaskManager.cpp
../src/utils/TaskManager.h
../src/planet/StoneObject.cpp
../src/planet/StoneObject.h
../src/render/FrameBuffer.cpp
../src/render/FrameBuffer.h
../src/UiManager.cpp
../src/UiManager.h
../src/Projectile.h
../src/Projectile.cpp
../src/network/NetworkInterface.h
../src/network/LocalClient.h
../src/network/LocalClient.cpp
../src/network/ClientState.h
../src/network/ClientState.cpp
../src/network/WebSocketClientBase.h
../src/network/WebSocketClientBase.cpp
../src/network/WebSocketClientEmscripten.h
../src/network/WebSocketClientEmscripten.cpp
../src/render/TextRenderer.h
../src/render/TextRenderer.cpp
../src/MenuManager.h
../src/MenuManager.cpp
../src/Space.h
../src/Space.cpp
../src/GameConstants.h
../src/GameConstants.cpp
) )
add_executable(space-game001 ${SOURCES}) add_executable(space-game001 ${SOURCES})
@@ -58,30 +95,33 @@ set(ENABLE_COMMONCRYPTO OFF CACHE BOOL "" FORCE)
add_subdirectory("../thirdparty/libzip-1.11.4" libzip-build) add_subdirectory("../thirdparty/libzip-1.11.4" libzip-build)
# Линковка: target_link_libraries(space-game001 PRIVATE zip z websocket.js)
# 'zip' берется из add_subdirectory
# 'z' - это системный zlib Emscripten-а (флаг -sUSE_ZLIB=1 добавим ниже)
target_link_libraries(space-game001 PRIVATE zip z)
# Эмскриптен-флаги # Эмскриптен-флаги
set(EMSCRIPTEN_FLAGS set(EMSCRIPTEN_FLAGS
"-sUSE_SDL=2" "-sUSE_SDL=2"
"-sUSE_SDL_IMAGE=2" "-sUSE_SDL_IMAGE=2"
"-sUSE_LIBPNG=1" "-sUSE_LIBPNG=1"
"-sUSE_ZLIB=1" # Добавили zlib порт "-sUSE_ZLIB=1"
"-pthread" "-sUSE_SDL_TTF=2"
"-sUSE_PTHREADS=1" #"-pthread"
#"-sUSE_PTHREADS=1"
"-fexceptions" "-fexceptions"
"-DNETWORK"
) )
target_compile_options(space-game001 PRIVATE ${EMSCRIPTEN_FLAGS} "-O2") target_compile_options(space-game001 PRIVATE ${EMSCRIPTEN_FLAGS} "-O2")
# Only loading.png and the shaders used before resources.zip is ready are preloaded.
# resources.zip is downloaded asynchronously at runtime and served as a separate file.
set(EMSCRIPTEN_LINK_FLAGS set(EMSCRIPTEN_LINK_FLAGS
${EMSCRIPTEN_FLAGS} ${EMSCRIPTEN_FLAGS}
"-O2" "-O2"
"-sPTHREAD_POOL_SIZE=4" #"-sPTHREAD_POOL_SIZE=4"
"-sALLOW_MEMORY_GROWTH=1" "-sALLOW_MEMORY_GROWTH=1"
"--preload-file resources.zip" "-sFULL_ES3=1"
"--preload-file ${CMAKE_CURRENT_SOURCE_DIR}/../resources/loading.png@resources/loading.png"
"--preload-file ${CMAKE_CURRENT_SOURCE_DIR}/../resources/shaders@resources/shaders"
) )
# Применяем настройки линковки # Применяем настройки линковки
@@ -131,8 +171,8 @@ install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/space-game001plain.html"
DESTINATION . DESTINATION .
) )
# Если вам все еще нужен сам resources.zip отдельно в папке public: # resources.zip is served separately and downloaded asynchronously at runtime
#install(FILES "${RESOURCES_ZIP}" DESTINATION .) install(FILES "${RESOURCES_ZIP}" DESTINATION .)
add_custom_command(TARGET space-game001 POST_BUILD add_custom_command(TARGET space-game001 POST_BUILD
COMMAND ${CMAKE_COMMAND} --install . COMMAND ${CMAKE_COMMAND} --install .
+7 -1
View File
@@ -1,7 +1,13 @@
# how to build # how to build
If emsdk is not installed, you need to clone it from here: https://github.com/emscripten-core/emsdk
Activate the environment: and install:
```
C:\Work\Projects\emsdk\emsdk.bat install latest
```
Then activate the environment:
``` ```
C:\Work\Projects\emsdk\emsdk.bat activate latest C:\Work\Projects\emsdk\emsdk.bat activate latest
C:\Work\Projects\emsdk\emsdk_env.bat C:\Work\Projects\emsdk\emsdk_env.bat
+2
View File
@@ -0,0 +1,2 @@
<!doctypehtml><html lang=en-us><head><meta charset=utf-8><meta content="text/html; charset=utf-8"http-equiv=Content-Type><title>Emscripten-Generated Code</title><style>body{font-family:arial;margin:0;padding:none}.emscripten{padding-right:0;margin-left:auto;margin-right:auto;display:block}div.emscripten{text-align:center}div.emscripten_border{border:1px solid #000}canvas.emscripten{border:0 none;background-color:#000}#emscripten_logo{display:inline-block;margin:0;padding:6px;width:265px}.spinner{height:30px;width:30px;margin:0;margin-top:20px;margin-left:20px;display:inline-block;vertical-align:top;-webkit-animation:rotation .8s linear infinite;-moz-animation:rotation .8s linear infinite;-o-animation:rotation .8s linear infinite;animation:rotation .8s linear infinite;border-left:5px solid #ebebeb;border-right:5px solid #ebebeb;border-bottom:5px solid #ebebeb;border-top:5px solid #787878;border-radius:100%;background-color:#bdd72e}@-webkit-keyframes rotation{from{-webkit-transform:rotate(0)}to{-webkit-transform:rotate(360deg)}}@-moz-keyframes rotation{from{-moz-transform:rotate(0)}to{-moz-transform:rotate(360deg)}}@-o-keyframes rotation{from{-o-transform:rotate(0)}to{-o-transform:rotate(360deg)}}@keyframes rotation{from{transform:rotate(0)}to{transform:rotate(360deg)}}#status{display:inline-block;vertical-align:top;margin-top:30px;margin-left:20px;font-weight:700;color:#787878}#progress{height:20px;width:300px}#controls{display:inline-block;float:right;vertical-align:top;margin-top:30px;margin-right:20px}#output{width:100%;height:200px;margin:0 auto;margin-top:10px;border-left:0;border-right:0px;padding-left:0;padding-right:0;display:block;background-color:#000;color:#fff;font-family:'Lucida Console',Monaco,monospace;outline:0}</style></head><body><script src="https://cdn.jsdelivr.net/npm/eruda"></script>
<script>eruda.init();</script><a href=http://emscripten.org><img id=emscripten_logo src=""></a><div class=spinner id=spinner></div><div class=emscripten id=status>Downloading...</div><span id=controls><span><input type=checkbox id=resize>Resize canvas</span> <span><input type=checkbox id=pointerLock checked>Lock/hide mouse pointer    </span><span><input type=button onclick='Module.requestFullscreen(document.getElementById("pointerLock").checked,document.getElementById("resize").checked)'value=Fullscreen></span></span><div class=emscripten><progress hidden id=progress max=100 value=0></progress></div><div class=emscripten_border><canvas class=emscripten id=canvas oncontextmenu=event.preventDefault() tabindex=-1></canvas></div><textarea id=output rows=8></textarea><script>var statusElement=document.getElementById("status"),progressElement=document.getElementById("progress"),spinnerElement=document.getElementById("spinner"),canvasElement=document.getElementById("canvas"),outputElement=document.getElementById("output");outputElement&&(outputElement.value=""),canvasElement.addEventListener("webglcontextlost",(e=>{alert("WebGL context lost. You will need to reload the page."),e.preventDefault()}),!1);var Module={print(...e){if(console.log(...e),outputElement){var t=e.join(" ");outputElement.value+=t+"\n",outputElement.scrollTop=outputElement.scrollHeight}},canvas:canvasElement,setStatus(e){if(Module.setStatus.last||(Module.setStatus.last={time:Date.now(),text:""}),e!==Module.setStatus.last.text){var t=e.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/),n=Date.now();t&&n-Module.setStatus.last.time<30||(Module.setStatus.last.time=n,Module.setStatus.last.text=e,t?(e=t[1],progressElement.value=100*parseInt(t[2]),progressElement.max=100*parseInt(t[4]),progressElement.hidden=!1,spinnerElement.hidden=!1):(progressElement.value=null,progressElement.max=null,progressElement.hidden=!0,e||(spinnerElement.style.display="none")),statusElement.innerHTML=e)}},totalDependencies:0,monitorRunDependencies(e){this.totalDependencies=Math.max(this.totalDependencies,e),Module.setStatus(e?"Preparing... ("+(this.totalDependencies-e)+"/"+this.totalDependencies+")":"All downloads complete.")}};Module.setStatus("Downloading..."),window.onerror=e=>{Module.setStatus("Exception thrown, see JavaScript console"),spinnerElement.style.display="none",Module.setStatus=e=>{e&&console.error("[post-exception status] "+e)}}</script><script async src="space-game001.js" crossorigin="anonymous"></script></body></html>
+209 -93
View File
@@ -1,100 +1,216 @@
<!doctypehtml> <!DOCTYPE html>
<html lang=en-us> <html lang="en-us">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
<title>Space Game</title>
<style>
body, html {
margin: 0; padding: 0; width: 100%; height: 100%;
overflow: hidden; background-color: #000;
position: fixed;
}
#canvas {
display: block;
position: absolute;
top: 0; left: 0;
width: 100vw; height: 100vh;
border: none;
}
<head> #fs-button {
<meta charset=utf-8> position: absolute;
<meta content="text/html; charset=utf-8" http-equiv=Content-Type> top: 10px; right: 10px;
<title>Space Game</title> padding: 10px;
<style> z-index: 10;
body { background: rgba(255,255,255,0.3);
font-family: arial; color: white; border: 1px solid white;
margin: 0; cursor: pointer;
overflow: hidden; font-family: sans-serif;
padding: 0; border-radius: 5px;
min-height: 100vh; }
background-color: #000; #status { color: white; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }
/* Nick modal */
#nickOverlay {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
background: rgba(0,0,0,0.85);
z-index: 9999;
}
#nickBox {
background: #111;
border: 1px solid #444;
padding: 24px;
width: 320px;
box-shadow: 0 8px 24px rgba(0,0,0,0.6);
text-align: center;
}
#nickBox h2 { margin: 0 0 12px 0; font-size: 18px; color: #eee; }
#nickBox input[type="text"] {
width: 100%;
padding: 10px;
font-size: 16px;
box-sizing: border-box;
margin-bottom: 12px;
border: 1px solid #333;
background: #000;
color: #fff;
}
#nickBox button {
padding: 10px 16px;
font-size: 16px;
background: #2a9fd6;
border: none;
color: #fff;
cursor: pointer;
}
#nickSkip { margin-left: 8px; background: #666; }
</style>
</head>
<body>
<button id="fs-button">Fullscreen</button>
<div id="status">Downloading...</div>
<canvas id="canvas" oncontextmenu="event.preventDefault()" tabindex="-1"></canvas>
<!--
<script>
var statusElement = document.getElementById("status");
var canvas = document.getElementById("canvas");
var Module = {
canvas: canvas,
setStatus: function(text) {
statusElement.innerHTML = text;
statusElement.style.display = text ? 'block' : 'none';
}
};
document.getElementById('fs-button').addEventListener('click', function() {
if (!document.fullscreenElement) {
document.documentElement.requestFullscreen().catch(e => {
console.error(`Error attempting to enable full-screen mode: ${e.message}`);
});
} else {
document.exitFullscreen();
}
});
window.addEventListener("orientationchange", function() {
setTimeout(() => {
window.dispatchEvent(new Event('resize'));
}, 200);
});
</script>
<script async src="space-game001.js"></script>-->
<div id="nickOverlay" style="display:none;">
<div id="nickBox">
<h2>Enter your nickname</h2>
<input id="nickInput" type="text" maxlength="32" placeholder="Player" />
<div>
<button id="nickSubmit">Start</button>
</div>
</div>
</div>
<script>
// Utility: подготовить глобальный Module до загрузки Emscripten-скрипта
function prepareModuleEnvironment() {
window.Module = window.Module || {};
var canvasEl = document.getElementById('canvas');
// Устанавливаем canvas для Emscripten, чтобы createContext не падал
window.Module.canvas = canvasEl;
// Подготовим заглушку setStatus, если ещё нет
window.Module.setStatus = window.Module.setStatus || function (text) {
var statusElement = document.getElementById("status");
statusElement.innerHTML = text;
statusElement.style.display = text ? 'block' : 'none';
};
}
// Show overlay only if no nickname saved.
function loadGameScript() {
var s = document.createElement('script');
s.src = 'space-game001.js';
s.async = true;
document.body.appendChild(s);
}
function showNickOverlay() {
var overlay = document.getElementById('nickOverlay');
overlay.style.display = 'flex';
var input = document.getElementById('nickInput');
input.focus();
}
function hideNickOverlay() {
var overlay = document.getElementById('nickOverlay');
overlay.style.display = 'none';
}
function saveNickAndStart(nick) {
try {
if (!nick || nick.trim() === '') nick = 'Player';
localStorage.setItem('spacegame_nick', nick);
} catch (e) {
console.warn('localStorage not available', e);
}
hideNickOverlay();
// перед загрузкой скрипта гарантируем, что Module.canvas задан
prepareModuleEnvironment();
loadGameScript();
}
document.addEventListener('DOMContentLoaded', function() {
// Готовим Module сразу — даже если откроется модалка, поле canvas будет доступно для скрипта (если он загружается позже)
prepareModuleEnvironment();
var stored = null;
try {
stored = localStorage.getItem('spacegame_nick');
} catch (e) {
console.warn('localStorage not available', e);
} }
.emscripten { if (stored && stored.trim() !== '') {
padding-right: 0; // Nick is present — start immediately
margin-left: auto; loadGameScript();
margin-right: auto; } else {
display: block // Show modal to request nickname before loading WASM
showNickOverlay();
var submit = document.getElementById('nickSubmit');
var skip = document.getElementById('nickSkip');
var input = document.getElementById('nickInput');
submit.addEventListener('click', function() {
saveNickAndStart(input.value);
});
skip.addEventListener('click', function() {
saveNickAndStart('Player');
});
input.addEventListener('keydown', function(e) {
if (e.key === 'Enter') {
saveNickAndStart(input.value);
}
});
} }
});
div.emscripten { window.addEventListener("orientationchange", function() {
text-align: center // Chrome на Android обновляет innerWidth/Height не мгновенно.
} // Ждем завершения анимации поворота.
setTimeout(() => {
// В Emscripten это вызовет ваш onWindowResized в C++
window.dispatchEvent(new Event('resize'));
}, 200);
});
div.emscripten_border { </script>
border: 1px solid #000
}
canvas.emscripten { </body>
border: 0 none; </html>
background-color: #000;
width: 90%;
height: 100vh;
}
@-webkit-keyframes rotation {
from {
-webkit-transform: rotate(0)
}
to {
-webkit-transform: rotate(360deg)
}
}
@-moz-keyframes rotation {
from {
-moz-transform: rotate(0)
}
to {
-moz-transform: rotate(360deg)
}
}
@-o-keyframes rotation {
from {
-o-transform: rotate(0)
}
to {
-o-transform: rotate(360deg)
}
}
@keyframes rotation {
from {
transform: rotate(0)
}
to {
transform: rotate(360deg)
}
}
#status {
display: none;
}
#progress {
height: 20px;
width: 300px
}
</style>
</head>
<body>
<div class=emscripten id=status></div>
<div class=emscripten><progress hidden id=progress max=100 value=0></progress></div>
<div class=emscripten_border><canvas class=emscripten id=canvas oncontextmenu=event.preventDefault()
tabindex=-1></canvas></div>
<script>var statusElement = document.getElementById("status"), progressElement = document.getElementById("progress"), spinnerElement = document.getElementById("spinner"), Module = { print: function () { var e = document.getElementById("output"); return e && (e.value = ""), function (t) { arguments.length > 1 && (t = Array.prototype.slice.call(arguments).join(" ")), console.log(t), e && (e.value += t + "\n", e.scrollTop = e.scrollHeight) } }(), canvas: (() => { var e = document.getElementById("canvas"); return e.addEventListener("webglcontextlost", (e => { alert("WebGL context lost. You will need to reload the page."), e.preventDefault() }), !1), e })(), setStatus: e => { if (Module.setStatus.last || (Module.setStatus.last = { time: Date.now(), text: "" }), e !== Module.setStatus.last.text) { var t = e.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/), n = Date.now(); t && n - Module.setStatus.last.time < 30 || (Module.setStatus.last.time = n, Module.setStatus.last.text = e, t ? (e = t[1], progressElement.value = 100 * parseInt(t[2]), progressElement.max = 100 * parseInt(t[4]), progressElement.hidden = !1, spinnerElement.hidden = !1) : (progressElement.value = null, progressElement.max = null, progressElement.hidden = !0, e || (spinnerElement.style.display = "none")), statusElement.innerHTML = e) } }, totalDependencies: 0, monitorRunDependencies: e => { this.totalDependencies = Math.max(this.totalDependencies, e), Module.setStatus(e ? "Preparing... (" + (this.totalDependencies - e) + "/" + this.totalDependencies + ")" : "All downloads complete.") } }; Module.setStatus("Downloading..."), window.onerror = e => { Module.setStatus("Exception thrown, see JavaScript console"), spinnerElement.style.display = "none", Module.setStatus = e => { e && console.error("[post-exception status] " + e) } }</script>
<script async src=space-game001.js></script>
</body>
</html>
+13 -1
View File
@@ -57,6 +57,18 @@ add_executable(space-game001
../src/network/ClientState.cpp ../src/network/ClientState.cpp
../src/network/WebSocketClient.h ../src/network/WebSocketClient.h
../src/network/WebSocketClient.cpp ../src/network/WebSocketClient.cpp
../src/network/WebSocketClientBase.h
../src/network/WebSocketClientBase.cpp
../src/network/WebSocketClientEmscripten.h
../src/network/WebSocketClientEmscripten.cpp
../src/render/TextRenderer.h
../src/render/TextRenderer.cpp
../src/MenuManager.h
../src/MenuManager.cpp
../src/Space.h
../src/Space.cpp
../src/GameConstants.h
../src/GameConstants.cpp
) )
# Установка проекта по умолчанию для Visual Studio # Установка проекта по умолчанию для Visual Studio
@@ -78,7 +90,7 @@ target_compile_definitions(space-game001 PRIVATE
WIN32_LEAN_AND_MEAN WIN32_LEAN_AND_MEAN
PNG_ENABLED PNG_ENABLED
SDL_MAIN_HANDLED SDL_MAIN_HANDLED
# NETWORK NETWORK
# SIMPLIFIED # SIMPLIFIED
) )
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large. Load diff
+22
View File
@@ -0,0 +1,22 @@
{
"root": {
"type": "FrameLayout",
"x": 0,
"y": 0,
"width": "match_parent",
"height": "match_parent",
"children": [
{
"type": "StaticImage",
"name": "connecting",
"x" : 0,
"y" : 0,
"width": 488,
"height": 154,
"horizontal_gravity": "center",
"vertical_gravity": "center",
"texture": "resources/connecting.png"
}
]
}
}
+52
View File
@@ -0,0 +1,52 @@
{
"root": {
"type": "FrameLayout",
"x": 0,
"y": 0,
"width": "match_parent",
"height": "match_parent",
"children": [
{
"type": "StaticImage",
"name": "connectionFailed",
"x" : 0,
"y" : 0,
"width": 488,
"height": 308,
"horizontal_gravity": "center",
"vertical_gravity": "center",
"texture": "resources/connection_failed.png"
},
{
"type": "Button",
"name": "connectionFailedReconnectButton",
"width": 382,
"height": 56,
"x" : 0,
"y" : -20,
"horizontal_gravity": "center",
"vertical_gravity": "center",
"textures": {
"normal": "resources/game_over/Filledbuttons.png",
"hover": "resources/game_over/Variant5.png",
"pressed": "resources/game_over/Variant6.png"
}
},
{
"type": "Button",
"name": "connectionFailedGoBack",
"width": 382,
"height": 56,
"x" : 0,
"y" : -86,
"horizontal_gravity": "center",
"vertical_gravity": "center",
"textures": {
"normal": "resources/game_over/Secondarybutton.png",
"hover": "resources/game_over/Secondarybutton.png",
"pressed": "resources/game_over/Secondarybutton.png"
}
}
]
}
}
+52
View File
@@ -0,0 +1,52 @@
{
"root": {
"type": "FrameLayout",
"x": 0,
"y": 0,
"width": "match_parent",
"height": "match_parent",
"children": [
{
"type": "StaticImage",
"name": "connectionLost",
"x" : 0,
"y" : 0,
"width": 488,
"height": 308,
"horizontal_gravity": "center",
"vertical_gravity": "center",
"texture": "resources/connection_lost.png"
},
{
"type": "Button",
"name": "reconnectButton",
"width": 382,
"height": 56,
"x" : 0,
"y" : -20,
"horizontal_gravity": "center",
"vertical_gravity": "center",
"textures": {
"normal": "resources/game_over/Filledbuttons.png",
"hover": "resources/game_over/Variant5.png",
"pressed": "resources/game_over/Variant6.png"
}
},
{
"type": "Button",
"name": "exitServerButton",
"width": 382,
"height": 56,
"x" : 0,
"y" : -86,
"horizontal_gravity": "center",
"vertical_gravity": "center",
"textures": {
"normal": "resources/game_over/Secondarybutton.png",
"hover": "resources/game_over/Secondarybutton.png",
"pressed": "resources/game_over/Secondarybutton.png"
}
}
]
}
}
+21
View File
@@ -0,0 +1,21 @@
{
"enabled": true,
"referenceResolution": [1280, 720],
"color": [1.0, 1.0, 1.0],
"cl_crosshairalpha": 1.0,
"cl_crosshairthickness": 2.0,
"centerGapPx": 10.0,
"top": {
"lengthPx": 14.0,
"angleDeg": 90.0
},
"arms": [
{ "lengthPx": 20.0, "angleDeg": 210.0 },
{ "lengthPx": 20.0, "angleDeg": 330.0 }
]
}
+1 -1
View File
@@ -5,7 +5,7 @@
"texture": "resources/spark_white.png", "texture": "resources/spark_white.png",
"speedRange": [10.0, 30.0], "speedRange": [10.0, 30.0],
"zSpeedRange": [-1.0, 1.0], "zSpeedRange": [-1.0, 1.0],
"scaleRange": [0.5, 1.0], "scaleRange": [5.0, 10.0],
"lifeTimeRange": [200.0, 800.0], "lifeTimeRange": [200.0, 800.0],
"emissionRate": 50.0, "emissionRate": 50.0,
"maxParticles": 5, "maxParticles": 5,
+83 -53
View File
@@ -1,55 +1,85 @@
{ {
"root": { "root": {
"type": "LinearLayout", "type": "LinearLayout",
"orientation": "vertical", "orientation": "vertical",
"align": "center", "vertical_align": "center",
"x": 0, "horizontal_align": "center",
"y": 0, "spacing": 10,
"width": 1920, "x": 0,
"height": 1080, "y": 0,
"background": { "width": "match_parent",
"color": [0, 0, 0, 0.7] "height": "match_parent",
}, "children": [
"children": [ {
{ "type": "Button",
"type": "Button", "name": "gameOverText",
"name": "gameOverText", "width": 327,
"x": 350, "height": 26,
"y": 400, "textures": {
"width": 600, "normal": "resources/game_over/MissionFailed.png",
"height": 150, "hover": "resources/game_over/MissionFailed.png",
"textures": { "pressed": "resources/game_over/MissionFailed.png"
"normal": "resources/gameover.png", }
"hover": "resources/gameover.png", },
"pressed": "resources/gameover.png" {
} "type": "Button",
}, "name": "underlineBtn",
{ "width": 168,
"type": "Button", "height": 44,
"name": "restartButton", "textures": {
"x": 350, "normal": "resources/game_over/Container.png",
"y": 300, "hover": "resources/game_over/Container.png",
"width": 300, "pressed": "resources/game_over/Container.png"
"height": 80, }
"textures": { },
"normal": "resources/shoot_normal.png", {
"hover": "resources/shoot_normal.png", "type": "Button",
"pressed": "resources/shoot_normal.png" "name": "finalscore",
} "width": 87,
}, "height": 9,
{ "textures": {
"type": "Button", "normal": "resources/game_over/FinalScore.png",
"name": "gameOverExitButton", "hover": "resources/game_over/FinalScore.png",
"x": 650, "pressed": "resources/game_over/FinalScore.png"
"y": 300, }
"width": 300, },
"height": 80, {
"textures": { "type": "TextView",
"normal": "resources/sand2.png", "name": "scoreText",
"hover": "resources/sand2.png", "width": 600,
"pressed": "resources/sand2.png" "height": 80,
} "text": "0",
} "fontSize": 36,
] "color": [
} 0,
217,
255,
1
],
"align": "center"
},
{
"type": "Button",
"name": "restartButton",
"width": 382,
"height": 56,
"textures": {
"normal": "resources/game_over/Filledbuttons.png",
"hover": "resources/game_over/Variant5.png",
"pressed": "resources/game_over/Variant6.png"
}
},
{
"type": "Button",
"name": "gameOverExitButton",
"width": 382,
"height": 56,
"textures": {
"normal": "resources/game_over/Secondarybutton.png",
"hover": "resources/game_over/Secondarybutton.png",
"pressed": "resources/game_over/Secondarybutton.png"
}
}
]
}
} }
+93
View File
@@ -0,0 +1,93 @@
{
"root": {
"type": "LinearLayout",
"orientation": "vertical",
"align": "center",
"x": 0,
"y": 0,
"width": 1920,
"height": 1080,
"background": {
"color": [0, 0, 0, 0.7]
},
"children": [
{
"type": "Button",
"name": "gameOverText",
"x": 476.5,
"y": 500,
"width": 327,
"height": 26,
"textures": {
"normal": "resources/game_over/MissionFailed.png",
"hover": "resources/game_over/MissionFailed.png",
"pressed": "resources/game_over/MissionFailed.png"
}
},
{
"type": "Button",
"name": "underlineBtn",
"x": 556,
"y": 465,
"width": 168,
"height": 44,
"textures": {
"normal": "resources/game_over/Container.png",
"hover": "resources/game_over/Container.png",
"pressed": "resources/game_over/Container.png"
}
},
{
"type": "Button",
"name": "finalscore",
"x": 596.5,
"y": 436,
"width": 87,
"height": 9,
"textures": {
"normal": "resources/game_over/FinalScore.png",
"hover": "resources/game_over/FinalScore.png",
"pressed": "resources/game_over/FinalScore.png"
}
},
{
"type": "TextView",
"name": "scoreText",
"x": 350,
"y": 356,
"width": 600,
"height": 80,
"text": "0",
"fontSize": 36,
"color": [0, 217, 255, 1],
"align": "center"
},
{
"type": "Button",
"name": "restartButton",
"x": 449,
"y": 308,
"width": 382,
"height": 56,
"textures": {
"normal": "resources/game_over/Filledbuttons.png",
"hover": "resources/game_over/Filledbuttons.png",
"pressed": "resources/game_over/Filledbuttons.png"
}
},
{
"type": "Button",
"name": "gameOverExitButton",
"x": 449,
"y": 240,
"width": 382,
"height": 56,
"textures": {
"normal": "resources/game_over/Secondarybutton.png",
"hover": "resources/game_over/Secondarybutton.png",
"pressed": "resources/game_over/Secondarybutton.png"
}
}
]
}
}
+65
View File
@@ -0,0 +1,65 @@
{
"root": {
"type": "LinearLayout",
"orientation": "vertical",
"vertical_align": "center",
"horizontal_align": "center",
"spacing": 10,
"x": 0,
"y": 0,
"width": "match_parent",
"height": "match_parent",
"children": [
{
"type": "StaticImage",
"name": "titleBtn",
"width": 434,
"height": 35,
"texture": "resources/main_menu/title.png"
},
{
"type": "StaticImage",
"name": "underlineBtn",
"width": 168,
"height": 44,
"texture": "resources/main_menu/line.png"
},
{
"type": "StaticImage",
"name": "subtitleBtn",
"width": 144,
"height": 11,
"texture": "resources/main_menu/subtitle.png"
},
{
"type": "Button",
"name": "singleButton",
"width": 382,
"height": 56,
"textures": {
"normal": "resources/main_menu/single.png",
"hover": "resources/main_menu/Variant5.png",
"pressed": "resources/main_menu/Variant6.png"
}
},
{
"type": "Button",
"name": "multiplayerButton",
"width": 382,
"height": 56,
"textures": {
"normal": "resources/main_menu/multi.png",
"hover": "resources/main_menu/Variant7.png",
"pressed": "resources/main_menu/Variant8.png"
}
},
{
"type": "StaticImage",
"name": "versionLabel",
"width": 81,
"height": 9,
"texture": "resources/main_menu/version.png"
}
]
}
}
+158
View File
@@ -0,0 +1,158 @@
{
"root": {
"type": "LinearLayout",
"x": 0,
"y": 0,
"width": 1280,
"height": 720,
"children": [
{
"type": "Button",
"name": "langButton",
"x": 1100,
"y": 580,
"width": 142,
"height": 96,
"textures": {
"normal": "resources/main_menu/lang.png",
"hover": "resources/main_menu/lang.png",
"pressed": "resources/main_menu/lang.png"
}
},
{
"type": "Button",
"name": "titleBtn",
"x": 512,
"y": 500,
"width": 254,
"height": 35,
"textures": {
"normal": "resources/multiplayer_menu/title.png",
"hover": "resources/multiplayer_menu/title.png",
"pressed": "resources/multiplayer_menu/title.png"
}
},
{
"type": "Button",
"name": "subtitle",
"x": 596.5,
"y": 470,
"width": 87,
"height": 11,
"textures": {
"normal": "resources/multiplayer_menu/JoinServer.png",
"hover": "resources/multiplayer_menu/JoinServer.png",
"pressed": "resources/multiplayer_menu/JoinServer.png"
}
},
{
"type": "Button",
"name": "subtitleBtn",
"x": 450,
"y": 445,
"width": 94,
"height": 9,
"textures": {
"normal": "resources/multiplayer_menu/ServerName.png",
"hover": "resources/multiplayer_menu/ServerName.png",
"pressed": "resources/multiplayer_menu/ServerName.png"
}
},
{
"type": "TextField",
"name": "serverInputField",
"x": 449,
"y": 390,
"width": 382,
"height": 56,
"placeholder": "Enter server name or IP",
"fontPath": "resources/fonts/DroidSans.ttf",
"fontSize": 16,
"maxLength": 256,
"color": [122, 156, 198, 1],
"placeholderColor": [122, 156, 198, 1],
"backgroundColor": [15, 29, 51, 1],
"borderColor": [15, 29, 51, 1]
},
{
"type": "Button",
"name": "connectButton",
"x": 449,
"y": 350,
"width": 382,
"height": 56,
"textures": {
"normal": "resources/multiplayer_menu/Filledbuttons.png",
"hover": "resources/multiplayer_menu/Filledbuttons.png",
"pressed": "resources/multiplayer_menu/Filledbuttons.png"
}
},
{
"type": "Button",
"name": "backButton",
"x": 449,
"y": 280,
"width": 382,
"height": 56,
"textures": {
"normal": "resources/multiplayer_menu/Backbutton.png",
"hover": "resources/multiplayer_menu/Backbutton.png",
"pressed": "resources/multiplayer_menu/Backbutton.png"
}
},
{
"type": "Button",
"name": "AvailableServers",
"x": 450,
"y": 240,
"width": 139,
"height": 9,
"textures": {
"normal": "resources/multiplayer_menu/AvailableServers.png",
"hover": "resources/multiplayer_menu/AvailableServers.png",
"pressed": "resources/multiplayer_menu/AvailableServers.png"
}
},
{
"type": "Button",
"name": "SerButton",
"x": 436.5,
"y": 170,
"width": 407,
"height": 62,
"textures": {
"normal": "resources/multiplayer_menu/Button.png",
"hover": "resources/multiplayer_menu/Button.png",
"pressed": "resources/multiplayer_menu/Button.png"
}
},
{
"type": "Button",
"name": "SerButton2",
"x": 436.5,
"y": 88,
"width": 407,
"height": 62,
"textures": {
"normal": "resources/multiplayer_menu/Button2.png",
"hover": "resources/multiplayer_menu/Button2.png",
"pressed": "resources/multiplayer_menu/Button2.png"
}
},
{
"type": "Button",
"name": "SerButton3",
"x": 436.5,
"y": 6,
"width": 407,
"height": 62,
"textures": {
"normal": "resources/multiplayer_menu/Button3.png",
"hover": "resources/multiplayer_menu/Button3.png",
"pressed": "resources/multiplayer_menu/Button3.png"
}
}
]
}
}
+66
View File
@@ -0,0 +1,66 @@
{
"root": {
"type": "LinearLayout",
"orientation": "vertical",
"vertical_align": "center",
"horizontal_align": "center",
"spacing": 10,
"x": 0,
"y": 0,
"width": "match_parent",
"height": "match_parent",
"children": [
{
"type": "StaticImage",
"name": "titleBtn",
"width": 266,
"height": 66,
"texture": "resources/select_your_ship.png"
},
{
"type": "LinearLayout",
"orientation": "horizontal",
"vertical_align": "center",
"horizontal_align": "center",
"spacing": 10,
"width": "match_parent",
"height": 260,
"children": [
{
"type": "Button",
"name": "spaceshipButton",
"width": 256,
"height": 256,
"textures": {
"normal": "resources/multiplayer_menu/ship_fighter.png",
"hover": "resources/multiplayer_menu/ship_fighter_pressed.png",
"pressed": "resources/multiplayer_menu/ship_fighter_pressed.png"
}
},
{
"type": "Button",
"name": "cargoshipButton",
"width": 256,
"height": 256,
"textures": {
"normal": "resources/multiplayer_menu/ship_cargo.png",
"hover": "resources/multiplayer_menu/ship_cargo_pressed.png",
"pressed": "resources/multiplayer_menu/ship_cargo_pressed.png"
}
}
]
},
{
"type": "Button",
"name": "backButton",
"width": 382,
"height": 56,
"textures": {
"normal": "resources/multiplayer_menu/Backbutton.png",
"hover": "resources/multiplayer_menu/Backbutton.png",
"pressed": "resources/multiplayer_menu/Backbutton.png"
}
}
]
}
}
+4 -12
View File
@@ -1,22 +1,14 @@
{ {
"emissionRate": 100.0, "emissionRate": 1.2,
"maxParticles": 200, "maxParticles": 400,
"particleSize": 0.3, "particleSize": 0.3,
"biasX": 0.3, "biasX": 0.3,
"emissionPoints": [ "emissionPoints": [
{
"position": [-1.3, 0, 0.0]
},
{
"position": [1.3, 0.0, 0.0]
}
], ],
"speedRange": [0.5, 2.0], "speedRange": [0.5, 2.0],
"zSpeedRange": [1.0, 3.0], "zSpeedRange": [1.0, 3.0],
"scaleRange": [0.8, 1.2], "scaleRange": [0.8, 1.2],
"lifeTimeRange": [600.0, 1400.0], "lifeTimeRange": [300.0, 500.0],
"texture": "resources/spark.png", "texture": "resources/spark.png",
"shaderProgramName": "default", "shaderProgramName": "spark"
"vertexShader": "resources/shaders/spark.vertex",
"fragmentShader": "resources/shaders/spark.fragment"
} }
+20
View File
@@ -0,0 +1,20 @@
{
"emissionRate": 1.2,
"maxParticles": 400,
"particleSize": 0.3,
"biasX": 0.3,
"emissionPoints": [
{
"position": [0.0, 2.8, -3.5]
},
{
"position": [0.0, 1.5, -3.5]
}
],
"speedRange": [0.5, 2.0],
"zSpeedRange": [1.0, 3.0],
"scaleRange": [0.8, 1.2],
"lifeTimeRange": [600.0, 1400.0],
"texture": "resources/spark.png",
"shaderProgramName": "spark"
}
@@ -2,14 +2,14 @@
"emissionPoints": [ "emissionPoints": [
{ "position": [0.0, 0.0, 0.0] } { "position": [0.0, 0.0, 0.0] }
], ],
"texture": "resources/spark_white.png", "texture": "resources/spark2.png",
"speedRange": [10.0, 30.0], "speedRange": [5.0, 10.0],
"zSpeedRange": [-1.0, 1.0], "zSpeedRange": [-1.0, 1.0],
"scaleRange": [0.5, 1.0], "scaleRange": [0.5, 2.0],
"lifeTimeRange": [200.0, 800.0], "lifeTimeRange": [200.0, 800.0],
"emissionRate": 50.0, "emissionRate": 30.0,
"maxParticles": 10, "maxParticles": 150,
"particleSize": 0.09, "particleSize": 1.0,
"biasX": 0.1, "biasX": 0.1,
"shaderProgramName": "default" "shaderProgramName": "default"
} }
+123 -163
View File
@@ -1,169 +1,129 @@
{ {
"root": { "root": {
"type": "FrameLayout", "type": "FrameLayout",
"x": 0, "x": 0,
"y": 0, "y": 0,
"width": 1280, "width": "match_parent",
"height": 720, "height": "match_parent",
"children": [ "children": [
{
"type": "FrameLayout",
"name": "leftPanel",
"x": 100,
"y": 100,
"width": 320,
"height": 400,
"children": [
{ {
"type": "LinearLayout", "type": "TextView",
"name": "mainButtons", "name": "gameScoreText",
"orientation": "vertical", "x": 0,
"spacing": 10, "y": 30,
"x": 0, "width": 200,
"y": 0, "height": 60,
"width": 300, "horizontal_gravity": "left",
"height": 300, "vertical_gravity": "top",
"children": [ "text": "Score: 0",
{ "fontSize": 36,
"type": "Button", "color": [
"name": "playButton", 0,
"x": -1000, 217,
"y": 500, 255,
"width": 200, 1
"height": 50, ],
"animations": { "centered": false
"buttonsExit": { },
"repeat": false, {
"steps": [ "type": "Button",
{ "name": "showPlayersButton",
"type": "move", "x": 0,
"to": [ "y": 100,
-400, "width": 150,
0 "height": 150,
], "horizontal_gravity": "left",
"duration": 1.0, "vertical_gravity": "top",
"easing": "easein" "textures": {
} "normal": "resources/button_players.png",
] "hover": "resources/button_players.png",
} "pressed": "resources/button_players.png",
}, "disabled": "resources/button_players.png"
"textures": { }
"normal": "./resources/sand2.png", },
"hover": "./resources/sand2.png", {
"pressed": "./resources/sand2.png" "type": "Button",
} "name": "shootButton",
}, "x": 0,
{ "y": 0,
"type": "Button", "width": 150,
"name": "settingsButton", "height": 150,
"x": -1000, "horizontal_gravity": "right",
"y": 400, "vertical_gravity": "bottom",
"width": 200, "textures": {
"height": 50, "normal": "resources/fire.png",
"animations": { "hover": "resources/fire.png",
"buttonsExit": { "pressed": "resources/fire2.png",
"repeat": false, "disabled": "resources/fire_disabled.png"
"steps": [ }
{ },
"type": "wait", {
"duration": 0.5 "type": "Button",
}, "name": "shootButton2",
{ "x": 0,
"type": "move", "y": 0,
"to": [ "width": 150,
-400, "height": 150,
0 "horizontal_gravity": "left",
], "vertical_gravity": "bottom",
"duration": 1.0, "textures": {
"easing": "easein" "normal": "resources/fire.png",
} "hover": "resources/fire.png",
] "pressed": "resources/fire2.png",
} "disabled": "resources/fire_disabled.png"
}, }
"textures": { },
"normal": "./resources/sand2.png", {
"hover": "./resources/sand2.png", "type": "Button",
"pressed": "./resources/sand2.png" "name": "minusButton",
} "x": -20,
}, "y": 110,
{ "width": 150,
"type": "Button", "height": 150,
"name": "exitButton", "border" : 20,
"x": -1000, "horizontal_gravity": "right",
"y": 300, "vertical_gravity": "bottom",
"width": 200, "textures": {
"height": 50, "normal": "resources/button_minus.png",
"animations": { "hover": "resources/button_minus.png",
"buttonsExit": { "pressed": "resources/button_minus_pressed.png",
"repeat": false, "disabled" : "resources/button_minus_disabled.png"
"steps": [ }
{ },
"type": "wait", {
"duration": 1.0 "type": "Button",
}, "name": "plusButton",
{ "x": -20,
"type": "move", "y": 220,
"to": [ "width": 150,
-400, "height": 150,
0 "border" : 20,
], "horizontal_gravity": "right",
"duration": 1.0, "vertical_gravity": "bottom",
"easing": "easein" "textures": {
} "normal": "resources/button_plus.png",
] "hover": "resources/button_plus.png",
}, "pressed": "resources/button_plus_pressed.png",
"bgScroll": { "disabled" : "resources/button_plus_disabled.png"
"repeat": true, }
"steps": [ },
{ {
"type": "move", "type": "Button",
"to": [ "name": "takeButton",
1280, "x": -20,
0 "y": 320,
], "width": 150,
"duration": 5.0, "height": 150,
"easing": "linear" "border" : 20,
} "horizontal_gravity": "right",
] "vertical_gravity": "bottom",
} "textures": {
}, "normal": "resources/button_take.png",
"textures": { "hover": "resources/button_take.png",
"normal": "./resources/sand2.png", "pressed": "resources/button_take_pressed.png",
"hover": "./resources/sand2.png", "disabled" : "resources/button_take_disabled.png"
"pressed": "./resources/sand2.png"
}
} }
]
} }
] ]
},
{
"type": "Slider",
"name": "velocitySlider",
"x": 1140,
"y": 100,
"width": 50,
"height": 500,
"value": 0.0,
"orientation": "vertical",
"textures": {
"track": "resources/velocitySliderTexture.png",
"knob": "resources/velocitySliderButton.png"
}
},
{
"type": "Button",
"name": "shootButton",
"x": 100,
"y": 100,
"width": 100,
"height": 100,
"textures": {
"normal": "resources/shoot_normal.png",
"hover": "resources/shoot_hover.png",
"pressed": "resources/shoot_pressed.png"
}
}
]
} }
} }
+194
View File
@@ -0,0 +1,194 @@
{
"root": {
"type": "FrameLayout",
"x": 0,
"y": 0,
"width": 1280,
"height": 720,
"children": [
{
"type": "FrameLayout",
"name": "leftPanel",
"x": 100,
"y": 100,
"width": 320,
"height": 400,
"children": [
{
"type": "LinearLayout",
"name": "mainButtons",
"orientation": "vertical",
"spacing": 10,
"x": 0,
"y": 0,
"width": 300,
"height": 300,
"children": [
{
"type": "Button",
"name": "playButton",
"x": -1000,
"y": 500,
"width": 200,
"height": 50,
"animations": {
"buttonsExit": {
"repeat": false,
"steps": [
{
"type": "move",
"to": [
-400,
0
],
"duration": 1.0,
"easing": "easein"
}
]
}
},
"textures": {
"normal": "./resources/sand2.png",
"hover": "./resources/sand2.png",
"pressed": "./resources/sand2.png"
}
},
{
"type": "Button",
"name": "settingsButton",
"x": -1000,
"y": 400,
"width": 200,
"height": 50,
"animations": {
"buttonsExit": {
"repeat": false,
"steps": [
{
"type": "wait",
"duration": 0.5
},
{
"type": "move",
"to": [
-400,
0
],
"duration": 1.0,
"easing": "easein"
}
]
}
},
"textures": {
"normal": "./resources/sand2.png",
"hover": "./resources/sand2.png",
"pressed": "./resources/sand2.png"
}
},
{
"type": "Button",
"name": "exitButton",
"x": -1000,
"y": 300,
"width": 200,
"height": 50,
"animations": {
"buttonsExit": {
"repeat": false,
"steps": [
{
"type": "wait",
"duration": 1.0
},
{
"type": "move",
"to": [
-400,
0
],
"duration": 1.0,
"easing": "easein"
}
]
},
"bgScroll": {
"repeat": true,
"steps": [
{
"type": "move",
"to": [
1280,
0
],
"duration": 5.0,
"easing": "linear"
}
]
}
},
"textures": {
"normal": "./resources/sand2.png",
"hover": "./resources/sand2.png",
"pressed": "./resources/sand2.png"
}
}
]
}
]
},
{
"type": "Slider",
"name": "velocitySlider",
"x": 1140,
"y": 300,
"width": 50,
"height": 300,
"value": 0.0,
"orientation": "vertical",
"textures": {
"track": "resources/velocitySliderTexture.png",
"knob": "resources/velocitySliderButton.png"
}
},
{
"type": "Button",
"name": "shootButton",
"x": 100,
"y": 100,
"width": 100,
"height": 100,
"textures": {
"normal": "resources/shoot_normal.png",
"hover": "resources/shoot_hover.png",
"pressed": "resources/shoot_pressed.png"
}
},
{
"type": "Button",
"name": "shootButton2",
"x": 1000,
"y": 100,
"width": 100,
"height": 100,
"textures": {
"normal": "resources/shoot_normal.png",
"hover": "resources/shoot_hover.png",
"pressed": "resources/shoot_pressed.png"
}
},
{
"type": "TextView",
"name": "velocityText",
"x": 10,
"y": 10,
"width": 200,
"height": 40,
"text": "Velocity: 0",
"fontSize": 24,
"color": [1.0, 1.0, 1.0, 1.0],
"centered": false
}
]
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large. Load diff
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,125 @@
//precisionhighp float;
// Фрагментный шейдер:
uniform vec3 uColor;
uniform float uDistanceToPlanetSurface; // Расстояние корабля до поверхности
// Константы затухания, определенные прямо в шейдере
const float DIST_FOG_MAX = 2000.0;
const float DIST_FOG_MIN = 1000.0;
varying vec3 vWorldNormal;
varying vec3 vViewNormal;
varying vec3 vViewPosition;
// Добавь эти uniform-ы
//uniform float uTime;
uniform vec3 uLightDirView;
uniform vec3 uPlayerDirWorld;
// Простая функция псевдослучайного шума
float hash(float n) { return fract(sin(n) * 43758.5453123); }
float noise(vec3 x) {
vec3 p = floor(x);
vec3 f = fract(x);
f = f * f * (3.0 - 2.0 * f);
float n = p.x + p.y * 57.0 + 113.0 * p.z;
return mix(mix(mix(hash(n + 0.0), hash(n + 1.0), f.x),
mix(hash(n + 57.0), hash(n + 58.0), f.x), f.y),
mix(mix(hash(n + 113.0), hash(n + 114.0), f.x),
mix(hash(n + 170.0), hash(n + 171.0), f.x), f.y), f.z);
}
// Fractal Brownian Motion для "кучевости" облаков
float fbm(vec3 p) {
float f = 0.5000 * noise(p); p *= 2.02;
f += 0.2500 * noise(p); p *= 2.03;
f += 0.1250 * noise(p);
return f;
}
void main()
{
//gl_FragColor = vec4(1.0, 0.0, 0.0, 0.5);
vec3 normal = normalize(vViewNormal);
vec3 viewVector = normalize(-vViewPosition);
float NdotV = dot(normal, viewVector);
// Вектор направления от центра планеты к текущему фрагменту атмосферы (Мировой)
vec3 fragmentDir = normalize(vWorldNormal);
// Вектор направления от центра планеты к игроку (нужно передать как uniform)
// Передай его в C++: renderer.RenderUniform3fv("uPlayerDirWorld", playerDirWorld.data());
// --- 1. Плавное отсечение за горизонтом (Horizon Mask) ---
// Считаем косинус угла между игроком и точкой атмосферы
float cosAngle = dot(fragmentDir, uPlayerDirWorld);
// Плавно затухаем от 0.0 (горизонт) до 0.2 (над головой)
//float horizonMask = smoothstep(0.0, 0.4, cosAngle);
float horizonMask = smoothstep(0.93, 1.0, cosAngle);
// --- 2. Плавный переход при прохождении сквозь слой (Transition Mask) ---
// Определяем "высоту" игрока относительно слоя (напр. слой на 1.03 * R)
// uDistanceToPlanetSurface уже вычислен в PlanetData
float layerHeight = 600.0; // Примерная толщина слоя атмосферы (3% от 20000)
// Делаем прозрачным при приближении к границе (dist около layerHeight)
// и снова видимым, когда спустились ниже
float distToLayer = abs(uDistanceToPlanetSurface - layerHeight);
float transitionMask = smoothstep(0.0, 200.0, distToLayer);
// --- 3. Освещение и облака ---
float diff = max(dot(normal, uLightDirView), 0.0);
if (uDistanceToPlanetSurface < layerHeight) {
diff = max(dot(-normal, uLightDirView), 0.0); // Инверсия для взгляда снизу
}
float lightIntensity = diff + 0.05;
vec3 cloudCoord = fragmentDir * 6.0;
//cloudCoord.x += uTime * 0.03;
float n = fbm(cloudCoord);
float cloudMask = smoothstep(0.4, 0.65, n);
// --- 4. Финальный расчет альфы ---
float atmosphereDensity = pow(1.0 - abs(NdotV), 5.0);
float distanceFactor = clamp((uDistanceToPlanetSurface - DIST_FOG_MIN) / (DIST_FOG_MAX - DIST_FOG_MIN), 0.0, 1.0);
// Базовая прозрачность облаков
float cloudAlpha = cloudMask * 0.8;
// Применяем маски:
// В космосе важен distanceFactor, на планете важен horizonMask
float finalCloudAlpha = cloudAlpha * transitionMask;
if (uDistanceToPlanetSurface < layerHeight) {
finalCloudAlpha *= horizonMask; // На планете скрываем то, что под ногами
} else {
finalCloudAlpha *= distanceFactor; // В космосе скрываем по вашей старой логике
if (NdotV <=0.0)
{
//finalCloudAlpha = 0.0;
discard;
}
}
vec3 currentAtmo = mix(vec3(0.01, 0.02, 0.1), uColor, lightIntensity);
vec3 currentCloud = mix(vec3(0.1, 0.1, 0.15), vec3(1.0, 1.0, 1.0), lightIntensity);
vec3 finalRGB = mix(currentAtmo, currentCloud, cloudMask);
//vec3 finalRGB = currentAtmo;
// Для дымки (atmo) оставляем затухание при посадке
float atmoAlpha = atmosphereDensity * distanceFactor;
//float atmoAlpha = distanceFactor;
float finalAtmoAlpha = atmoAlpha;
if (uDistanceToPlanetSurface < layerHeight) {
finalCloudAlpha *= horizonMask;
finalAtmoAlpha *= horizonMask; // Принудительно гасим дымку под горизонтом
}
gl_FragColor = vec4(finalRGB, max(finalAtmoAlpha, finalCloudAlpha));
}
@@ -0,0 +1,9 @@
//precisionmediump float;
varying vec3 color;
void main()
{
//gl_FragColor = vec4(color, 1.0);
gl_FragColor = vec4(1.0, 1.0, 0.5, 1.0);
}
@@ -0,0 +1,12 @@
//precisionmediump float;
uniform sampler2D Texture;
varying vec2 texCoord;
void main()
{
vec4 color = texture2D(Texture,texCoord).rgba;
//gl_FragColor = vec4(color.rgb*0.1 + vec3(0.9, 0.9, 0.9), 1.0);
gl_FragColor = color;
}
@@ -0,0 +1,8 @@
//precisionmediump float;
uniform samplerCube Texture;
varying vec3 dir;
void main(){
gl_FragColor = textureCube(Texture, normalize(dir));
}
@@ -0,0 +1,9 @@
//precisionmediump float;
uniform sampler2D Texture;
varying vec2 texCoord;
void main()
{
vec4 color = texture2D(Texture,texCoord).rgba;
gl_FragColor = color;
}
@@ -0,0 +1,37 @@
//precisionmediump float;
uniform samplerCube Texture;
uniform float skyPercent;
uniform float uPlayerLightFactor; // Глобальный фактор дня/ночи для позиции игрока
uniform vec3 uSkyColor;
varying vec3 vViewDir;
void main() {
vec3 viewDir = normalize(vViewDir);
// 1. Получаем звезды
vec4 starsColor = textureCube(Texture, viewDir);
// 2. Цвета атмосферы
vec3 dayColor = uSkyColor;
vec3 nightColor = vec3(0.01, 0.01, 0.04);
// 3. Теперь всё небо окрашивается одинаково в зависимости от положения игрока
// Мы плавно смешиваем ночной и дневной купол
vec3 atmosphericColor = mix(nightColor, dayColor, uPlayerLightFactor);
// 4. Логика видимости звезд
// Звезды видны в космосе (skyPercent=0)
// И в атмосфере, если сейчас ночь (uPlayerLightFactor -> 0)
float starsVisibility = (1.0 - skyPercent) + (skyPercent * (1.0 - uPlayerLightFactor));
// Делаем звезды чуть ярче на ночном небе
starsVisibility = pow(starsVisibility, 1.5);
// 5. Итоговый цвет
// Добавляем слой атмосферы к звездам
vec3 skyLayer = atmosphericColor * skyPercent;
vec3 finalColor = (starsColor.rgb * starsVisibility) + skyLayer;
gl_FragColor = vec4(finalColor, 1.0);
}
@@ -0,0 +1,14 @@
//precisionmediump float;
varying vec2 TexCoord;
varying float vHeight;
uniform sampler2D Texture;
void main()
{
vec4 stoneColor = texture2D(Texture, TexCoord);
gl_FragColor = vec4(stoneColor.rgb, vHeight);
//gl_FragColor = vec4(vHeight, vHeight, vHeight, vHeight);
//gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);
}
+1 -1
View File
@@ -15,7 +15,7 @@ varying vec3 vWorldNormal;
uniform mat4 ProjectionModelViewMatrix; uniform mat4 ProjectionModelViewMatrix;
uniform mat4 ModelViewMatrix; uniform mat4 ModelViewMatrix;
uniform highp vec3 uViewPos; uniform vec3 uViewPos;
void main() { void main() {
gl_Position = ProjectionModelViewMatrix * vec4(vPosition, 1.0); gl_Position = ProjectionModelViewMatrix * vec4(vPosition, 1.0);
@@ -0,0 +1,116 @@
//precisionhighp float;
varying vec2 TexCoord;
varying vec3 vViewDirTangent;
varying vec3 Color;
varying vec3 worldPosition;
varying vec3 vWorldNormal;
uniform sampler2D Texture;
uniform sampler2D BakedTexture;
uniform float uHeightScale;
uniform float uDistanceToPlanetSurface;
uniform float uCurrentZFar;
uniform vec3 uViewPos;
const vec4 FOG_COLOR = vec4(0.0, 0.5, 1.0, 1.0); // Синий туман
uniform vec3 uLightDirWorld; // Направление ЛУЧЕЙ (1, -1, -1)
uniform float uPlayerLightFactor;
uniform vec3 uPlayerDirWorld;
void main() {
// --- 1. Расчет освещения поверхности ---
// Направление НА источник света
vec3 lightToSource = normalize(-uLightDirWorld);
vec3 fragmentDir = normalize(vWorldNormal);
// Используем vNormal (нормаль в мировом пространстве, так как vPosition тоже в мировом)
// Важно: если vNormal не нормализована в вершинном, делаем это здесь
vec3 normal = normalize(fragmentDir); // На планете-сфере нормаль совпадает с направлением от центра
float diff = max(dot(normal, lightToSource), 0.0);
float ambient = 0.3; // Базовая освещенность ночной стороны
float surfaceLightIntensity = diff + ambient;
// --- 2. Динамический цвет тумана ---
// Синхронизируем туман с атмосферой: днем голубой, ночью темно-синий
vec3 dayFog = vec3(0.0, 0.5, 1.0);
vec3 nightFog = vec3(0.01, 0.01, 0.04);
vec3 dynamicFogColor = mix(nightFog, dayFog, uPlayerLightFactor);
// --- 3. Основная логика текстур (твой код) ---
vec3 viewDir = normalize(vViewDirTangent);
float height = texture2D(Texture, TexCoord).a;
vec2 p = vec2(viewDir.x, -viewDir.y) * (height * uHeightScale);
vec2 finalTexCoord = TexCoord + p;
float realDist = distance(worldPosition, uViewPos);
float textureMixFactor = clamp((2000.0 - realDist) / 500.0, 0.0, 1.0);
vec4 bakedTextureColor = texture2D(BakedTexture, finalTexCoord);
vec4 textureColor = texture2D(Texture, TexCoord);
vec4 textureFlavoredColor = vec4(textureColor.rgb * Color, 1.0);
if (bakedTextureColor.x < 0.01 && bakedTextureColor.y < 0.01 && bakedTextureColor.z < 0.01) {
textureMixFactor = 1.0;
}
vec4 finalColor = textureMixFactor * textureFlavoredColor + (1.0 - textureMixFactor) * bakedTextureColor;
// --- 4. ПРИМЕНЕНИЕ ОСВЕЩЕНИЯ ---
// Умножаем результат текстурирования на освещенность
finalColor.rgb *= surfaceLightIntensity;
// --- 5. Расчет тумана (с использованием динамического цвета) ---
float h = uDistanceToPlanetSurface;
float fogStart, fogEnd;
if (h >= 1000.0) {
gl_FragColor = vec4(finalColor.rgb, 1.0);
}
else
{
if (h > 100.0) {
// Нормализуем высоту от 100 до 1000 (t: 0 -> 1)
float t = (h - 100.0) / 900.0;
// На высоте 100 туман начинается со 100.
// К высоте 1000 он плавно "убегает" к границе 2500, где объект исчезает.
fogStart = mix(1500.0, 15000.0, t);
// Держим ширину зоны тумана в пределах 400-600 единиц
float fogRange = mix(1000.0, 6000.0, t);
fogEnd = fogStart + fogRange;
}
else if (h > 40.0) {
float t = (h - 40.0) / 60.0;
// На высоте 100 туман начинается со 100.
// К высоте 1000 он плавно "убегает" к границе 2500, где объект исчезает.
fogStart = mix(800.0, 1500.0, t);
fogEnd = mix(1000.0, 2500.0, t);
}
else if (h > 20.0) {
float t = (h - 20.0) / 20.0;
fogStart = mix(200.0, 800.0, t);
fogEnd = mix(500.0, 1000.0, t);
}
else {
// Минимумы при h = 0: start 25, end 125
float t = clamp(h / 20.0, 0.0, 1.0);
fogStart = mix(100.0, 200.0, t);
fogEnd = mix(250.0, 500.0, t);
}
float fogRange = max(fogEnd - fogStart, 1.0);
float fogFactor = clamp((realDist - fogStart) / fogRange, 0.0, 1.0);
// Смешиваем с динамическим цветом тумана
vec3 mixedColor = mix(finalColor.rgb, dynamicFogColor, fogFactor);
gl_FragColor = vec4(mixedColor, 1.0);
}
}
+1 -1
View File
@@ -11,7 +11,7 @@ uniform float uHeightScale;
uniform float uDistanceToPlanetSurface; uniform float uDistanceToPlanetSurface;
uniform float uCurrentZFar; uniform float uCurrentZFar;
uniform vec3 uViewPos; uniform highp vec3 uViewPos;
const vec4 FOG_COLOR = vec4(0.0, 0.5, 1.0, 1.0); // Синий туман const vec4 FOG_COLOR = vec4(0.0, 0.5, 1.0, 1.0); // Синий туман
+1 -3
View File
@@ -14,7 +14,7 @@ varying vec3 vWorldNormal;
uniform mat4 ProjectionModelViewMatrix; uniform mat4 ProjectionModelViewMatrix;
uniform mat4 ModelViewMatrix; uniform mat4 ModelViewMatrix;
uniform highp vec3 uViewPos; uniform vec3 uViewPos;
void main() { void main() {
vWorldNormal = vNormal; vWorldNormal = vNormal;
@@ -23,8 +23,6 @@ void main() {
vec3 viewDirWorld = normalize(uViewPos - vPosition); vec3 viewDirWorld = normalize(uViewPos - vPosition);
// Строим матрицу перехода из атрибутов
// Так как базис ортонормирован, TBN^-1 == TBN_transpose
vViewDirTangent = vec3( vViewDirTangent = vec3(
dot(viewDirWorld, vTangent), dot(viewDirWorld, vTangent),
dot(viewDirWorld, vBinormal), dot(viewDirWorld, vBinormal),
@@ -0,0 +1,102 @@
//precisionhighp float;
// planetStone фрагментный шейдер
varying vec2 TexCoord;
varying vec3 worldPosition;
varying vec3 vWorldNormal;
uniform sampler2D Texture;
uniform float uDistanceToPlanetSurface;
uniform vec3 uViewPos;
uniform vec3 uLightDirWorld;
uniform float uPlayerLightFactor;
void main()
{
// --- 1. Подготовка векторов ---
vec3 normal = normalize(vWorldNormal);
vec3 lightToSource = normalize(-uLightDirWorld);
// Вектор от центра планеты к камню (нормаль самой поверхности планеты под камнем)
// Предполагаем, что центр планеты в (0,0,0)
vec3 surfaceNormal = normalize(worldPosition);
// --- 2. Расчет Shadow Mask ---
// Проверяем, освещена ли точка планеты, на которой стоит камень
float shadowMask = clamp(dot(surfaceNormal, lightToSource) * 5.0, 0.0, 1.0);
// Коэффициент 5.0 делает переход на терминаторе более четким
// --- 3. Освещение камня ---
float diff = max(dot(normal, lightToSource), 0.0);
// Применяем shadowMask к диффузной составляющей
// Если точка на планете в тени, то прямой свет (diff) обнуляется
float ambient = 0.3;
float lightIntensity = (diff * shadowMask);
lightIntensity *= mix(0.2, 1.0, shadowMask);
lightIntensity += ambient;
// --- 4. Остальная логика (цвета и туман) ---
vec3 dayFog = vec3(0.0, 0.5, 1.0);
vec3 nightFog = vec3(0.01, 0.01, 0.04);
vec3 dynamicFogColor = mix(nightFog, dayFog, uPlayerLightFactor);
vec4 textureColor = texture2D(Texture, TexCoord);
vec3 litColor = textureColor.rgb * lightIntensity;
float realDist = distance(worldPosition, uViewPos);
float h = uDistanceToPlanetSurface;
float alphaFactor = clamp((2000.0 - realDist) / 500.0, 0.0, 1.0);
float fogStart, fogEnd;
// --- Логика расчета границ тумана ---
if (h >= 1000.0) {
gl_FragColor = vec4(litColor, alphaFactor);
}
else
{
if (h > 100.0) {
// Нормализуем высоту от 100 до 1000 (t: 0 -> 1)
float t = (h - 100.0) / 900.0;
// На высоте 100 туман начинается со 100.
// К высоте 1000 он плавно "убегает" к границе 2500, где объект исчезает.
fogStart = mix(1500.0, 15000.0, t);
// Держим ширину зоны тумана в пределах 400-600 единиц
float fogRange = mix(1000.0, 6000.0, t);
fogEnd = fogStart + fogRange;
}
else if (h > 40.0) {
float t = (h - 40.0) / 60.0;
// На высоте 100 туман начинается со 100.
// К высоте 1000 он плавно "убегает" к границе 2500, где объект исчезает.
fogStart = mix(800.0, 1500.0, t);
fogEnd = mix(1000.0, 2500.0, t);
}
else if (h > 20.0) {
float t = (h - 20.0) / 20.0;
fogStart = mix(200.0, 800.0, t);
fogEnd = mix(500.0, 1000.0, t);
}
else {
// Минимумы при h = 0: start 25, end 125
float t = clamp(h / 20.0, 0.0, 1.0);
fogStart = mix(100.0, 200.0, t);
fogEnd = mix(250.0, 500.0, t);
}
// Расчет фактора тумана
float fogRange = max(fogEnd - fogStart, 1.0);
float fogFactor = clamp((realDist - fogStart) / fogRange, 0.0, 1.0);
// Смешивание освещенного камня с динамическим туманом
vec3 mixedColor = mix(litColor, dynamicFogColor, fogFactor);
gl_FragColor = vec4(mixedColor, alphaFactor);
}
}
+9
View File
@@ -0,0 +1,9 @@
//precisionmediump float;
uniform sampler2D Texture;
varying vec2 texCoord;
void main()
{
vec4 color = texture2D(Texture,texCoord).rgba;
gl_FragColor = color;
}
File renamed without changes.
+11
View File
@@ -0,0 +1,11 @@
attribute vec2 vPosition;
attribute vec2 vTexCoord;
varying vec2 TexCoord;
uniform mat4 uProjection;
void main() {
TexCoord = vTexCoord;
gl_Position = uProjection * vec4(vPosition, 0.0, 1.0);
}
+14
View File
@@ -0,0 +1,14 @@
#version 330 core
in vec2 TexCoord;
out vec4 FragColor;
uniform sampler2D uText;
uniform vec4 uColor;
uniform vec4 uOutlineColor;
uniform float uOutlineWidth = 0.7;
void main() {
float dist = texture(uText, TexCoord).r;
float outline = smoothstep(0.5 - uOutlineWidth, 0.5 + uOutlineWidth, dist);
float text = smoothstep(0.5, 0.5 + 0.1, dist);
float glow = exp(-pow(dist - 0.5, 2.0) / 0.02);
FragColor = vec4(uColor.rgb * (text + glow * 0.6), uColor.a * outline);
}
Loaded 100 of 165 files, more files were not shown because too many files have changed in this diff. Show more