Musique de fond (#44)
All checks were successful
Linux arm64 / Build (push) Successful in 5m30s
All checks were successful
Linux arm64 / Build (push) Successful in 5m30s
Fix #7 Reviewed-on: #44 Co-authored-by: Persson-dev <sim16.prib@gmail.com> Co-committed-by: Persson-dev <sim16.prib@gmail.com>
This commit was merged in pull request #44.
This commit is contained in:
BIN
assets/sessionD.wav
Normal file
BIN
assets/sessionD.wav
Normal file
Binary file not shown.
@@ -158,6 +158,14 @@ class DataBuffer {
|
||||
return m_Buffer.data();
|
||||
}
|
||||
|
||||
std::vector<std::uint8_t>& GetVector() {
|
||||
return m_Buffer;
|
||||
}
|
||||
|
||||
const std::vector<std::uint8_t>& GetVector() const {
|
||||
return m_Buffer;
|
||||
}
|
||||
|
||||
std::size_t GetReadOffset() const {
|
||||
return m_ReadOffset;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@ class ClientListener {
|
||||
virtual void OnSpectatorChange(game::PlayerID player) {}
|
||||
virtual void OnPlayerShoot(PlayerID player, const Vec3f& position, float yaw, float pitch) {}
|
||||
virtual void OnGameConfigUpdate() {}
|
||||
virtual void OnGameJoin() {}
|
||||
virtual void OnGameLeave() {}
|
||||
};
|
||||
|
||||
} // namespace game
|
||||
|
||||
25
include/client/audio/AudioBuffer.h
Normal file
25
include/client/audio/AudioBuffer.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "blitz/common/DataBuffer.h"
|
||||
#include "blitz/common/NonCopyable.h"
|
||||
#include "blitz/maths/Vector.h"
|
||||
#include "client/audio/AudioLoader.h"
|
||||
|
||||
namespace blitz {
|
||||
namespace audio {
|
||||
|
||||
class AudioBuffer : private NonCopyable {
|
||||
private:
|
||||
unsigned int m_ID;
|
||||
|
||||
public:
|
||||
AudioBuffer(AudioData&& audioData);
|
||||
~AudioBuffer();
|
||||
|
||||
unsigned int GetID() const {
|
||||
return m_ID;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace audio
|
||||
} // namespace blitz
|
||||
21
include/client/audio/AudioListener.h
Normal file
21
include/client/audio/AudioListener.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include "blitz/common/NonCopyable.h"
|
||||
#include "blitz/maths/Vector.h"
|
||||
|
||||
namespace blitz {
|
||||
namespace audio {
|
||||
|
||||
class AudioListener : private NonCopyable {
|
||||
public:
|
||||
AudioListener();
|
||||
~AudioListener();
|
||||
|
||||
void SetGain(float a_Gain);
|
||||
void SetPosition(const Vec3f& a_Position);
|
||||
void SetVelocity(const Vec3f& a_Velocity);
|
||||
void SetOrientation(const Vec3f& a_Orientation, const Vec3f& a_Up);
|
||||
};
|
||||
|
||||
} // namespace audio
|
||||
} // namespace blitz
|
||||
24
include/client/audio/AudioLoader.h
Normal file
24
include/client/audio/AudioLoader.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "blitz/common/DataBuffer.h"
|
||||
|
||||
namespace blitz {
|
||||
namespace audio {
|
||||
|
||||
enum AudioFormat { afMono8 = 0, afMono16, afStereo8, afStereo16 };
|
||||
|
||||
struct AudioData {
|
||||
DataBuffer m_Buffer;
|
||||
AudioFormat m_Format;
|
||||
std::uint32_t m_Frequency;
|
||||
};
|
||||
|
||||
namespace AudioLoader {
|
||||
|
||||
// files should be 8 or 16 bits wav
|
||||
AudioData LoadAudioFile(const std::string& filePath);
|
||||
|
||||
}; // namespace AudioLoader
|
||||
|
||||
} // namespace audio
|
||||
} // namespace blitz
|
||||
33
include/client/audio/AudioManager.h
Normal file
33
include/client/audio/AudioManager.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include "blitz/game/Listeners.h"
|
||||
#include "client/audio/AudioListener.h"
|
||||
#include "client/audio/AudioSource.h"
|
||||
|
||||
namespace blitz {
|
||||
|
||||
class Client;
|
||||
|
||||
namespace audio {
|
||||
|
||||
class AudioManager : public game::ClientListener {
|
||||
private:
|
||||
Client* m_Client;
|
||||
AudioListener m_Listener;
|
||||
AudioSourcePtr m_MenuMusic;
|
||||
std::vector<AudioSourcePtr> m_Sources;
|
||||
|
||||
public:
|
||||
AudioManager(Client* client);
|
||||
~AudioManager();
|
||||
|
||||
virtual void OnGameJoin() override;
|
||||
virtual void OnGameLeave() override;
|
||||
|
||||
private:
|
||||
void InitMainMenuMusic();
|
||||
};
|
||||
|
||||
} // namespace audio
|
||||
|
||||
} // namespace blitz
|
||||
42
include/client/audio/AudioSource.h
Normal file
42
include/client/audio/AudioSource.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include "blitz/common/NonCopyable.h"
|
||||
#include "blitz/maths/Vector.h"
|
||||
#include "client/audio/AudioBuffer.h"
|
||||
#include <memory>
|
||||
|
||||
namespace blitz {
|
||||
namespace audio {
|
||||
|
||||
typedef std::unique_ptr<AudioBuffer> AudioBufferPtr;
|
||||
|
||||
class AudioSource : NonCopyable {
|
||||
private:
|
||||
unsigned int m_ID;
|
||||
AudioBufferPtr m_Buffer;
|
||||
|
||||
public:
|
||||
enum SourceState { ssInitial = 0, ssPlaying, ssPaused, ssStopped };
|
||||
|
||||
AudioSource();
|
||||
~AudioSource();
|
||||
|
||||
void SetGain(float a_Gain);
|
||||
void SetPitch(float a_Pitch);
|
||||
void SetPosition(const Vec3f& a_Position);
|
||||
void SetDirection(const Vec3f& a_Direction);
|
||||
void SetVelocity(const Vec3f& a_Velocity);
|
||||
void SetLooping(bool a_Looping);
|
||||
void SetBuffer(AudioBufferPtr&& a_Buffer);
|
||||
|
||||
SourceState GetSourceState() const;
|
||||
|
||||
void Play();
|
||||
void Pause();
|
||||
void Stop();
|
||||
};
|
||||
|
||||
typedef std::unique_ptr<AudioSource> AudioSourcePtr;
|
||||
|
||||
} // namespace audio
|
||||
} // namespace blitz
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "blitz/network/Network.h"
|
||||
#include "client/Client.h"
|
||||
#include "client/audio/AudioManager.h"
|
||||
#include "client/display/Display.h"
|
||||
#include "client/render/MainRenderer.h"
|
||||
|
||||
@@ -12,6 +13,7 @@ int main(int argc, char** argv) {
|
||||
return EXIT_FAILURE;
|
||||
|
||||
blitz::render::MainRenderer renderer(&client);
|
||||
blitz::audio::AudioManager audioManager(&client);
|
||||
blitz::network::NetworkInitializer network;
|
||||
|
||||
while (!display.IsCloseRequested()) {
|
||||
|
||||
@@ -13,7 +13,7 @@ DataBuffer GetAsset(const std::string& fileName) {
|
||||
|
||||
SDL_RWops* io = SDL_RWFromFile(fileName.c_str(), "rb");
|
||||
|
||||
assert(io != nullptr);
|
||||
assert(io != nullptr && "Can't find the requested file !");
|
||||
|
||||
std::int64_t bufferSize = SDL_RWsize(io);
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "client/Client.h"
|
||||
|
||||
#include "blitz/misc/Log.h"
|
||||
#include "blitz/protocol/packets/ChatPacket.h"
|
||||
#include "blitz/protocol/packets/DisconnectPacket.h"
|
||||
#include "blitz/protocol/packets/PlayerPositionAndRotationPacket.h"
|
||||
@@ -17,11 +18,13 @@ Client::Client() :
|
||||
m_Game(std::make_unique<client::ClientGame>(this, m_Connexion->GetDispatcher())) {}
|
||||
|
||||
Client::~Client() {
|
||||
protocol::DisconnectPacket packet("Client");
|
||||
m_Connexion->SendPacket(&packet);
|
||||
Disconnect();
|
||||
}
|
||||
|
||||
void Client::Update() {
|
||||
if (m_Connexion->GetSocketStatus() != network::TCPSocket::Status::Connected)
|
||||
return;
|
||||
|
||||
if (m_Connexion->UpdateSocket()) {
|
||||
static std::uint64_t lastTime = utils::GetTime();
|
||||
|
||||
@@ -29,6 +32,8 @@ void Client::Update() {
|
||||
m_Game->Tick(utils::GetTime() - lastTime);
|
||||
|
||||
lastTime = utils::GetTime();
|
||||
} else {
|
||||
Disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,11 +62,21 @@ bool Client::CreateGame(std::uint16_t port, const std::string& pseudo) {
|
||||
}
|
||||
|
||||
void Client::Disconnect() {
|
||||
if (m_Connexion->GetSocketStatus() != network::TCPSocket::Status::Connected)
|
||||
return;
|
||||
|
||||
protocol::DisconnectPacket packet("Client wants to leave !");
|
||||
m_Connexion->SendPacket(&packet);
|
||||
|
||||
utils::LOGD("[Client] Disconnected !");
|
||||
|
||||
if (m_Server) {
|
||||
m_Server->Stop();
|
||||
}
|
||||
m_Connexion->CloseConnection();
|
||||
Reset();
|
||||
|
||||
NotifyListeners(&game::ClientListener::OnGameLeave);
|
||||
}
|
||||
|
||||
void Client::Reset() {
|
||||
|
||||
@@ -53,6 +53,7 @@ void ClientConnexion::HandlePacket(const protocol::ChatPacket* packet) {
|
||||
|
||||
void ClientConnexion::HandlePacket(const protocol::DisconnectPacket* packet) {
|
||||
utils::LOG("Disconnected !");
|
||||
m_Client->NotifyListeners(&game::ClientListener::OnGameLeave);
|
||||
}
|
||||
|
||||
void ClientConnexion::HandlePacket(const protocol::KeepAlivePacket* packet) {
|
||||
@@ -62,6 +63,7 @@ void ClientConnexion::HandlePacket(const protocol::KeepAlivePacket* packet) {
|
||||
|
||||
void ClientConnexion::HandlePacket(const protocol::ConnexionInfoPacket* packet) {
|
||||
m_PlayerID = packet->GetConnectionID();
|
||||
utils::LOGD("[ClientConnexion] Logging in with pseudo " + m_PlayerName + " ...");
|
||||
Login(m_PlayerName);
|
||||
}
|
||||
|
||||
|
||||
27
src/client/audio/AudioBuffer.cpp
Normal file
27
src/client/audio/AudioBuffer.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#include "client/audio/AudioBuffer.h"
|
||||
|
||||
#include <AL/al.h>
|
||||
|
||||
namespace blitz {
|
||||
namespace audio {
|
||||
|
||||
static const std::vector<unsigned int> AudioFormats = {
|
||||
AL_FORMAT_MONO8,
|
||||
AL_FORMAT_MONO16,
|
||||
AL_FORMAT_STEREO8,
|
||||
AL_FORMAT_STEREO16,
|
||||
};
|
||||
|
||||
AudioBuffer::AudioBuffer(AudioData&& audioData) {
|
||||
alGenBuffers(1, &m_ID);
|
||||
alBufferData(m_ID, AudioFormats[audioData.m_Format], audioData.m_Buffer.data() + audioData.m_Buffer.GetReadOffset(),
|
||||
audioData.m_Buffer.GetSize() - audioData.m_Buffer.GetReadOffset(), static_cast<ALsizei>(audioData.m_Frequency));
|
||||
}
|
||||
|
||||
AudioBuffer::~AudioBuffer() {
|
||||
alDeleteBuffers(1, &m_ID);
|
||||
m_ID = 0;
|
||||
}
|
||||
|
||||
} // namespace audio
|
||||
} // namespace blitz
|
||||
47
src/client/audio/AudioListener.cpp
Normal file
47
src/client/audio/AudioListener.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
#include "client/audio/AudioListener.h"
|
||||
|
||||
#include "blitz/misc/Log.h"
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
|
||||
namespace blitz {
|
||||
namespace audio {
|
||||
|
||||
AudioListener::AudioListener() {
|
||||
ALCdevice* device = alcOpenDevice(nullptr);
|
||||
|
||||
if (device) {
|
||||
ALCcontext* context = alcCreateContext(device, nullptr);
|
||||
alcMakeContextCurrent(context);
|
||||
} else {
|
||||
utils::LOGE("[AudioListener] Can't initialize sound !");
|
||||
}
|
||||
}
|
||||
|
||||
AudioListener::~AudioListener() {
|
||||
ALCcontext* context = alcGetCurrentContext();
|
||||
ALCdevice* device = alcGetContextsDevice(context);
|
||||
alcMakeContextCurrent(NULL);
|
||||
alcDestroyContext(context);
|
||||
alcCloseDevice(device);
|
||||
}
|
||||
|
||||
void AudioListener::SetGain(float a_Gain) {
|
||||
alListenerf(AL_GAIN, a_Gain);
|
||||
}
|
||||
|
||||
void AudioListener::SetPosition(const Vec3f& a_Position) {
|
||||
alListener3f(AL_POSITION, a_Position.x, a_Position.y, a_Position.z);
|
||||
}
|
||||
|
||||
void AudioListener::SetVelocity(const Vec3f& a_Velocity) {
|
||||
alListener3f(AL_VELOCITY, a_Velocity.x, a_Velocity.y, a_Velocity.z);
|
||||
}
|
||||
|
||||
void AudioListener::SetOrientation(const Vec3f& a_Orientation, const Vec3f& a_Up) {
|
||||
Vec3f data[] = {a_Orientation, a_Up};
|
||||
alListenerfv(AL_ORIENTATION, reinterpret_cast<float*>(data));
|
||||
}
|
||||
|
||||
} // namespace audio
|
||||
} // namespace blitz
|
||||
51
src/client/audio/AudioLoader.cpp
Normal file
51
src/client/audio/AudioLoader.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
#include "client/audio/AudioLoader.h"
|
||||
|
||||
#include "blitz/misc/Log.h"
|
||||
#include "client/AssetsManager.h"
|
||||
|
||||
namespace blitz {
|
||||
namespace audio {
|
||||
|
||||
namespace AudioLoader {
|
||||
|
||||
struct WavHeader {
|
||||
/* RIFF Chunk Descriptor */
|
||||
uint8_t RIFF[4]; // RIFF Header Magic header
|
||||
uint32_t ChunkSize; // RIFF Chunk Size
|
||||
uint8_t WAVE[4]; // WAVE Header
|
||||
/* "fmt" sub-chunk */
|
||||
uint8_t FMT[4]; // FMT header
|
||||
uint32_t Subchunk1Size; // Size of the fmt chunk
|
||||
uint16_t AudioFormat; // Audio format 1=PCM,6=mulaw,7=alaw, 257=IBM Mu-Law, 258=IBM A-Law, 259=ADPCM
|
||||
uint16_t NumOfChan; // Number of channels 1=Mono 2=Sterio
|
||||
uint32_t SamplesPerSec; // Sampling Frequency in Hz
|
||||
uint32_t BytesPerSec; // bytes per second
|
||||
uint16_t BlockAlign; // 2=16-bit mono, 4=16-bit stereo
|
||||
uint16_t BitsPerSample; // Number of bits per sample
|
||||
/* "data" sub-chunk */
|
||||
uint8_t Subchunk2ID[4]; // "data" string
|
||||
uint32_t Subchunk2Size; // Sampled data length
|
||||
};
|
||||
|
||||
AudioData LoadAudioFile(const std::string& filePath) {
|
||||
|
||||
DataBuffer fileBuffer = utils::AssetsManager::GetAsset(filePath);
|
||||
|
||||
WavHeader wavHeader;
|
||||
fileBuffer >> wavHeader;
|
||||
|
||||
if (wavHeader.Subchunk2Size == 0) {
|
||||
utils::LOGE("[AudioLoader] Failed to load sound " + filePath + " !");
|
||||
}
|
||||
|
||||
fileBuffer.Resize(fileBuffer.GetReadOffset() + wavHeader.Subchunk2Size);
|
||||
|
||||
int audioFormat = (wavHeader.NumOfChan - 1) * 2 + (wavHeader.BitsPerSample / 8) - 1;
|
||||
|
||||
return {fileBuffer, AudioFormat(audioFormat), wavHeader.SamplesPerSec};
|
||||
}
|
||||
|
||||
}; // namespace AudioLoader
|
||||
|
||||
} // namespace audio
|
||||
} // namespace blitz
|
||||
43
src/client/audio/AudioManager.cpp
Normal file
43
src/client/audio/AudioManager.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
#include "client/audio/AudioManager.h"
|
||||
|
||||
#include "client/Client.h"
|
||||
#include "client/audio/AudioBuffer.h"
|
||||
|
||||
namespace blitz {
|
||||
namespace audio {
|
||||
|
||||
AudioManager::AudioManager(Client* client) : m_Client(client) {
|
||||
m_Listener.SetPosition({});
|
||||
m_Listener.SetVelocity({});
|
||||
m_Listener.SetGain(1.0f);
|
||||
m_Listener.SetOrientation(blitz::Vec3f{0.0, 0.0, 0.0}, blitz::Vec3f{0.0, 1.0, 0.0});
|
||||
InitMainMenuMusic();
|
||||
m_MenuMusic->Play();
|
||||
m_Client->BindListener(this);
|
||||
}
|
||||
|
||||
void AudioManager::InitMainMenuMusic() {
|
||||
AudioData audioData = AudioLoader::LoadAudioFile("sessionD.wav");
|
||||
AudioBufferPtr audioBuffer = std::make_unique<AudioBuffer>(std::move(audioData));
|
||||
m_MenuMusic = std::make_unique<AudioSource>();
|
||||
m_MenuMusic->SetBuffer(std::move(audioBuffer));
|
||||
m_MenuMusic->SetPosition({});
|
||||
m_MenuMusic->SetVelocity({});
|
||||
m_MenuMusic->SetPitch(1.0f);
|
||||
m_MenuMusic->SetLooping(true);
|
||||
}
|
||||
|
||||
void AudioManager::OnGameJoin() {
|
||||
m_MenuMusic->Stop();
|
||||
}
|
||||
|
||||
void AudioManager::OnGameLeave() {
|
||||
m_MenuMusic->Play();
|
||||
}
|
||||
|
||||
AudioManager::~AudioManager() {
|
||||
m_Client->UnbindListener(this);
|
||||
}
|
||||
|
||||
} // namespace audio
|
||||
} // namespace blitz
|
||||
66
src/client/audio/AudioSource.cpp
Normal file
66
src/client/audio/AudioSource.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
#include "client/audio/AudioSource.h"
|
||||
|
||||
#include <AL/al.h>
|
||||
|
||||
namespace blitz {
|
||||
namespace audio {
|
||||
|
||||
AudioSource::AudioSource() {
|
||||
alGenSources(1, &m_ID);
|
||||
}
|
||||
|
||||
AudioSource::~AudioSource() {
|
||||
alDeleteSources(1, &m_ID);
|
||||
}
|
||||
|
||||
void AudioSource::SetGain(float a_Gain) {
|
||||
alSourcef(m_ID, AL_GAIN, a_Gain);
|
||||
}
|
||||
|
||||
void AudioSource::SetPitch(float a_Pitch) {
|
||||
alSourcef(m_ID, AL_PITCH, a_Pitch);
|
||||
}
|
||||
|
||||
void AudioSource::SetPosition(const Vec3f& a_Position) {
|
||||
alSource3f(m_ID, AL_POSITION, a_Position.x, a_Position.y, a_Position.z);
|
||||
}
|
||||
|
||||
void AudioSource::SetDirection(const Vec3f& a_Direction) {
|
||||
alSource3f(m_ID, AL_DIRECTION, a_Direction.x, a_Direction.y, a_Direction.z);
|
||||
}
|
||||
|
||||
void AudioSource::SetVelocity(const Vec3f& a_Velocity) {
|
||||
alSource3f(m_ID, AL_VELOCITY, a_Velocity.x, a_Velocity.y, a_Velocity.z);
|
||||
}
|
||||
|
||||
void AudioSource::SetLooping(bool a_Looping) {
|
||||
alSourcei(m_ID, AL_LOOPING, a_Looping);
|
||||
}
|
||||
|
||||
void AudioSource::SetBuffer(AudioBufferPtr&& a_Buffer) {
|
||||
alSourcei(m_ID, AL_BUFFER, a_Buffer->GetID());
|
||||
m_Buffer = std::move(a_Buffer);
|
||||
}
|
||||
|
||||
AudioSource::SourceState AudioSource::GetSourceState() const {
|
||||
int state;
|
||||
|
||||
alGetSourcei(m_ID, AL_SOURCE_STATE, &state);
|
||||
|
||||
return SourceState(state - AL_INITIAL);
|
||||
}
|
||||
|
||||
void AudioSource::Play() {
|
||||
alSourcePlay(m_ID);
|
||||
}
|
||||
|
||||
void AudioSource::Pause() {
|
||||
alSourcePause(m_ID);
|
||||
}
|
||||
|
||||
void AudioSource::Stop() {
|
||||
alSourceStop(m_ID);
|
||||
}
|
||||
|
||||
} // namespace audio
|
||||
} // namespace blitz
|
||||
@@ -53,6 +53,7 @@ void ClientGame::HandlePacket(const protocol::PlayerJoinPacket* packet) {
|
||||
// Initialize camera
|
||||
if (packet->GetPlayerID() == m_Client->GetPlayerID()) {
|
||||
m_Client->NotifyListeners(&game::ClientListener::OnSpectatorChange, packet->GetPlayerID());
|
||||
m_Client->NotifyListeners(&game::ClientListener::OnGameJoin);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ if is_plat("linux") and is_arch("arm64-v8a") then
|
||||
end
|
||||
|
||||
add_requires("libsdl 2.28.3", {configs = {sdlmain = false}})
|
||||
add_requires(opengl, "assimp 5.3.1", "nlohmann_json")
|
||||
add_requires(opengl, "assimp 5.3.1", "nlohmann_json", "openal-soft")
|
||||
|
||||
|
||||
-- Client binary (default)
|
||||
@@ -26,7 +26,7 @@ target("BlitzClient")
|
||||
|
||||
-- Libraries
|
||||
add_deps("Blitz")
|
||||
add_packages("libsdl", opengl, "assimp", "nlohmann_json")
|
||||
add_packages("libsdl", opengl, "assimp", "nlohmann_json", "openal-soft")
|
||||
|
||||
add_includedirs("../libs", "../libs/imgui")
|
||||
add_files("../libs/imgui/**.cpp")
|
||||
|
||||
Reference in New Issue
Block a user