Added music

This commit is contained in:
Vladislav Khorev 2026-06-21 21:27:27 +03:00
parent 7db9ca8f70
commit 84f9fa37a8
13 changed files with 118 additions and 8 deletions

BIN
audio/bishkek fight calm.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
audio/bishkek fight.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
audio/bishkek univer day.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
audio/main menu final.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
audio/obshaga.ogg (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -99,9 +99,20 @@ void AudioPlayerAsync::playSoundAsync(const std::string& filePath, int loops, in
} }
void AudioPlayerAsync::playMusicAsync(const std::string& filePath, int loops) { void AudioPlayerAsync::playMusicAsync(const std::string& filePath, int loops) {
std::cout << "AudioPlayerAsync::playMusicAsync called step 1" << std::endl;
if (!initialized) return; if (!initialized) return;
std::cout << "AudioPlayerAsync::playMusicAsync called step 1" << std::endl;
if (filePath == currentTrack)
{
return;
}
currentTrack = filePath;
auto task = [filePath, loops]() { auto task = [filePath, loops]() {
std::cout << "AudioPlayerAsync::playMusicAsync called step 3" << std::endl;
Mix_Music* music = Mix_LoadMUS(filePath.c_str()); Mix_Music* music = Mix_LoadMUS(filePath.c_str());
if (!music) { if (!music) {
std::cerr << "Failed to load music " << filePath << ": " << Mix_GetError() << std::endl; std::cerr << "Failed to load music " << filePath << ": " << Mix_GetError() << std::endl;
@ -124,6 +135,9 @@ void AudioPlayerAsync::playMusicAsync(const std::string& filePath, int loops) {
void AudioPlayerAsync::stopMusicAsync() { void AudioPlayerAsync::stopMusicAsync() {
if (!initialized) return; if (!initialized) return;
currentTrack = "";
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
Mix_HaltMusic(); Mix_HaltMusic();
#else #else

View File

@ -46,5 +46,7 @@ private:
std::unordered_map<std::string, Mix_Chunk*> soundCache; std::unordered_map<std::string, Mix_Chunk*> soundCache;
std::mutex soundCacheMutex; std::mutex soundCacheMutex;
std::string currentTrack;
bool initialized = false; bool initialized = false;
}; };

View File

@ -74,8 +74,8 @@ namespace ZL
Game::Game() Game::Game()
: newTickCount(0) : newTickCount(0)
, lastTickCount(0) , lastTickCount(0)
, menuManager(renderer, gameState)
, audioPlayer(std::make_unique<AudioPlayerAsync>()) , audioPlayer(std::make_unique<AudioPlayerAsync>())
, menuManager(renderer, gameState, *audioPlayer)
{ {
} }
@ -327,14 +327,13 @@ namespace ZL
menuManager.startGameFunc = [this]() { menuManager.startGameFunc = [this]() {
gameState.currentLocationName = "location_dorm"; gameState.currentLocationName = "location_dorm";
currentLocation()->scriptEngine.callLocationEnterCallback(); currentLocation()->scriptEngine.callLocationEnterCallback();
this->audioPlayer->playMusicAsync("audio/obshaga.ogg");
}; };
menuManager.onSaveGame = [this](int slot) { saveGame(slot); }; menuManager.onSaveGame = [this](int slot) { saveGame(slot); };
menuManager.onLoadGame = [this](int slot) { loadGame(slot); }; menuManager.onLoadGame = [this](int slot) { loadGame(slot); };
menuManager.getSlotInfoFunc = [this](int slot) { return readSlotInfo(slot); }; menuManager.getSlotInfoFunc = [this](int slot) { return readSlotInfo(slot); };
loadingCompleted = true;
if (audioPlayer->init()) { if (audioPlayer->init()) {
audioPlayer->setMusicVolume(100); audioPlayer->setMusicVolume(100);
audioPlayer->setSoundVolume(80); audioPlayer->setSoundVolume(80);
@ -344,6 +343,11 @@ namespace ZL
std::cout << "Audio initialization failed" << std::endl; std::cout << "Audio initialization failed" << std::endl;
} }
audioPlayer->playMusicAsync("audio/main menu final.ogg");
loadingCompleted = true;
} }
void Game::createLocations() void Game::createLocations()
@ -448,6 +452,12 @@ namespace ZL
} }
} }
gameState.locations["uni_interior"]->requestDarklandsPlayBattleMusic = [this]() {
audioPlayer->playMusicAsync("audio/bishkek fight.ogg");
};
gameState.locations["uni_interior"]->requestDarklandsPlayNormalMusic = [this]() {
audioPlayer->playMusicAsync("audio/bishkek fight calm.ogg");
};
LocationSetup uniExteriorParams = uniInteriorParams; LocationSetup uniExteriorParams = uniInteriorParams;
uniExteriorParams.gameObjectsJsonPath = "resources/config2/gameobjects_uni_exterior_x.json"; uniExteriorParams.gameObjectsJsonPath = "resources/config2/gameobjects_uni_exterior_x.json";
uniExteriorParams.interactiveObjectsJsonPath = "resources/config2/interactive_objects_uni_exterior_x.json"; uniExteriorParams.interactiveObjectsJsonPath = "resources/config2/interactive_objects_uni_exterior_x.json";

View File

@ -57,6 +57,8 @@ namespace ZL {
bool startDarklandsTransition(); bool startDarklandsTransition();
bool startNightTransition(); bool startNightTransition();
std::unique_ptr<AudioPlayerAsync> audioPlayer;
MenuManager menuManager; MenuManager menuManager;
void activateSlowMoEffect(); void activateSlowMoEffect();
@ -91,8 +93,7 @@ namespace ZL {
float dragStartAzimuth = 0.0f; float dragStartAzimuth = 0.0f;
float dragStartInclination = 0.0f; float dragStartInclination = 0.0f;
std::unique_ptr<AudioPlayerAsync> audioPlayer;
Location* currentLocation() const; Location* currentLocation() const;
void saveGame(int slot); void saveGame(int slot);

View File

@ -1516,9 +1516,32 @@ namespace ZL
dialogueSystem.update(static_cast<int>(delta)); dialogueSystem.update(static_cast<int>(delta));
updateTriggerZones(player->state.position); updateTriggerZones(player->state.position);
} }
bool npcAttacking = false;
for (auto& npc : npcs) for (auto& npc : npcs)
{ {
npc->update(delta, resolver); npc->update(delta, resolver);
if (npc->state.enabled && npc->state.canAttack && (!npc->state.pathWaypoints.empty() || npc->state.battle_state != 0) && npc->getHp() > 0.f)
{
//std::cout << "[NPC] NPC '" << npc->state.npcId << "' is attacking target index " << npc->state.attackTargetIndex << std::endl;
npcAttacking = true;
}
}
if (state.isDarklands)
{
if (npcAttacking && !playBattleMusic)
{
playBattleMusic = true;
if (requestDarklandsPlayBattleMusic) requestDarklandsPlayBattleMusic();
}
else if (!npcAttacking && playBattleMusic)
{
playBattleMusic = false;
if (requestDarklandsPlayNormalMusic) requestDarklandsPlayNormalMusic();
}
} }
resolveCharacterCollisions(); resolveCharacterCollisions();

View File

@ -114,6 +114,10 @@ namespace ZL
std::function<void()> requestReturnToMainMenu; std::function<void()> requestReturnToMainMenu;
std::function<void(int, bool, const std::string&)> requestSetChatUnread; std::function<void(int, bool, const std::string&)> requestSetChatUnread;
std::function<void()> requestDarklandsPlayBattleMusic;
std::function<void()> requestDarklandsPlayNormalMusic;
// Navigation editor — toggle with 'N', save with 'B', right-click to finalize polygon // Navigation editor — toggle with 'N', save with 'B', right-click to finalize polygon
EditorMode editorMode = EditorMode::None; EditorMode editorMode = EditorMode::None;
LocationEditor editor; LocationEditor editor;
@ -126,6 +130,8 @@ namespace ZL
int lastMouseX = 0; int lastMouseX = 0;
int lastMouseY = 0; int lastMouseY = 0;
bool playBattleMusic = false;
void setup(const LocationSetup& params, Quest::QuestJournal* journal); void setup(const LocationSetup& params, Quest::QuestJournal* journal);
void setupNavigation(const std::vector<std::string>& paths); void setupNavigation(const std::vector<std::string>& paths);

View File

@ -92,9 +92,10 @@ namespace ZL {
} }
} }
MenuManager::MenuManager(Renderer& iRenderer, GameState& gameState) : MenuManager::MenuManager(Renderer& iRenderer, GameState& gameState, AudioPlayerAsync& audioPlayer) :
renderer(iRenderer), renderer(iRenderer),
gameState_(gameState) gameState_(gameState),
audioPlayer_(audioPlayer)
{ {
} }
@ -250,6 +251,9 @@ namespace ZL {
void MenuManager::showMainMenu() { void MenuManager::showMainMenu() {
if (onResetGame) onResetGame(); if (onResetGame) onResetGame();
audioPlayer_.playMusicAsync("audio/main menu final.ogg");
uiState_ = GameUiState::MainMenu; uiState_ = GameUiState::MainMenu;
uiManager.clearMenuStack(); uiManager.clearMenuStack();
topUiManager.replaceRoot(nullptr); topUiManager.replaceRoot(nullptr);
@ -900,13 +904,46 @@ namespace ZL {
uiManager.replaceRoot(gameState_.isDarklands ? hudUniExtDarkRoot : hudUniExtRoot); uiManager.replaceRoot(gameState_.isDarklands ? hudUniExtDarkRoot : hudUniExtRoot);
applyCurrentHealthBar(); applyCurrentHealthBar();
setupGameplayHudCallbacks(); setupGameplayHudCallbacks();
if (gameState_.isDarklands)
{
audioPlayer_.playMusicAsync("audio/bishkek fight calm.ogg");
}
else if (gameState_.isNight)
{
audioPlayer_.playMusicAsync("audio/bishkek fight calm.ogg");
}
else
{
audioPlayer_.playMusicAsync("audio/bishkek univer day.ogg");
}
} else if (locationName == "uni_interior") { } else if (locationName == "uni_interior") {
applyUniIntHud(); applyUniIntHud();
if (gameState_.isDarklands)
{
audioPlayer_.playMusicAsync("audio/bishkek fight calm.ogg");
}
else if (gameState_.isNight)
{
audioPlayer_.playMusicAsync("audio/bishkek fight calm.ogg");
}
else
{
audioPlayer_.playMusicAsync("audio/bishkek univer day.ogg");
}
} else { } else {
// Returning to dorm: reuse step5ab, suppress already-completed hints // Returning to dorm: reuse step5ab, suppress already-completed hints
uiManager.replaceRoot(hudStep5abRoot); uiManager.replaceRoot(hudStep5abRoot);
applyCurrentHealthBar(); applyCurrentHealthBar();
setupStep5Callbacks(); setupStep5Callbacks();
if (gameState_.isNight)
{
audioPlayer_.playMusicAsync("audio/bishkek fight calm.ogg");
}
else
{
audioPlayer_.playMusicAsync("audio/obshaga.ogg");
}
} }
} }

View File

@ -9,6 +9,7 @@
#include <deque> #include <deque>
#include <string> #include <string>
#include <memory> #include <memory>
#include "AudioPlayerAsync.h"
// Forward-declared here to avoid pulling Game.h into MenuManager.h. // Forward-declared here to avoid pulling Game.h into MenuManager.h.
namespace ZL { struct SaveSlotInfo; } namespace ZL { struct SaveSlotInfo; }
@ -31,7 +32,7 @@ namespace ZL {
UiManager uiManager; UiManager uiManager;
UiManager topUiManager; UiManager topUiManager;
MenuManager(Renderer& iRenderer, GameState& gameState); MenuManager(Renderer& iRenderer, GameState& gameState, AudioPlayerAsync& audioPlayer);
void setup(Inventory& inv, const std::string& zipFile); void setup(Inventory& inv, const std::string& zipFile);
@ -101,6 +102,7 @@ namespace ZL {
private: private:
GameState& gameState_; GameState& gameState_;
AudioPlayerAsync& audioPlayer_;
void enterGameplay(bool isFromLoad = false); void enterGameplay(bool isFromLoad = false);
void applyHudForCurrentState(); void applyHudForCurrentState();