mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-09 02:07:04 +08:00
feat(audio): integrate OpenAL audio engine with WAV/MP3/FLAC support
This commit is contained in:
@@ -32,6 +32,8 @@ add_subdirectory(third_party/glad)
|
|||||||
|
|
||||||
add_subdirectory(third_party/imgui)
|
add_subdirectory(third_party/imgui)
|
||||||
|
|
||||||
|
add_subdirectory(third_party/dr_libs)
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME})
|
add_executable(${PROJECT_NAME})
|
||||||
|
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
@@ -129,6 +131,7 @@ target_link_libraries(${PROJECT_NAME}
|
|||||||
Freetype::Freetype
|
Freetype::Freetype
|
||||||
tomlplusplus::tomlplusplus
|
tomlplusplus::tomlplusplus
|
||||||
imgui
|
imgui
|
||||||
|
dr_libs
|
||||||
tbb
|
tbb
|
||||||
protobuf::libprotobuf
|
protobuf::libprotobuf
|
||||||
absl::log
|
absl::log
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "Cubed/audio/audio_engine.hpp"
|
||||||
#include "Cubed/gameplay/client_world.hpp"
|
#include "Cubed/gameplay/client_world.hpp"
|
||||||
#include "Cubed/gameplay/network_server.hpp"
|
#include "Cubed/gameplay/network_server.hpp"
|
||||||
#include "Cubed/gameplay/server_world.hpp"
|
#include "Cubed/gameplay/server_world.hpp"
|
||||||
@@ -62,6 +63,8 @@ private:
|
|||||||
|
|
||||||
Window m_window{m_renderer};
|
Window m_window{m_renderer};
|
||||||
|
|
||||||
|
AudioEngine m_audio;
|
||||||
|
|
||||||
inline static double last_time = glfwGetTime();
|
inline static double last_time = glfwGetTime();
|
||||||
inline static double current_time = glfwGetTime();
|
inline static double current_time = glfwGetTime();
|
||||||
inline static double delta_time = 0.0f;
|
inline static double delta_time = 0.0f;
|
||||||
|
|||||||
20
include/Cubed/audio/audio_buffer.hpp
Normal file
20
include/Cubed/audio/audio_buffer.hpp
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Cubed/audio/audio_data.hpp"
|
||||||
|
|
||||||
|
#include <AL/al.h>
|
||||||
|
namespace Cubed {
|
||||||
|
class AudioBuffer {
|
||||||
|
public:
|
||||||
|
AudioBuffer(const AudioData& data);
|
||||||
|
AudioBuffer(const AudioBuffer&) = delete;
|
||||||
|
AudioBuffer(AudioBuffer&&) = delete;
|
||||||
|
AudioBuffer& operator=(const AudioBuffer&) = delete;
|
||||||
|
AudioBuffer& operator=(AudioBuffer&&) = delete;
|
||||||
|
~AudioBuffer();
|
||||||
|
ALuint buffer() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ALuint m_buffer = 0;
|
||||||
|
void set_data(const AudioData& data);
|
||||||
|
};
|
||||||
|
} // namespace Cubed
|
||||||
10
include/Cubed/audio/audio_data.hpp
Normal file
10
include/Cubed/audio/audio_data.hpp
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
namespace Cubed {
|
||||||
|
struct AudioData {
|
||||||
|
std::vector<int16_t> pcm;
|
||||||
|
uint32_t channels;
|
||||||
|
uint32_t sample_rate;
|
||||||
|
};
|
||||||
|
} // namespace Cubed
|
||||||
38
include/Cubed/audio/audio_engine.hpp
Normal file
38
include/Cubed/audio/audio_engine.hpp
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Cubed/audio/audio_source.hpp"
|
||||||
|
#include "Cubed/audio/sound_manager.hpp"
|
||||||
|
|
||||||
|
#include <AL/al.h>
|
||||||
|
#include <AL/alc.h>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
namespace Cubed {
|
||||||
|
|
||||||
|
class ClientWorld;
|
||||||
|
|
||||||
|
class AudioEngine {
|
||||||
|
public:
|
||||||
|
AudioEngine();
|
||||||
|
AudioEngine(const AudioEngine&) = delete;
|
||||||
|
AudioEngine(AudioEngine&&) = delete;
|
||||||
|
AudioEngine& operator=(const AudioEngine&) = delete;
|
||||||
|
AudioEngine& operator=(AudioEngine&&) = delete;
|
||||||
|
~AudioEngine();
|
||||||
|
|
||||||
|
void init();
|
||||||
|
void play_bgm();
|
||||||
|
void update(glm::vec3 listener_pos);
|
||||||
|
|
||||||
|
private:
|
||||||
|
using SourcePool = std::unordered_map<std::string, ALuint>;
|
||||||
|
bool m_init{false};
|
||||||
|
ALCdevice* device{nullptr};
|
||||||
|
ALCcontext* context{nullptr};
|
||||||
|
glm::vec3 listener_pos;
|
||||||
|
std::unique_ptr<AudioSource> m_bgm;
|
||||||
|
SoundManager m_sounds;
|
||||||
|
};
|
||||||
|
} // namespace Cubed
|
||||||
16
include/Cubed/audio/audio_loader.hpp
Normal file
16
include/Cubed/audio/audio_loader.hpp
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Cubed/audio/audio_data.hpp"
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
namespace Cubed {
|
||||||
|
|
||||||
|
class AudioLoader {
|
||||||
|
public:
|
||||||
|
static AudioData load(const std::filesystem::path& path);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static AudioData load_wav(const std::filesystem::path& path);
|
||||||
|
static AudioData load_mp3(const std::filesystem::path& path);
|
||||||
|
static AudioData load_flac(const std::filesystem::path& path);
|
||||||
|
};
|
||||||
|
} // namespace Cubed
|
||||||
26
include/Cubed/audio/audio_source.hpp
Normal file
26
include/Cubed/audio/audio_source.hpp
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Cubed/audio/audio_buffer.hpp"
|
||||||
|
|
||||||
|
#include <AL/al.h>
|
||||||
|
namespace Cubed {
|
||||||
|
|
||||||
|
enum class AudioState { INITIAL, PLAYING, PAUSED, STOPPED };
|
||||||
|
|
||||||
|
class AudioSource {
|
||||||
|
public:
|
||||||
|
AudioSource();
|
||||||
|
~AudioSource();
|
||||||
|
|
||||||
|
void set_buffer(const AudioBuffer& buffer);
|
||||||
|
void set_loop(bool on = true);
|
||||||
|
|
||||||
|
void play();
|
||||||
|
void stop();
|
||||||
|
void pause();
|
||||||
|
|
||||||
|
AudioState state();
|
||||||
|
|
||||||
|
private:
|
||||||
|
ALuint m_source = 0;
|
||||||
|
};
|
||||||
|
} // namespace Cubed
|
||||||
19
include/Cubed/audio/sound_manager.hpp
Normal file
19
include/Cubed/audio/sound_manager.hpp
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Cubed/audio/audio_buffer.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
namespace Cubed {
|
||||||
|
class SoundManager {
|
||||||
|
public:
|
||||||
|
SoundManager();
|
||||||
|
~SoundManager();
|
||||||
|
void load(const std::string& name);
|
||||||
|
const AudioBuffer& get_buffer(const std::string& name) const;
|
||||||
|
void init();
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<std::string, AudioBuffer> m_buffers;
|
||||||
|
};
|
||||||
|
} // namespace Cubed
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "Cubed/audio/audio_engine.hpp"
|
||||||
#include "Cubed/gameplay/block.hpp"
|
#include "Cubed/gameplay/block.hpp"
|
||||||
#include "Cubed/gameplay/chunk_pos.hpp"
|
#include "Cubed/gameplay/chunk_pos.hpp"
|
||||||
#include "Cubed/gameplay/client_chunk.hpp"
|
#include "Cubed/gameplay/client_chunk.hpp"
|
||||||
@@ -40,7 +41,7 @@ struct PlayerRenderData {
|
|||||||
|
|
||||||
class ClientWorld {
|
class ClientWorld {
|
||||||
public:
|
public:
|
||||||
ClientWorld();
|
ClientWorld(AudioEngine& auido);
|
||||||
~ClientWorld();
|
~ClientWorld();
|
||||||
void init(std::string_view player_name,
|
void init(std::string_view player_name,
|
||||||
std::shared_ptr<NetworkClient> client);
|
std::shared_ptr<NetworkClient> client);
|
||||||
@@ -112,6 +113,7 @@ private:
|
|||||||
ClientPlayer m_player;
|
ClientPlayer m_player;
|
||||||
OtherPlayerHashMap m_player_info;
|
OtherPlayerHashMap m_player_info;
|
||||||
ChunkHashMap m_chunks;
|
ChunkHashMap m_chunks;
|
||||||
|
AudioEngine& m_audio;
|
||||||
std::vector<glm::vec4> m_planes;
|
std::vector<glm::vec4> m_planes;
|
||||||
std::jthread m_client_thread;
|
std::jthread m_client_thread;
|
||||||
|
|
||||||
|
|||||||
@@ -44,4 +44,10 @@ target_sources(${PROJECT_NAME}
|
|||||||
gameplay/session.cpp
|
gameplay/session.cpp
|
||||||
gameplay/network_client.cpp
|
gameplay/network_client.cpp
|
||||||
player_renderer.cpp
|
player_renderer.cpp
|
||||||
|
audio/audio_engine.cpp
|
||||||
|
audio/audio_loader.cpp
|
||||||
|
audio/audio_source.cpp
|
||||||
|
audio/audio_buffer.cpp
|
||||||
|
audio/sound_manager.cpp
|
||||||
|
audio/source_pool.cpp
|
||||||
)
|
)
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
#include <imgui_impl_glfw.h>
|
#include <imgui_impl_glfw.h>
|
||||||
namespace Cubed {
|
namespace Cubed {
|
||||||
|
|
||||||
App::App() {}
|
App::App() : m_client_world(m_audio) {}
|
||||||
|
|
||||||
App::~App() {
|
App::~App() {
|
||||||
if (m_client) {
|
if (m_client) {
|
||||||
@@ -59,6 +59,8 @@ void App::init(int argc, char** argv) {
|
|||||||
cursor_enter_callback);
|
cursor_enter_callback);
|
||||||
glfwSetCharCallback(m_window.get_glfw_window(), char_callback);
|
glfwSetCharCallback(m_window.get_glfw_window(), char_callback);
|
||||||
|
|
||||||
|
m_audio.init();
|
||||||
|
|
||||||
ChunkGenerator::init();
|
ChunkGenerator::init();
|
||||||
BlockManager::init();
|
BlockManager::init();
|
||||||
m_renderer.init();
|
m_renderer.init();
|
||||||
@@ -357,6 +359,7 @@ void App::update() {
|
|||||||
m_renderer.update_fov(fov + 5.0f);
|
m_renderer.update_fov(fov + 5.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m_audio.update(m_camera.get_camera_pos());
|
||||||
m_renderer.update(delta_time);
|
m_renderer.update(delta_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
22
src/audio/audio_buffer.cpp
Normal file
22
src/audio/audio_buffer.cpp
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#include "Cubed/audio/audio_buffer.hpp"
|
||||||
|
|
||||||
|
namespace Cubed {
|
||||||
|
AudioBuffer::AudioBuffer(const AudioData& data) {
|
||||||
|
alGenBuffers(1, &m_buffer);
|
||||||
|
set_data(data);
|
||||||
|
}
|
||||||
|
AudioBuffer::~AudioBuffer() { alDeleteBuffers(1, &m_buffer); }
|
||||||
|
|
||||||
|
ALuint AudioBuffer::buffer() const { return m_buffer; }
|
||||||
|
void AudioBuffer::set_data(const AudioData& data) {
|
||||||
|
ALenum format;
|
||||||
|
if (data.channels == 1) {
|
||||||
|
format = AL_FORMAT_MONO16;
|
||||||
|
} else {
|
||||||
|
format = AL_FORMAT_STEREO16;
|
||||||
|
}
|
||||||
|
alBufferData(m_buffer, format, data.pcm.data(), data.pcm.size(),
|
||||||
|
data.sample_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Cubed
|
||||||
46
src/audio/audio_engine.cpp
Normal file
46
src/audio/audio_engine.cpp
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#include "Cubed/audio/audio_engine.hpp"
|
||||||
|
|
||||||
|
#include "Cubed/tools/log.hpp"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
namespace Cubed {
|
||||||
|
AudioEngine::AudioEngine() {};
|
||||||
|
|
||||||
|
AudioEngine::~AudioEngine() {
|
||||||
|
if (!m_init) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_bgm.reset();
|
||||||
|
m_sounds.clear();
|
||||||
|
|
||||||
|
alcMakeContextCurrent(nullptr);
|
||||||
|
alcDestroyContext(context);
|
||||||
|
alcCloseDevice(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioEngine::init() {
|
||||||
|
device = alcOpenDevice(NULL);
|
||||||
|
if (!device) {
|
||||||
|
throw std::runtime_error("Failed to open OpenAL device.");
|
||||||
|
}
|
||||||
|
context = alcCreateContext(device, nullptr);
|
||||||
|
|
||||||
|
if (!context) {
|
||||||
|
throw std::runtime_error("Failed to create OpenAL context.");
|
||||||
|
}
|
||||||
|
alcMakeContextCurrent(context);
|
||||||
|
|
||||||
|
m_sounds.init();
|
||||||
|
m_bgm = std::make_unique<AudioSource>();
|
||||||
|
m_bgm->set_buffer(m_sounds.get_buffer("bgm/bgm001.mp3"));
|
||||||
|
Logger::info("Audio Engine Init Success");
|
||||||
|
|
||||||
|
m_init = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioEngine::play_bgm() { m_bgm->play(); }
|
||||||
|
|
||||||
|
void AudioEngine::update(glm::vec3 listener_pos) {}
|
||||||
|
|
||||||
|
} // namespace Cubed
|
||||||
90
src/audio/audio_loader.cpp
Normal file
90
src/audio/audio_loader.cpp
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
#include "Cubed/audio/audio_loader.hpp"
|
||||||
|
|
||||||
|
#include "Cubed/tools/cubed_assert.hpp"
|
||||||
|
|
||||||
|
#include <dr_flac.h>
|
||||||
|
#include <dr_mp3.h>
|
||||||
|
#include <dr_wav.h>
|
||||||
|
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
namespace Cubed {
|
||||||
|
AudioData AudioLoader::load(const std::filesystem::path& path) {
|
||||||
|
if (!fs::is_regular_file(path)) {
|
||||||
|
std::string err = std::format("Path {} is not a file", path.string());
|
||||||
|
ASSERT_MSG(false, err);
|
||||||
|
throw std::runtime_error(err);
|
||||||
|
}
|
||||||
|
auto ext = path.extension().string();
|
||||||
|
|
||||||
|
if (ext == ".wav") {
|
||||||
|
return load_wav(path);
|
||||||
|
}
|
||||||
|
if (ext == ".mp3") {
|
||||||
|
return load_mp3(path);
|
||||||
|
}
|
||||||
|
if (ext == ".flac") {
|
||||||
|
return load_flac(path);
|
||||||
|
}
|
||||||
|
throw std::runtime_error(std::format("Unsupported audio format {}", ext));
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioData AudioLoader::load_wav(const std::filesystem::path& path) {
|
||||||
|
drwav wav{};
|
||||||
|
if (!drwav_init_file(&wav, path.string().c_str(), nullptr)) {
|
||||||
|
throw std::runtime_error("Failed to open wav");
|
||||||
|
}
|
||||||
|
AudioData data;
|
||||||
|
data.channels = wav.channels;
|
||||||
|
data.sample_rate = wav.sampleRate;
|
||||||
|
data.pcm.resize(wav.totalPCMFrameCount * wav.channels);
|
||||||
|
drwav_read_pcm_frames_s16(&wav, wav.totalPCMFrameCount, data.pcm.data());
|
||||||
|
|
||||||
|
drwav_uninit(&wav);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioData AudioLoader::load_mp3(const std::filesystem::path& path) {
|
||||||
|
drmp3_config config;
|
||||||
|
|
||||||
|
drmp3_uint64 frame_count;
|
||||||
|
|
||||||
|
int16_t* pcm = drmp3_open_file_and_read_pcm_frames_s16(
|
||||||
|
path.string().c_str(), &config, &frame_count, nullptr);
|
||||||
|
|
||||||
|
if (!pcm)
|
||||||
|
throw std::runtime_error("mp3 load failed");
|
||||||
|
|
||||||
|
AudioData data;
|
||||||
|
|
||||||
|
data.channels = config.channels;
|
||||||
|
data.sample_rate = config.sampleRate;
|
||||||
|
|
||||||
|
data.pcm.assign(pcm, pcm + frame_count * config.channels);
|
||||||
|
|
||||||
|
drmp3_free(pcm, nullptr);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioData AudioLoader::load_flac(const std::filesystem::path& path) {
|
||||||
|
drflac_uint64 frame_count;
|
||||||
|
unsigned int channels;
|
||||||
|
unsigned int sample_rate;
|
||||||
|
|
||||||
|
int16_t* pcm = drflac_open_file_and_read_pcm_frames_s16(
|
||||||
|
path.string().c_str(), &channels, &sample_rate, &frame_count, nullptr);
|
||||||
|
|
||||||
|
if (!pcm)
|
||||||
|
throw std::runtime_error("Failed to load flac");
|
||||||
|
|
||||||
|
AudioData data;
|
||||||
|
data.channels = channels;
|
||||||
|
data.sample_rate = sample_rate;
|
||||||
|
|
||||||
|
data.pcm.assign(pcm, pcm + frame_count * channels);
|
||||||
|
|
||||||
|
drflac_free(pcm, nullptr);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
} // namespace Cubed
|
||||||
50
src/audio/audio_source.cpp
Normal file
50
src/audio/audio_source.cpp
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
#include "Cubed/audio/audio_source.hpp"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace Cubed {
|
||||||
|
AudioSource::AudioSource() { alGenSources(1, &m_source); }
|
||||||
|
AudioSource::~AudioSource() {
|
||||||
|
if (m_source != 0) {
|
||||||
|
stop();
|
||||||
|
alDeleteSources(1, &m_source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioSource::set_buffer(const AudioBuffer& buffer) {
|
||||||
|
if (state() == AudioState::PLAYING) {
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
alSourcei(m_source, AL_BUFFER, buffer.buffer());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioSource::set_loop(bool on) {
|
||||||
|
if (on) {
|
||||||
|
alSourcei(m_source, AL_LOOPING, AL_TRUE);
|
||||||
|
} else {
|
||||||
|
alSourcei(m_source, AL_LOOPING, AL_FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioSource::play() { alSourcePlay(m_source); }
|
||||||
|
|
||||||
|
void AudioSource::stop() { alSourceStop(m_source); }
|
||||||
|
void AudioSource::pause() { alSourcePause(m_source); }
|
||||||
|
|
||||||
|
AudioState AudioSource::state() {
|
||||||
|
ALint state;
|
||||||
|
alGetSourcei(m_source, AL_SOURCE_STATE, &state);
|
||||||
|
switch (state) {
|
||||||
|
case AL_INITIAL:
|
||||||
|
return AudioState::INITIAL;
|
||||||
|
case AL_PLAYING:
|
||||||
|
return AudioState::PLAYING;
|
||||||
|
case AL_STOPPED:
|
||||||
|
return AudioState::STOPPED;
|
||||||
|
case AL_PAUSED:
|
||||||
|
return AudioState::PAUSED;
|
||||||
|
}
|
||||||
|
throw std::runtime_error("Invaild state");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Cubed
|
||||||
37
src/audio/sound_manager.cpp
Normal file
37
src/audio/sound_manager.cpp
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#include "Cubed/audio/sound_manager.hpp"
|
||||||
|
|
||||||
|
#include "Cubed/audio/audio_loader.hpp"
|
||||||
|
#include "Cubed/tools/cubed_assert.hpp"
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
namespace Cubed {
|
||||||
|
SoundManager::SoundManager() {}
|
||||||
|
SoundManager::~SoundManager() { clear(); }
|
||||||
|
void SoundManager::clear() { m_buffers.clear(); }
|
||||||
|
void SoundManager::init() { load("bgm/bgm001.mp3"); }
|
||||||
|
|
||||||
|
void SoundManager::load(const std::string& name) {
|
||||||
|
fs::path sound_path{std::string(ASSETS_PATH) + "sound/" + name};
|
||||||
|
try {
|
||||||
|
|
||||||
|
AudioData data = AudioLoader::load(sound_path);
|
||||||
|
auto [_, inserted] = m_buffers.try_emplace(name, data);
|
||||||
|
if (!inserted) {
|
||||||
|
Logger::error("Key Already exist, check the sound name {}", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
Logger::error("Load Sound Error {}", e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const AudioBuffer& SoundManager::get_buffer(const std::string& name) const {
|
||||||
|
auto it = m_buffers.find(name);
|
||||||
|
if (it == m_buffers.end()) {
|
||||||
|
std::string err = std::format("Can't Find Buffer {}", name);
|
||||||
|
ASSERT_MSG(false, err);
|
||||||
|
throw std::runtime_error(err);
|
||||||
|
}
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
} // namespace Cubed
|
||||||
@@ -107,6 +107,10 @@ void DevPanel::show_about_table_bar() {
|
|||||||
ImGui::Text("OpenAl Soft");
|
ImGui::Text("OpenAl Soft");
|
||||||
ImGui::Text("dr_libs");
|
ImGui::Text("dr_libs");
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
ImGui::Text("Music");
|
||||||
|
ImGui::Text("'Find a Peaceful Place' by ROZKOL (Free Music Archive), "
|
||||||
|
"CC BY 4.0.");
|
||||||
|
ImGui::Separator();
|
||||||
ImGui::Text("Special Thanks");
|
ImGui::Text("Special Thanks");
|
||||||
ImGui::Text("TANGERIME");
|
ImGui::Text("TANGERIME");
|
||||||
ImGui::Text("SkyOnPole");
|
ImGui::Text("SkyOnPole");
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ struct ChunkRenderData {
|
|||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
ClientWorld::ClientWorld() : m_player(*this) {}
|
ClientWorld::ClientWorld(AudioEngine& auido)
|
||||||
|
: m_player(*this), m_audio(auido) {}
|
||||||
|
|
||||||
ClientWorld::~ClientWorld() {
|
ClientWorld::~ClientWorld() {
|
||||||
stop_client_thread();
|
stop_client_thread();
|
||||||
@@ -356,6 +357,7 @@ void ClientWorld::init(std::string_view player_name,
|
|||||||
// request login
|
// request login
|
||||||
Logger::info("Send Login Request");
|
Logger::info("Send Login Request");
|
||||||
m_client->send(make_packet(req), 0);
|
m_client->send(make_packet(req), 0);
|
||||||
|
m_audio.play_bgm();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientWorld::start_client_thread(std::string_view uuid) {
|
void ClientWorld::start_client_thread(std::string_view uuid) {
|
||||||
|
|||||||
Reference in New Issue
Block a user