0
0
mirror of https://github.com/Nimac0/SDL_Minigame synced 2026-01-12 06:53:41 +00:00

Merge branch 'UpdateSoundMaps' into dev

This commit is contained in:
Nimac0 2025-01-28 22:51:29 +01:00
commit e0c35aa690
9 changed files with 128 additions and 60 deletions

View File

@ -12,10 +12,10 @@ set(ENGINE_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(BUILD_SHARED_LIBS FALSE) set(BUILD_SHARED_LIBS FALSE)
set(SDL2MIXER_VENDORED ON) set(SDLMIXER_VENDORED ON)
set(SDL2TTF_VENDORED ON) set(SDLTTF_VENDORED ON)
set(SDL2_SOURCE_DIR ${ENGINE_SOURCE_DIR}/extern/SDL”) set(SDL_SOURCE_DIR ${ENGINE_SOURCE_DIR}/extern/SDL”)
set(TMXLITE_STATIC_LIB TRUE) set(TMXLITE_STATIC_LIB TRUE)

View File

@ -6,6 +6,7 @@
#include <functional> #include <functional>
#include "Entity.h" #include "Entity.h"
#include "SoundEffects.h"
class Vector2D; class Vector2D;
class Manager; class Manager;
@ -30,17 +31,7 @@ public:
PowerupType calculateType(); PowerupType calculateType();
// sound management
void addSoundEffect(std::string id, const char* path);
void addMusic(std::string id, const char* path);
Mix_Chunk* getSound(std::string id);
Mix_Music* getMusic(std::string id);
private: private:
Manager* man; Manager* man;
std::map<std::string, Mix_Chunk*> soundEffects;
std::map<std::string, Mix_Music*> music;
}; };

View File

@ -0,0 +1,3 @@
#pragma once
enum class BackgroundMusic;

View File

@ -3,6 +3,7 @@
#include "Component.h" #include "Component.h"
#include "Vector2D.h" #include "Vector2D.h"
#include "Constants.h" #include "Constants.h"
#include "SoundEffects.h"
class TransformComponent; class TransformComponent;
@ -11,8 +12,8 @@ class ProjectileComponent : public Component
//can maybe be split in separate .cpp file //can maybe be split in separate .cpp file
public: public:
ProjectileComponent(int range, int speed, Vector2D direction, Entity* owner) ProjectileComponent(int range, int speed, Vector2D direction, Entity* owner, SoundEffects soundEffect)
: range(range), speed(speed), direction(direction), owner(owner) {} : range(range), speed(speed), direction(direction), owner(owner), soundEffect(soundEffect) {}
~ProjectileComponent() {} ~ProjectileComponent() {}
void init() override; void init() override;
@ -28,4 +29,6 @@ private:
Entity* owner = nullptr; Entity* owner = nullptr;
Vector2D direction; Vector2D direction;
SoundEffects soundEffect;
}; };

3
include/SoundEffects.h Normal file
View File

@ -0,0 +1,3 @@
#pragma once
enum class SoundEffects;

View File

@ -6,6 +6,8 @@
#include "ECS.h" #include "ECS.h"
#include "TextureManager.h" #include "TextureManager.h"
#include "BackgroundMusic.h"
#include "SoundEffects.h"
class GameInternal; class GameInternal;
@ -17,8 +19,17 @@ class GameInternal;
*/ */
class SoundManager class SoundManager
{ {
public: public:
SoundManager() {}
SoundManager() {
if (this_instance == nullptr) {
this_instance = this;
}
else {
throw std::runtime_error("SoundManager instance already exists!");
}
}
~SoundManager() { ~SoundManager() {
for (auto& it : this->sound_cache) { for (auto& it : this->sound_cache) {
Mix_FreeChunk(it.second); Mix_FreeChunk(it.second);
@ -32,35 +43,32 @@ class SoundManager
SoundManager(SoundManager const&) = delete; SoundManager(SoundManager const&) = delete;
void operator=(SoundManager const&) = delete; void operator=(SoundManager const&) = delete;
std::map<const char*, Mix_Music*> music_cache; /*
std::map<const char*, Mix_Chunk*> sound_cache;
/*!
* \brief Loads music from a file (mp3) * \brief Loads music from a file (mp3)
* \returns a pointer to Mix_Music * \returns a pointer to Mix_Music
* \sa AssetManager::AddMusic(std::string id, const char* path) * \sa AssetManager::AddMusic(std::string id, const char* path)
*/
Mix_Music* loadMusic(const char* fileName); Mix_Music* loadMusic(const char* fileName);
/*! /*!
* \brief Loads sound effects from a file (wav) * \brief Loads sound effects from a file (wav)
* \returns a pointer to Mix_Chunk * \returns a pointer to Mix_Chunk
* \sa AssetManager::AddSound(std::string id, const char* path) * \sa AssetManager::AddSound(std::string id, const char* path)
*/
Mix_Chunk* loadSound(const char* fileName);
Mix_Chunk* loadSound(const char* fileName);
*/
/*! /*!
* \brief Handles playing of sound effects * \brief Handles playing of sound effects
* *
* Handles if sounds can overlap, how often they can loop, as well as the volume at which the specified sound effect should play * Handles if sounds can overlap, how often they can loop, as well as the volume at which the specified sound effect should play
* and on which channel the soundeffect should play. * and on which channel the soundeffect should play.
*/ */
static void playSound(GameInternal* game, std::string sound, bool canOverlap, int loops, int volume, int channel); static void playSound(SoundEffects sound, bool canOverlap, int loops, int volume, int channel);
/*! /*!
* \brief Handles playing of music * \brief Handles playing of music
* *
* Handles how often track can loop, as well as the volume at which the specified track should play and if it fades in. * Handles how often track can loop, as well as the volume at which the specified track should play and if it fades in.
*/ */
static void playMusic(GameInternal* game, std::string sound, int loops, int volume, int ms); static void playMusic(BackgroundMusic sound, int loops, int volume, int milliseconds);
static void setSoundVolume(int volume, int channel); //!< Volume handling for sound effects (either all or on a specific channel) static void setSoundVolume(int volume, int channel); //!< Volume handling for sound effects (either all or on a specific channel)
static void setMusicVolume(int volume); //!< Volume handling for music track static void setMusicVolume(int volume); //!< Volume handling for music track
@ -73,5 +81,29 @@ class SoundManager
static void fadeOutMusic(int ms); //!< Handles fading out a music track static void fadeOutMusic(int ms); //!< Handles fading out a music track
/*!
* \brief Initializes sound-effects and adds them to a cache
*
*/
static void addSoundEffects(const std::map<SoundEffects, const char*> &effects);
/*!
* \brief Initializes background-music and adds them to a cache
*
*/
static void addBackgroundMusic(const std::map<BackgroundMusic, const char*> &backgroundMusic);
static SoundManager* getInstance() {
return this_instance;
}
private: private:
std::map<BackgroundMusic, Mix_Music*> music_cache;
std::map<SoundEffects, Mix_Chunk*> sound_cache;
static SoundManager* this_instance;
static void addSingleBackgroundMusic(BackgroundMusic backgroundMusic, const char* path);
static void addSingleSoundEffect(SoundEffects soundEffect, const char* path);
}; };

View File

@ -22,26 +22,6 @@ AssetManager::AssetManager(Manager* manager) : man(manager) {}
AssetManager::~AssetManager() {} AssetManager::~AssetManager() {}
void AssetManager::addSoundEffect(std::string id, const char* path)
{
soundEffects.emplace(id, this->man->getGame()->soundManager->loadSound(path));
}
void AssetManager::addMusic(std::string id, const char* path)
{
music.emplace(id, this->man->getGame()->soundManager->loadMusic(path));
}
Mix_Chunk* AssetManager::getSound(std::string id) {
return soundEffects.at(id);
}
Mix_Music* AssetManager::getMusic(std::string id)
{
return music.at(id);
}
void AssetManager::createPowerup(Vector2D pos, std::function<void (Entity*)> pickupFunc, Textures texture) { void AssetManager::createPowerup(Vector2D pos, std::function<void (Entity*)> pickupFunc, Textures texture) {
auto& powerups(man->addEntity()); auto& powerups(man->addEntity());

View File

@ -14,7 +14,7 @@ void ProjectileComponent::init()
{ {
transformComponent = &entity->getComponent<TransformComponent>(); transformComponent = &entity->getComponent<TransformComponent>();
transformComponent->direction = direction; transformComponent->direction = direction;
SoundManager::playSound(this->entity->getManager().getGame(), "throw_egg", true, PLAY_ONCE, MAX_VOLUME, -1); SoundManager::playSound(this->soundEffect, true, PLAY_ONCE, MAX_VOLUME, -1);
} }
void ProjectileComponent::update(uint_fast16_t diffTime) void ProjectileComponent::update(uint_fast16_t diffTime)

View File

@ -8,9 +8,10 @@
#include "GameInternal.h" #include "GameInternal.h"
#include "AssetManager.h" #include "AssetManager.h"
/*
Mix_Music* SoundManager::loadMusic(const char* fileName) Mix_Music* SoundManager::loadMusic(const char* fileName)
{ {
auto it = this->music_cache.find(fileName); //auto it = this->music_cache.find(fileName);
if (it != this->music_cache.end()) { if (it != this->music_cache.end()) {
return it->second; return it->second;
@ -48,14 +49,21 @@ Mix_Chunk* SoundManager::loadSound(const char* fileName)
return sound; return sound;
} }
void SoundManager::playSound(GameInternal* game, std::string sound, bool canOverlap, int loops, int volume, int channel) */
void SoundManager::playSound(SoundEffects sound, bool canOverlap, int loops, int volume, int channel)
{ {
if (!this_instance->sound_cache.contains(sound)) {
std::cerr << "Error playing Sound-Effect: sound effect not found" << std::endl;
return;
}
if(!canOverlap) if(!canOverlap)
{ {
// dev needs to specify a channel for this check to work, if they set it to -1 and let sdl pick the first available // dev needs to specify a channel for this check to work, if they set it to -1 and let sdl pick the first available
// channel mix_getchunk() won't work // channel mix_getchunk() won't work
if (Mix_Playing(channel) != 0 && if (Mix_Playing(channel) != 0 &&
Mix_GetChunk(channel) == game->assets->getSound(sound) && Mix_GetChunk(channel) == this_instance->sound_cache.at(sound) &&
channel != -1) channel != -1)
{ {
return; return;
@ -64,25 +72,30 @@ void SoundManager::playSound(GameInternal* game, std::string sound, bool canOver
Mix_HaltChannel(channel); Mix_HaltChannel(channel);
} }
if(Mix_VolumeChunk(game->assets->getSound(sound), volume) == -1) if(Mix_VolumeChunk(this_instance->sound_cache.at(sound), volume) == -1)
{ {
std::cerr << "Error adjusting volume: " << SDL_GetError() << std::endl; std::cerr << "Error adjusting volume: " << SDL_GetError() << std::endl;
} }
if (Mix_PlayChannel(channel, game->assets->getSound(sound), loops) == -1) if (Mix_PlayChannel(channel, this_instance->sound_cache.at(sound), loops) == -1)
{ {
std::cerr << "Error playing sound '" << sound << "': " << SDL_GetError() << std::endl; std::cerr << "Error playing sound " << ": " << SDL_GetError() << std::endl;
} }
} }
void SoundManager::playMusic(GameInternal* game, std::string music, int loops, int volume, int ms) void SoundManager::playMusic(BackgroundMusic music, int loops, int volume, int milliseconds)
{ {
if (!this_instance->music_cache.contains(music)) {
std::cerr << "Error playing music: music not found" << std::endl;
return;
}
if (Mix_PlayingMusic() != 0 || Mix_Fading() == Mix_Fading::MIX_FADING_IN) if (Mix_PlayingMusic() != 0 || Mix_Fading() == Mix_Fading::MIX_FADING_IN)
return; return;
if(ms > 0) if(milliseconds > 0)
{ {
Mix_FadeInMusic(game->assets->getMusic(music), loops, ms); Mix_FadeInMusic(this_instance->music_cache.at(music), loops, milliseconds);
return; return;
} }
@ -90,11 +103,6 @@ void SoundManager::playMusic(GameInternal* game, std::string music, int loops, i
{ {
std::cerr << "Error adjusting volume: " << SDL_GetError() << std::endl; std::cerr << "Error adjusting volume: " << SDL_GetError() << std::endl;
} }
if (Mix_PlayMusic(game->assets->getMusic(music), loops) == -1)
{
std::cerr << "Error playing music '" << music << "': " << SDL_GetError() << std::endl;
}
} }
void SoundManager::setSoundVolume(int volume, int channel) void SoundManager::setSoundVolume(int volume, int channel)
@ -134,3 +142,51 @@ void SoundManager::fadeOutMusic(int ms)
Mix_FadeOutMusic(ms); Mix_FadeOutMusic(ms);
} }
void SoundManager::addSingleSoundEffect(SoundEffects soundEffect, const char *path) {
if (this_instance->sound_cache.contains(soundEffect)) {
std::cerr << "Error when adding Sound-Effect: sound-effect with that key already in cache" << std::endl;
return;
}
Mix_Chunk* sound = Mix_LoadWAV(path);
if (sound == nullptr) {
std::cerr << "Error when loading Sound-Effect: could not load sound effect from " << path << std::endl;
return;
}
this_instance->sound_cache.emplace(soundEffect, sound);
}
void SoundManager::addSingleBackgroundMusic(BackgroundMusic backgroundMusic, const char *path) {
if (this_instance->music_cache.contains(backgroundMusic)) {
std::cerr << "Error when adding Sound-Effect: sound-effect with that key already in cache" << std::endl;
return;
}
Mix_Music* music = Mix_LoadMUS(path);
if (music == nullptr) {
std::cerr << "Error when loading Sound-Effect: could not load sound effect from " << path << std::endl;
return;
}
this_instance->music_cache.emplace(backgroundMusic, music);
}
void SoundManager::addSoundEffects(const std::map<SoundEffects, const char *> &effects) {
for (auto effect : effects)
addSingleSoundEffect(effect.first, effect.second);
}
void SoundManager::addBackgroundMusic(const std::map<BackgroundMusic, const char *> &backgroundMusic) {
for (auto track : backgroundMusic)
addSingleBackgroundMusic(track.first, track.second);
}
SoundManager* SoundManager::this_instance = nullptr;