diff --git a/assets.zip b/assets.zip new file mode 100644 index 0000000..b8c7ef4 Binary files /dev/null and b/assets.zip differ diff --git a/config/spark_config.json b/config/spark_config.json index 6dce53a..8f71245 100644 --- a/config/spark_config.json +++ b/config/spark_config.json @@ -5,10 +5,10 @@ "biasX": 0.3, "emissionPoints": [ { - "position": [-2.1, 0.4, 5.0] + "position": [-1.3, 0, 0.0] }, { - "position": [2.1, 0.4, 5.0] + "position": [1.3, 0.0, 0.0] } ], "speedRange": [0.5, 2.0], diff --git a/src/Game.cpp b/src/Game.cpp index 4f948c2..115de29 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -15,7 +15,7 @@ namespace ZL #ifdef EMSCRIPTEN const char* CONST_ZIP_FILE = "space-game001a.zip"; #else - const char* CONST_ZIP_FILE = ""; + const char* CONST_ZIP_FILE = "../assets.zip"; #endif @@ -176,11 +176,11 @@ namespace ZL #endif #endif -#ifndef SIMPLIFIED - bool cfgLoaded = sparkEmitter.loadFromJsonFile("../config/spark_config.json", renderer, CONST_ZIP_FILE); - bool projCfgLoaded = projectileEmitter.loadFromJsonFile("../config/spark_projectile_config.json", renderer, CONST_ZIP_FILE); +//#ifndef SIMPLIFIED + bool cfgLoaded = sparkEmitter.loadFromJsonFile("config/spark_config.json", renderer, CONST_ZIP_FILE); + bool projCfgLoaded = projectileEmitter.loadFromJsonFile("config/spark_projectile_config.json", renderer, CONST_ZIP_FILE); projectileEmitter.setEmissionPoints(std::vector()); - uiManager.loadFromFile("../config/ui.json", renderer, CONST_ZIP_FILE); + uiManager.loadFromFile("config/ui.json", renderer, CONST_ZIP_FILE); uiManager.setButtonCallback("playButton", [this](const std::string& name) { std::cerr << "Play button pressed: " << name << std::endl; @@ -191,7 +191,7 @@ namespace ZL }); uiManager.setButtonCallback("settingsButton", [this](const std::string& name) { - if (uiManager.pushMenuFromFile("../config/settings.json", this->renderer, CONST_ZIP_FILE)) { + if (uiManager.pushMenuFromFile("config/settings.json", this->renderer, CONST_ZIP_FILE)) { uiManager.setButtonCallback("Opt1", [this](const std::string& n) { std::cerr << "Opt1 pressed: " << n << std::endl; @@ -215,7 +215,7 @@ namespace ZL musicVolume = value; Environment::shipVelocity = musicVolume * 20.0f; }); -#endif +//#endif cubemapTexture = std::make_shared( std::array{ @@ -446,11 +446,11 @@ namespace ZL } } -#ifndef SIMPLIFIED +//#ifndef SIMPLIFIED sparkEmitter.draw(renderer, Environment::zoom, Environment::width, Environment::height); projectileEmitter.draw(renderer, Environment::zoom, Environment::width, Environment::height); -#endif +//#endif renderer.PopMatrix(); renderer.PopProjectionMatrix(); renderer.DisableVertexAttribArray(vPositionName); @@ -613,10 +613,10 @@ namespace ZL drawShip(); drawBoxes(); -#ifndef SIMPLIFIED +//#ifndef SIMPLIFIED drawUI(); -#endif +//#endif CheckGlError(); } @@ -632,10 +632,10 @@ namespace ZL size_t delta = (newTickCount - lastTickCount > CONST_MAX_TIME_INTERVAL) ? CONST_MAX_TIME_INTERVAL : newTickCount - lastTickCount; -#ifndef SIMPLIFIED +//#ifndef SIMPLIFIED //gameObjects.updateScene(delta); sparkEmitter.update(static_cast(delta)); -#endif +//#endif planetObject.update(static_cast(delta)); if (Environment::tapDownHold) { @@ -670,7 +670,7 @@ namespace ZL Environment::shipPosition = Environment::shipPosition + velocityDirectionAdjusted; } -#ifndef SIMPLIFIED +//#ifndef SIMPLIFIED for (auto& p : projectiles) { if (p && p->isActive()) { p->update(static_cast(delta), renderer); @@ -705,7 +705,7 @@ namespace ZL sparkEmitter.update(static_cast(delta)); projectileEmitter.update(static_cast(delta)); -#endif +//#endif lastTickCount = newTickCount; } } @@ -763,7 +763,7 @@ namespace ZL uiManager.onMouseDown(uiX, uiY); bool uiHandled = false; -#ifndef SIMPLIFIED +//#ifndef SIMPLIFIED if (event.button.button == SDL_BUTTON_LEFT && !uiManager.isUiInteraction()) { uint64_t now = SDL_GetTicks64(); if (now - lastProjectileFireTime >= static_cast(projectileCooldownMs)) { @@ -771,7 +771,7 @@ namespace ZL fireProjectiles(); } } -#endif +//#endif for (const auto& button : uiManager.findButton("") ? std::vector>{} : std::vector>{}) { (void)button; } diff --git a/src/SparkEmitter.cpp b/src/SparkEmitter.cpp index 849bbb5..bb070eb 100644 --- a/src/SparkEmitter.cpp +++ b/src/SparkEmitter.cpp @@ -7,6 +7,7 @@ #include #include "Environment.h" #include +#include "utils/Utils.h" namespace ZL { @@ -329,15 +330,29 @@ namespace ZL { bool SparkEmitter::loadFromJsonFile(const std::string& path, Renderer& renderer, const std::string& zipFile) { std::cout << "Loading spark config from: " << path << std::endl; - std::ifstream in(path); - if (!in.is_open()) { - std::cerr << "Failed to open JSON file: " << path << std::endl; + + std::string content; + try { + if (zipFile.empty()) { + content = readTextFile(path); + } + else { + auto buf = readFileFromZIP(path, zipFile); + if (buf.empty()) { + std::cerr << "Failed to read JSON from zip: " << path << " in " << zipFile << std::endl; + throw std::runtime_error("Failed to load spark emitter config file!"); + } + content.assign(buf.begin(), buf.end()); + } + } + catch (const std::exception& e) { + std::cerr << "Failed to open JSON file: " << path << " : " << e.what() << std::endl; throw std::runtime_error("Failed to load spark emitter config file!"); } json j; try { - in >> j; + j = json::parse(content); std::cout << "JSON parsed successfully" << std::endl; } catch (const std::exception& e) { diff --git a/src/UiManager.cpp b/src/UiManager.cpp index 48c3c21..33d7a82 100644 --- a/src/UiManager.cpp +++ b/src/UiManager.cpp @@ -152,15 +152,28 @@ namespace ZL { } void UiManager::loadFromFile(const std::string& path, Renderer& renderer, const std::string& zipFile) { - std::ifstream in(path); - if (!in.is_open()) { - std::cerr << "UiManager: failed to open " << path << std::endl; + std::string content; + try { + if (zipFile.empty()) { + content = readTextFile(path); + } + else { + auto buf = readFileFromZIP(path, zipFile); + if (buf.empty()) { + std::cerr << "UiManager: failed to read " << path << " from zip " << zipFile << std::endl; + throw std::runtime_error("Failed to load UI file: " + path); + } + content.assign(buf.begin(), buf.end()); + } + } + catch (const std::exception& e) { + std::cerr << "UiManager: failed to open " << path << " : " << e.what() << std::endl; throw std::runtime_error("Failed to load UI file: " + path); } json j; try { - in >> j; + j = json::parse(content); } catch (const std::exception& e) { std::cerr << "UiManager: json parse error: " << e.what() << std::endl; diff --git a/src/utils/Utils.cpp b/src/utils/Utils.cpp index bfc09c2..91f6252 100644 --- a/src/utils/Utils.cpp +++ b/src/utils/Utils.cpp @@ -5,9 +5,11 @@ #include #include #include -#ifdef EMSCRIPTEN #include -#endif +#include +#include +#include +#include namespace ZL { @@ -34,7 +36,7 @@ namespace ZL file.seekg(0, std::ios::beg); std::vector vec; - vec.reserve(fileSize); + vec.reserve(static_cast(fileSize)); vec.insert(vec.begin(), std::istream_iterator(file), @@ -42,47 +44,96 @@ namespace ZL return vec; } - + std::vector readFileFromZIP(const std::string& filename, const std::string& zipfilename) { #ifdef EMSCRIPTEN const std::string zipPath = zipfilename; int zipErr; zip_t* archive = zip_open(zipPath.c_str(), ZIP_RDONLY, &zipErr); if (!archive) { - throw std::runtime_error("Ошибка открытия ZIP: " + zipPath); + throw std::runtime_error("?????? ???????? ZIP: " + zipPath); } - + std::string cleanFilename = filename; if (cleanFilename.rfind("./", 0) == 0) { cleanFilename = cleanFilename.substr(2); } - - std::cout << "Ищем в ZIP: " << cleanFilename << std::endl; - + + std::cout << "???? ? ZIP: " << cleanFilename << std::endl; + zip_file_t* zipFile = zip_fopen(archive, cleanFilename.c_str(), 0); if (!zipFile) { zip_close(archive); - throw std::runtime_error("Файл не найден в ZIP: " + cleanFilename); + throw std::runtime_error("???? ?? ?????? ? ZIP: " + cleanFilename); } - + zip_stat_t fileStat; if (zip_stat(archive, cleanFilename.c_str(), 0, &fileStat) != 0) { zip_fclose(zipFile); zip_close(archive); - throw std::runtime_error("Ошибка чтения ZIP-статистики."); + throw std::runtime_error("?????? ?????? ZIP-??????????."); } - + std::vector fileData; fileData.resize(fileStat.size); - + zip_fread(zipFile, fileData.data(), fileData.size()); - + zip_fclose(zipFile); zip_close(archive); - + return fileData; #else - return {}; + // ??????? + + if (zipfilename.empty()) { + std::cerr << "readFileFromZIP: zipfilename empty" << std::endl; + return {}; + } + + int zipErr = 0; + zip_t* archive = zip_open(zipfilename.c_str(), ZIP_RDONLY, &zipErr); + if (!archive) { + std::cerr << "readFileFromZIP: zip_open failed for: " << zipfilename + << " (error code " << zipErr << ")" << std::endl; + return {}; + } + + std::string cleanFilename = filename; + if (cleanFilename.rfind("./", 0) == 0) { + cleanFilename = cleanFilename.substr(2); + } + + zip_stat_t fileStat; + if (zip_stat(archive, cleanFilename.c_str(), 0, &fileStat) != 0) { + std::cerr << "readFileFromZIP: file not found in ZIP: " << cleanFilename + << " in " << zipfilename << std::endl; + zip_close(archive); + return {}; + } + + zip_file_t* zipFile = zip_fopen(archive, cleanFilename.c_str(), 0); + if (!zipFile) { + std::cerr << "readFileFromZIP: zip_fopen failed for " << cleanFilename << std::endl; + zip_close(archive); + return {}; + } + + std::vector fileData; + fileData.resize(static_cast(fileStat.size)); + + zip_int64_t readBytes = zip_fread(zipFile, fileData.data(), static_cast(fileData.size())); + if (readBytes < 0) { + std::cerr << "readFileFromZIP: zip_fread failed for " << cleanFilename << std::endl; + zip_fclose(zipFile); + zip_close(archive); + return {}; + } + + zip_fclose(zipFile); + zip_close(archive); + + return fileData; #endif } @@ -102,4 +153,4 @@ namespace ZL } return false; } -}; +}; \ No newline at end of file