Added music and perfom bug fixes

This commit is contained in:
Vladislav Khorev committed 2026-07-18 20:21:31 +03:00
1 parent e5e3d7bb28
commit 825a56a4a4
29 files changed
+185 -68

No files matched your search

+6 -1
View File
@@ -408,4 +408,9 @@ public
web_resources/
pc_resources/
resources_hd/
web_resources_x2/
web_resources_x2/
.artifacts/
*.zip
+2 -1
View File
@@ -39,7 +39,8 @@ add_subdirectory("${TP_ROOT}/libpng-1.6.51" libpng-build)
# --- SDL2 ---
# Android-версия SDL требует специфичных настроек, но add_subdirectory обычно подхватывает их сама
add_subdirectory("${TP_ROOT}/SDL-release-2.32.10" sdl-build)
#add_subdirectory("${TP_ROOT}/SDL_mixer-release-2.8.0" sdl-mixer-build)
add_subdirectory("${TP_ROOT}/SDL_mixer-release-2.8.0" sdl-mixer-build)
add_subdirectory("${TP_ROOT}/SDL_ttf-release-2.24.0" sdl-ttf-build)
+2
View File
@@ -150,6 +150,7 @@ target_link_libraries(main
z
SDL2
SDL2_ttf
SDL2_mixer
log
android
OpenSLES
@@ -163,6 +164,7 @@ target_link_libraries(main
target_include_directories(main PRIVATE
#${CMAKE_CURRENT_SOURCE_DIR}/../SDL/include
${CMAKE_CURRENT_SOURCE_DIR}/../../../../thirdparty/SDL_ttf-release-2.24.0/external/freetype/include
#${CMAKE_CURRENT_SOURCE_DIR}/../zlib
#${CMAKE_CURRENT_SOURCE_DIR}/../libpng
${CMAKE_CURRENT_SOURCE_DIR}/../../../../thirdparty/eigen-5.0.0
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.
+98 -38
View File
@@ -2,6 +2,11 @@
#include <iostream>
#include "utils/Utils.h"
#ifdef __ANDROID__
#include <android/log.h>
#endif
#ifdef __EMSCRIPTEN__
AudioPlayerAsync::AudioPlayerAsync() {}
#else
@@ -22,33 +27,34 @@ AudioPlayerAsync::~AudioPlayerAsync() {
}
bool AudioPlayerAsync::init() {
/*if (initialized) return true;
if (initialized) return true;
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
std::cerr << "SDL_InitSubSystem(SDL_INIT_AUDIO) failed: " << SDL_GetError() << std::endl;
FRG::logger() << "SDL_InitSubSystem(SDL_INIT_AUDIO) failed: " << SDL_GetError() << std::endl;
return false;
}
if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0) {
std::cerr << "Mix_OpenAudio failed: " << Mix_GetError() << std::endl;
FRG::logger() << "Mix_OpenAudio failed: " << Mix_GetError() << std::endl;
return false;
}
Mix_AllocateChannels(16);
initialized = true;
FRG::logger() << "AudioPlayerAsync initialized with SDL2_mixer" << std::endl;*/
FRG::logger() << "AudioPlayerAsync initialized with SDL2_mixer" << std::endl;
return true;
}
void AudioPlayerAsync::shutdown() {
if (!initialized) return;
/*
if (currentMusic_) {
Mix_HaltMusic();
Mix_FreeMusic(currentMusic_);
currentMusic_ = nullptr;
}
currentMusicData_.clear();
{
std::lock_guard<std::mutex> lock(soundCacheMutex);
@@ -61,16 +67,20 @@ void AudioPlayerAsync::shutdown() {
Mix_CloseAudio();
SDL_QuitSubSystem(SDL_INIT_AUDIO);
initialized = false;
FRG::logger() << "AudioPlayerAsync shutdown" << std::endl;*/
FRG::logger() << "AudioPlayerAsync shutdown" << std::endl;
}
void AudioPlayerAsync::playSoundAsync(const std::string& filePath, int loops, int channel) {
/*if (!initialized) {
std::cerr << "AudioPlayerAsync not initialized" << std::endl;
if (!initialized) {
FRG::logger() << "AudioPlayerAsync not initialized" << std::endl;
return;
}
if (!soundEnabled_) return;
auto task = [this, filePath, loops, channel]() {
Mix_Chunk* sound = nullptr;
{
@@ -80,11 +90,34 @@ void AudioPlayerAsync::playSoundAsync(const std::string& filePath, int loops, in
sound = it->second;
}
}
if (!sound) {
#ifdef __ANDROID__
__android_log_print(ANDROID_LOG_ERROR, "Game",
"AudioPlayerAsync::playSoundAsync step x2");
std::vector<char> buffer = FRG::readFile(filePath);
if (buffer.empty()) {
__android_log_print(ANDROID_LOG_ERROR, "Game",
"AudioPlayerAsync::playSoundAsync step x3");
FRG::logger() << "Failed to read sound file into buffer: " << filePath << std::endl;
return;
}
__android_log_print(ANDROID_LOG_ERROR, "Game",
"AudioPlayerAsync::playSoundAsync step x4");
SDL_RWops* rw = SDL_RWFromMem(buffer.data(), buffer.size());
if (!rw) {
FRG::logger() << "Failed to create RWops from buffer for " << filePath << ": " << SDL_GetError() << std::endl;
return;
}
sound = Mix_LoadWAV_RW(rw, 1); // 1 means it will free rw automatically
FRG::logger() << "sound = Mix_LoadWAV_RW(rw, 1); just fired " << std::endl;
#else
sound = Mix_LoadWAV(filePath.c_str());
#endif
if (!sound) {
std::cerr << "Failed to load sound " << filePath << ": " << Mix_GetError() << std::endl;
FRG::logger() << "Failed to load sound " << filePath << ": " << Mix_GetError() << std::endl;
return;
}
std::lock_guard<std::mutex> cacheLock(soundCacheMutex);
@@ -93,7 +126,7 @@ void AudioPlayerAsync::playSoundAsync(const std::string& filePath, int loops, in
int result = Mix_PlayChannel(channel, sound, loops);
if (result == -1) {
std::cerr << "Mix_PlayChannel failed: " << Mix_GetError() << std::endl;
FRG::logger() << "Mix_PlayChannel failed: " << Mix_GetError() << std::endl;
}
};
@@ -104,11 +137,11 @@ void AudioPlayerAsync::playSoundAsync(const std::string& filePath, int loops, in
taskQueue.push(std::move(task));
cv.notify_one();
#endif
*/
}
void AudioPlayerAsync::playMusicAsync(const std::string& filePath, int loops) {
/*if (!initialized) return;
if (!initialized) return;
if (filePath == currentTrack)
return;
@@ -122,14 +155,29 @@ void AudioPlayerAsync::playMusicAsync(const std::string& filePath, int loops) {
Mix_FreeMusic(currentMusic_);
currentMusic_ = nullptr;
}
Mix_Music* music = Mix_LoadMUS(filePath.c_str());
currentMusicData_.clear();
Mix_Music* music = nullptr;
#ifdef __ANDROID__
currentMusicData_ = FRG::readFile(filePath);
if (!currentMusicData_.empty()) {
SDL_RWops* rw = SDL_RWFromMem(currentMusicData_.data(), currentMusicData_.size());
if (rw) {
music = Mix_LoadMUS_RW(rw, 1);
}
}
#else
music = Mix_LoadMUS(filePath.c_str());
#endif
if (!music) {
std::cerr << "Failed to load music " << filePath << ": " << Mix_GetError() << std::endl;
FRG::logger() << "Failed to load music " << filePath << ": " << Mix_GetError() << std::endl;
return;
}
if (Mix_PlayMusic(music, loops) == -1) {
std::cerr << "Mix_PlayMusic failed: " << Mix_GetError() << std::endl;
FRG::logger() << "Mix_PlayMusic failed: " << Mix_GetError() << std::endl;
Mix_FreeMusic(music);
currentMusicData_.clear();
return;
}
currentMusic_ = music;
@@ -142,11 +190,11 @@ void AudioPlayerAsync::playMusicAsync(const std::string& filePath, int loops) {
taskQueue.push(std::move(task));
cv.notify_one();
#endif
*/
}
void AudioPlayerAsync::stopMusicAsync() {
/*if (!initialized) return;
if (!initialized) return;
currentTrack = "";
@@ -159,11 +207,11 @@ void AudioPlayerAsync::stopMusicAsync() {
});
cv.notify_one();
#endif
*/
}
void AudioPlayerAsync::pauseMusicAsync() {
/*if (!initialized) return;
if (!initialized) return;
#ifdef __EMSCRIPTEN__
Mix_PauseMusic();
#else
@@ -173,11 +221,11 @@ void AudioPlayerAsync::pauseMusicAsync() {
});
cv.notify_one();
#endif
*/
}
void AudioPlayerAsync::resumeMusicAsync() {
/*if (!initialized) return;
if (!initialized) return;
#ifdef __EMSCRIPTEN__
Mix_ResumeMusic();
#else
@@ -187,11 +235,11 @@ void AudioPlayerAsync::resumeMusicAsync() {
});
cv.notify_one();
#endif
*/
}
void AudioPlayerAsync::setMusicVolume(int volume) {
/*
if (!initialized) return;
volume = std::max(0, std::min(128, volume));
musicVolume_ = volume;
@@ -204,11 +252,11 @@ void AudioPlayerAsync::setMusicVolume(int volume) {
});
cv.notify_one();
#endif
*/
}
void AudioPlayerAsync::setSoundVolume(int volume) {
/*
if (!initialized) return;
volume = std::max(0, std::min(128, volume));
soundVolume_ = volume;
@@ -221,11 +269,11 @@ void AudioPlayerAsync::setSoundVolume(int volume) {
});
cv.notify_one();
#endif
*/
}
void AudioPlayerAsync::crossFadeMusicAsync(const std::string& filePath, int fadeDurationMs, int loops) {
/*if (!initialized) return;
if (!initialized) return;
if (filePath == currentTrack) return;
currentTrack = filePath;
if (!musicEnabled_) return;
@@ -241,14 +289,26 @@ void AudioPlayerAsync::crossFadeMusicAsync(const std::string& filePath, int fade
}
Mix_HaltMusic();
if (currentMusic_) { Mix_FreeMusic(currentMusic_); currentMusic_ = nullptr; }
currentMusicData_.clear();
#endif
Mix_Music* music = nullptr;
#ifdef __ANDROID__
currentMusicData_ = FRG::readFile(filePath);
if (!currentMusicData_.empty()) {
SDL_RWops* rw = SDL_RWFromMem(currentMusicData_.data(), currentMusicData_.size());
if (rw) {
music = Mix_LoadMUS_RW(rw, 1);
}
}
#else
music = Mix_LoadMUS(filePath.c_str());
#endif
Mix_Music* music = Mix_LoadMUS(filePath.c_str());
if (!music) {
std::cerr << "Failed to load music " << filePath << ": " << Mix_GetError() << std::endl;
FRG::logger() << "Failed to load music " << filePath << ": " << Mix_GetError() << std::endl;
return;
}
if (Mix_FadeInMusic(music, loops, fadeDurationMs / 2) == -1) {
std::cerr << "Mix_FadeInMusic failed: " << Mix_GetError() << std::endl;
FRG::logger() << "Mix_FadeInMusic failed: " << Mix_GetError() << std::endl;
Mix_FreeMusic(music);
return;
}
@@ -262,11 +322,11 @@ void AudioPlayerAsync::crossFadeMusicAsync(const std::string& filePath, int fade
taskQueue.push(std::move(task));
cv.notify_one();
#endif
*/
}
void AudioPlayerAsync::crossFadeMusicFromPositionAsync(const std::string& filePath, int fadeDurationMs, int loops) {
/*if (!initialized) return;
if (!initialized) return;
if (filePath == currentTrack) return;
currentTrack = filePath;
if (!musicEnabled_) return;
@@ -288,11 +348,11 @@ void AudioPlayerAsync::crossFadeMusicFromPositionAsync(const std::string& filePa
Mix_Music* music = Mix_LoadMUS(filePath.c_str());
if (!music) {
std::cerr << "Failed to load music " << filePath << ": " << Mix_GetError() << std::endl;
FRG::logger() << "Failed to load music " << filePath << ": " << Mix_GetError() << std::endl;
return;
}
if (Mix_FadeInMusicPos(music, loops, fadeDurationMs / 2, position) == -1) {
std::cerr << "Mix_FadeInMusicPos failed: " << Mix_GetError() << std::endl;
FRG::logger() << "Mix_FadeInMusicPos failed: " << Mix_GetError() << std::endl;
Mix_FreeMusic(music);
return;
}
@@ -306,11 +366,11 @@ void AudioPlayerAsync::crossFadeMusicFromPositionAsync(const std::string& filePa
taskQueue.push(std::move(task));
cv.notify_one();
#endif
*/
}
void AudioPlayerAsync::setMusicEnabled(bool enabled) {
/*if (musicEnabled_ == enabled) return;
if (musicEnabled_ == enabled) return;
musicEnabled_ = enabled;
if (!initialized) return;
@@ -330,7 +390,7 @@ void AudioPlayerAsync::setMusicEnabled(bool enabled) {
currentTrack = ""; // clear so crossFadeMusicAsync doesn't bail early
crossFadeMusicAsync(track);
}
}*/
}
}
void AudioPlayerAsync::setSoundEnabled(bool enabled) {
+9 -5
View File
@@ -1,13 +1,16 @@
#pragma once
#if 0
#ifdef __ANDROID__
#include <SDL_mixer.h>
#include <SDL.h>
#else
#include <SDL2/SDL_mixer.h>
#include <SDL2/SDL.h>
#endif
#include <string>
#include <unordered_map>
#include <memory>
#include <mutex>
#include <SDL2/SDL.h>
#include <vector>
#ifndef __EMSCRIPTEN__
#include <queue>
@@ -53,14 +56,15 @@ private:
std::queue<std::function<void()>> taskQueue;
#endif
bool stop = false;
#if 0
std::unordered_map<std::string, Mix_Chunk*> soundCache;
std::mutex soundCacheMutex;
std::string currentTrack;
Mix_Music* currentMusic_ = nullptr;
#endif
std::vector<char> currentMusicData_;
int musicVolume_ = 128;
int soundVolume_ = 128;
bool musicEnabled_ = true;
+3 -21
View File
@@ -1517,41 +1517,23 @@ namespace FRG
const int uiX = mx;
const int uiY = Environment::projectionHeight - my;
#ifdef __ANDROID__
__android_log_print(ANDROID_LOG_ERROR, "Game",
"Game::onPointerDown step 1");
#endif
menuManager.topUiManager.onTouchDown(fingerId, uiX, uiY);
const bool capturedByTopUi = menuManager.topUiManager.isUiInteractionForFinger(fingerId);
const bool dialogueActive = currentLocation() && currentLocation()->dialogueSystem.isActive();
if (!dialogueActive && !capturedByTopUi) {
#ifdef __ANDROID__
__android_log_print(ANDROID_LOG_ERROR, "Game",
"Game::onPointerDown step 2");
#endif
menuManager.uiManager.onTouchDown(fingerId, uiX, uiY);
}
st.capturedByUi = capturedByTopUi || (!dialogueActive && menuManager.uiManager.isUiInteractionForFinger(fingerId));
activePointers[fingerId] = st;
#ifdef __ANDROID__
__android_log_print(ANDROID_LOG_ERROR, "Game",
"Game::onPointerDown step 3");
#endif
if (st.capturedByUi) {
// UI button / slider / text-field grabbed this press; don't drive
// gameplay or pinch from it.
#ifdef __ANDROID__
__android_log_print(ANDROID_LOG_ERROR, "Game",
"Game::onPointerDown step 4");
#endif
return;
}
#ifdef __ANDROID__
__android_log_print(ANDROID_LOG_ERROR, "Game",
"Game::onPointerDown step 5");
#endif
if (countNonUiPointers() >= 2) {
// Second finger landed on the gameplay area: switch to pinch-zoom
+1 -1
View File
@@ -378,7 +378,7 @@ namespace FRG {
#ifndef EMSCRIPTEN
#if !defined(EMSCRIPTEN) && !defined(__ANDROID__)
uiManager.setTextButtonCallback("menuExitButton", [this](const std::string&) {
audioPlayer_.playSoundAsync("audio/751089__smallconfusion__mechanical-plastic-click-11.ogg");
Environment::exitGameLoop = true;
+1 -1
View File
@@ -206,7 +206,7 @@ int main(int argc, char* argv[]) {
"Shadow Over Bishkek",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
0, 0,
SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN
SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE
);
if (!FRG::Environment::window) {